Refactor Your Way to a Dependency Injection Container
The 30-second version
Invert the dependency on a Service, moving the
newstatement up one level in the call stack.1
Repeat for all dependencies on Services until the corresponding
newstatements arrive at your application’s entry point. The entry point now creates a large object graph of all your Services in its
Remove duplication in
- Instantiate common objects only once, passing them into the necessary constructors, replacing any Singletons with plain objects.
- Extract the choice of implementation for each Service interface into a lookup table mapping interface type to implementation type.
- Externalise the lookup table to a file, if you like.
Now you have a customised Dependency Injection Container for your application. To go a little farther:
Remove duplication in
EntryPoint.initialize()among three applications.
Now you have a generic Dependency Injection Container that probably provides 80% or more of the features you’ll ever need.
I recommend trying this incrementally. Think of the
new statements flowing up the call stack, into the entry point, then changing from code into data. Nice, no?
I don’t have much to add.
I hope this helps to demystify dependency injection containers. To read about the technique of injecting dependencies, I refer you to one of my articles and then a trusty web search.
This technique applies the Dependency Inversion Principle repeatedly to move the choice of implementation for an interface up the call stack. This way, concrete things depend on abstract things.
Removing duplication in the entry point respects the principle Abstractions in Code, Details in Data, but it does rely on reflection, which can cause some problems. All the better not to scatter this reflection throughout the code causing a serious cohesion problem. Using reflection like this, all in one place, helps balance using a powerful technique with a design that everyone can understand.
Now you know what about 70% of what a dependency injection container does. You can build one. Even if you don’t go that far, the Dependency Inversion Principle will help reducing coupling and highlight cohesion problems in your design. It provides another set of mechanics to practise on the way to becoming an accomplished designer.
Loose Couplings, “Dependency Injection != using a DI Container”. A handy overview of using dependency injection containers, notably a reminder that the container ought to enchance your use of dependency injection, and not interfere with it.
I mean “Service” in the Domain-Driven Design sense.↩︎