Dependency Injection
What is Dependency Injection?
Martin Fowler has been characterized has having invented Dependency Injection. This is not true. I'm sure Martin is a nice guy. I know he enjoys a beer, so its very likely that we would get on well. However, dependency injection has been around for about as long as Object Oriented Programming, and as such was probably really invented back in the 60's with Simula I and all the languages that followed.
Ok, so what is Dependency Injection?
The concept is very simple:
When constructing an object - Give it the things it depends on, don't let it make them (or find them) itself.
Define dependencies using [Interfaces] - An interface can be a very high or low level abstraction, depending on where you are in your system.
Can you give me an example?
Sure. Imagine a derivatives pricing system. It takes ages and ages in order to calculate the price of some derivatives, because Monte-Carlo simulations are required in order to do the calculations.
You may want to make some kind of market on these instruments, which involves modifying the price depending on whether you are buying or selling these things.
So, here is something that could you could use.
OK, so now we have an object that does something - applies a spread to a price returned by a pricer.
As the pricer exposes its dependencies, and uses interfaces, it doesn't know whether we are using a test pricer, and/or SpreadCalculator..
Or a some other class, that loads a sophisticated c++ library.
in either case, constructing the calculator is the same:
Notice that in all cases - we use [Interfaces] and never the concrete class names. Notice also that we Never Use Impl, just give each class a natural english name that unambiguously states what it does. (See also [Naming])
Sounds hard
Finding the objects in the system can take a little bit of time.
In fact, once you get the hang of it, creating simple objects is much easier!
Applying it to bigger systems
By choosing appropriate interfaces into the system it just becomes a case of providing higher and higher level abstractions - for each of which one or other implementation can be picked.