Dependency Injection Inversion
Posted by Uncle Bob on 01/17/2010
Dependency Injection is all the rage. There are several frameworks that will help you inject dependencies into your system. Some use XML (God help us) to specify those dependencies. Others use simple statements in code. In either case, the goal of these frameworks is to help you create instances without having to resort to new or Factories.
I think these frameworks are great tools. But I also think you should carefully restrict how and where you use them.
Consider, for example, this simple example using Google’s Guice framework.
public class BillingApplication { public static void main(String[] args) { Injector injector = Guice.createInjector(new BillingModule()); BillingService billingService = injector.getInstance(BillingService.class); billingService.processCharge(2034, "Bob"); } }
My goal is to create an instance of BillingService. To do this, I first get an Injector from Guice. Then I use the injector to get an instance of my BillingService class. What’s so great about this? Well, take a look at the constructor of the BillingService class.
class BillingService { private CreditCardProcessor processor; private TransactionLog transactionLog; @Inject BillingService(CreditCardProcessor processor, TransactionLog transactionLog) { this.processor = processor; this.transactionLog = transactionLog; } public void processCharge(int amount, String id) { boolean approval = processor.approve(amount, id); transactionLog.log( String.format("Transaction by %s for %d %s", id, amount, approvalCode(approval))); } private String approvalCode(boolean approval) { return approval?"approved":"denied"; } }
Oh ho! The BillingService constructor requires two arguments! A CreditCardProcessor and a TransactionLog. How was the main program able to create an instance of BillingService without those two arguments? That’s the magic of Guice (and of all Dependency Injection frameworks). Guice knows that the BillingService needs those two arguments, and it knows how to create them. Did you see that funky @Inject attribute above the constructor? That’s how it got connected into Guice.
And here’s the magic module that tells Guice how to create the arguments for the BillingService
public class BillingModule extends AbstractModule { protected void configure() { bind(TransactionLog.class).to(DatabaseTransactionLog.class); bind(CreditCardProcessor.class).to(MyCreditCardProcessor.class); } }
Clever these Google-folk! The two bind functions tell Guice that whenever we need an instance of a TransactionLog it should use an instance of DatabaseTransactionLog. Whenever it needs a CreditCardProcessor it should use an instance of MyCreditCardProcessor.
Isn’t that cool! Now you don’t have to build factories. You don’t have to use new. You just tell Guice how to map interfaces to implementations, and which constructors to inject those implementations in to, and then call Injector.getInstance(SomeClass.class); and voila! You have your instance automatically constructed for you. Cool.
Well, yes it’s cool. On the other hand, consider this code:
public class BillingApplicationNoGuice { public static void main(String[] args) { CreditCardProcessor cp = new MyCreditCardProcessor(); TransactionLog tl = new DatabaseTransactionLog(); BillingService bs = new BillingService(cp, tl); bs.processCharge(9000, "Bob"); } }
Why is this worse? It seems to me it’s better.
But Uncle Bob, you’ve violated DIP by creating concrete instances!
True, but you have to mention concrete instances somewhere. main seems like a perfectly good place for that. Indeed, it seems better than hiding the concrete references in BillingModule.
I don’t want a bunch of secret modules with bind calls scattered all around my code. I don’t want to have to hunt for the particular bind call for the Zapple interface when I’m looking at some module. I want to know where all the instances are created.
But Uncle Bob, You’d know where they are because this is a Guice application.
I don’t want to write a Guice application. Guice is a framework, and I don’t want framework code smeared all through my application. I want to keep frameworks nicely decoupled and at arms-length from the main body of my code. I don’t want to have @Inject attributes everywhere and bind calls hidden under rocks.
But Uncle Bob, What if I want to get an instance of BillingService from deep in the bowels of my application? With Guice I can just say injector.getInstance(BillingService.class);.
True, but I don’t want to have createInstance calls scattered all through my code. I don’t want Guice to be poured all over my app. I want my app to be clean, not soaked in Guice.
But Uncle Bob, That means I have to use new or factories, or pass globals around.
You think the injector is not a global? You think BillingService.class is not a global? There will always be globals to deal with. You can’t write systems without them. You just need to manage them nicely.
And, no, I don’t have to use new everywhere, and I don’t need factories. I can do something as simple as:
public class BillingApplicationNoGuice { public static void main(String[] args) { CreditCardProcessor cp = new MyCreditCardProcessor(); TransactionLog tl = new DatabaseTransactionLog(); BillingService.instance = new BillingService(cp, tl); // Deep in the bowels of my system. BillingService.instance.processCharge(9000, "Bob"); } }
But Uncle Bob, what if you want to create many instances of BillingService rather than just that one singleton?
Then I’d use a factory, like so:
public class BillingApplication { public static void main(String[] args) { Injector injector = Guice.createInjector(new BillingModule()); BillingService.factory = new BillingServiceFactory(injector); // Deep in the bowels of my code. BillingService billingService = BillingService.factory.make(); billingService.processCharge(2034, "Bob"); } }
But Uncle Bob, I thought the whole idea was to avoid factories!
Hardly. After all, Guice is just a big factory. But you didn’t let me finish. Did you notice that I passed the Guice injector into the factory? Here’s the factory implementation.
public class BillingServiceFactory extends AbstractModule { private Injector injector; public BillingServiceFactory(Injector injector) { this.injector = injector; } protected void configure() { bind(TransactionLog.class).to(DatabaseTransactionLog.class); bind(CreditCardProcessor.class).to(MyCreditCardProcessor.class); } public BillingService make() { return injector.getInstance(BillingService.class); } }
I like this because now all the Guice is in one well understood place. I don’t have Guice all over my application. Rather, I’ve got factories that contain the Guice. Guicey factories that keep the Guice from being smeared all through my application.
What’s more, if I wanted to replace Guice with some other DI framework, I know exactly what classes would need to change, and how to change them. So I’ve kept Guice uncoupled from my application.
Indeed, using this form allows me to defer using Guice until I think it’s necessary. I can just build the factories the good old GOF way until the need to externalize dependencies emerges.
But Uncle Bob, don’t you think Dependency Injection is a good thing?
Of course I do. Dependency Injection is just a special case of Dependency Inversion. I think Dependency Inversion is so important that I want to invert the dependencies on Guice! I don’t want lots of concrete Guice dependencies scattered through my code.
BTW, did you notice that I was using Dependency Injection even when I wasn’t using Guice at all? This is nice and simple manual dependency injection. Here’s that code again in case you don’t want to look back:
public class BillingApplicationNoGuice { public static void main(String[] args) { CreditCardProcessor cp = new MyCreditCardProcessor(); TransactionLog tl = new DatabaseTransactionLog(); BillingService bs = new BillingService(cp, tl); bs.processCharge(9000, "Bob"); } }
Dependency Injection doesn’t require a framework; it just requires that you invert your dependencies and then construct and pass your arguments to deeper layers. Consider, for example, that the following test works just fine in all the cases above. It does not rely on Guice, it only relies on the fact that dependencies were inverted and can be injected into BillingService
public class BillingServiceTest { private LogSpy log; @Before public void setup() { log = new LogSpy(); } @Test public void approval() throws Exception { BillingService bs = new BillingService(new Approver(), log); bs.processCharge(9000, "Bob"); assertEquals("Transaction by Bob for 9000 approved", log.getLogged()); } @Test public void denial() throws Exception { BillingService bs = new BillingService(new Denier(), log); bs.processCharge(9000, "Bob"); assertEquals("Transaction by Bob for 9000 denied", log.getLogged()); } } class Approver implements CreditCardProcessor { public boolean approve(int amount, String id) { return true; } } class Denier implements CreditCardProcessor { public boolean approve(int amount, String id) { return false; } } class LogSpy implements TransactionLog { private String logged; public void log(String s) { logged = s; } public String getLogged() { return logged; } }
Also notice that I rolled my own Test Doubles (we used to call them mocks, but we’re not allowed to anymore.) It would have been tragic to use a mocking framework for such a simple set of tests.
Most of the time the best kind of Dependency Injection to use, is the manual kind. Externalized dependency injection of the kind that Guice provides is appropriate for those classes that you know will be extension points for your system.
But for classes that aren’t obvious extension points, you will simply know the concrete type you need, and can create it at a relatively high level and inject it down as an interface to the lower levels. If, one day, you find that you need to externalize that dependency, it’ll be easy because you’ve already inverted and injected it.
Comments
Ben 41 minutes later:
Of course Guice looks like overkill for and example with 2 dependencies and a single scope/lifetime. What happens if some of the dependencies need be created per HttpRequest, some are created new each time and some are singletons? Are you going to write a factory for each scope?
Mark Seemann about 1 hour later:
Fortunately, I hardly consider this post controversial. In my book, DI is simply a set of patterns and principles that describe how we can write loosely coupled code. These include the GoF principle of programming to interfaces, as well as patterns such as Constructor Injection.
DI simply describes how you organize classes and turn their dependencies into invariants.
How you decide to wire up those dependencies in the end are much less important. You can use Poor Man’s DI (as you show in one of your Main examples), or you can use a DI Container (in .NET, most DI Containers don’t require you to put attributes or other explicit things in the code to work).
The Hollywood Principle is very applicable to DI: Don’t call the DI Container, it’ll call you.
The best approach is to let the container wire up the desired object graph in the application’s entry point and then get out of the way. I call this place the Composition Root.
The idea is to keep the application code completely Container-agnostic.
In summary, I agree :)
Sam Newman about 1 hour later:
Yeah – my view on IOC/DI for years has been that using a DI framework is something I consider down the line, but my starting point is wiring by hand.
BTW, I would not consider creating concrete instances to be a violation of DIP (not that I would care about it violating some rule anyway if I thought that it was the right solution) – not when the instances are then just being provided to the class that will use them.
Like the previous commentator, I do find DI frameworks useful for things like lifecycle management (even then their not essential), and for the fact that they can remove the need for some boiler-plate wiring code.
Personally, I prefer Pico to Guice – why on earth did they think @inject was a good idea when a class only has one constructor?
Geir about 1 hour later:
You just tell Guice how to map interfaces to implementations, and which constructors to inject those implementations in to, and then call Injector.getInstance(SomeClass.class);
Can I suggest changing the example code to Injector.getInstance(SomeInterface.class) in your post? I have had to spend hours with some people explaining how DI gets you from an interface to an implementation, and the process seemed easier when I clearly separated what was interfaces and implementations in my examples.
Personally, I really like the annotations used by Spring. I can declare a class to be a service by annotating the class with a @Service annotation. The service gets injected in a similar manner to what you show with Guice.
The only explicit configuration I need to do outside of my services is where I have multiple service implementations around, which I wouldn’t usually have. I really like this because it mostly does away with the need of having wiring of dependencies in a separate entity – main methods or xml files. All configuration is local to the service or the consumer of the service – and it is possible to make tooling that lets you move from one to the other.
Gil Zilberfeld about 1 hour later:
I like how you managed to put all the Guice stuff inside a factory. I do expect, though, that in a real application, with multiple factories for different object, it would become a bit messy. But it’s concentrated mess.
I have to ask – when do you consider moving from hand written test doubles to a framework? And where in a TDD process would you decide that?
Gil Zilberfeld
Typemock
Neil Mosafi about 1 hour later:
The only place that should have reference to the container should be the bootstrapping code (main in your case). I would not use any container that requires otherwise.
Sven Efftinge about 2 hours later:
Yes, an injector is a factory, but it will usually only be called once per application. The rest is wired and has no dependency to the injector. No serious Guice user will use the injector directly in order to obtain some object.
The problem is not the factory or the new operator but the static dependency. You should know that as a TDD friend.
And, yes , you can’t get rid of globals completely, but you can get rid of many dependencies to them. Stating that one should give up on removing them, because you can’t get rid of them completely is IMHO very questionable.
Darren Gilroy about 2 hours later:
But Uncle Bob, what if CreditCardProcessor has two dependencies, and DatabaseTransactionLog has two dependencies, and each of those has two dependencies… (Remember the Faberge Shampoo commercial?)
You suggest we can create instances at a relatively high level and inject them down as an interfaces to the lower levels, but I contend that as the graph gets larger that quickly becomes unwieldy.
The point of Guice (and similar tools) is not to avoid factories, instead it fills the role of one-big-factory so you don’t have to. From my perspective, Guice exactly supports the role/spirit/purpose of GOF factories, just with less ceremony.
Uri Goldstein about 2 hours later:
Hi Uncle Bob,
As much as I appreciate your thoroughness, wasn’t this post a bit too long? :)
To the point – The way you’re using DI here really is quote awful – just like you say yourself. DI should be used more carefully and with component oriented programming in mind.
One of the most important principles is to decouple the application from the specific DI container. Your classes need to be “DI free” in that no special attributes are present and no direct calls are made to DI container instances.
Ideally IMHO, the container really should only be used only on bootstrapping to initially weave the components together.
You can have both the flexibility of DI with only a minimal impact on code readability and maintain independence from tightly coupled containers and their meta data.
Jason Snelders about 3 hours later:
Uncle Bob, thanks for the wonderful post. I don’t always agree with what you have to say (and that’s a good thing) but this one I thin hit the nail succinctly and elegantly on the head.
Derek Greer about 6 hours later:
Thanks for the post Uncle Bob. While I appreciate your desire for simplicity by minimizing your reliance on DI and mocking frameworks, the example set forth here falls short in highlighting either the real benefits or faults of DI containers (I know, you said you hate the name container, but that’s what everyone calls them so if you are going to say fake vs. mock because of that then …).
One issue in this example is in your presumption of how DI frameworks are generally used. I think it’s important to draw a distinction between Dependency Injection and the Service Locator pattern here. Dependency Injection is the process of separating the concerns of acquiring dependencies from an object, while the Service Locator pattern merely provides a layer of indirection for acquiring dependencies (not necessarily performing any injection on the object being obtained). While I’ve found that newcomers do tend to gravitate toward using containers directly as a service locator, the container should generally only ever be referenced in an application’s bootstrapping related components, or at most in module or application level controllers. An application can generally be designed to have all dependencies resolved through the container with minimal infrastructure coupling to the actual DI framework.
Another issue is that your example only demonstrates dependency injection with a two-level object graft. It fails to highlight the strengths of a DI container with more typical scenarios, or the weaknesses of the manual approach you advocated.
Dean Wampler about 8 hours later:
For most needs, I now use Scala’s “self types” and traits to accomplish the goals of DI/IoC using Scala code itself, rather than a separate framework:
http://programming-scala.labs.oreilly.com/ch13.html#DependencyInjectionInScala
Esko Luontola about 8 hours later:
“I have to ask – when do you consider moving from hand written test doubles to a framework? And where in a TDD process would you decide that?”
In my case, the point where I started using Guice the first time was when it was time to implement a request scope in the application. Implementing scopes with hand-written factories would have been very complicated, but with Guice it was easy. At that point the project had about 2000 SLOC production code (77 .java files) and 3000 SLOC test code. Creating a custom request scope (and the application’s subsystem which is based on scopes), annotating existing classes with @Inject and writing the Guice modules took in total 4 hours.
This experience showed me that manual DI can get you quite far, and then when the dependencies get complex enough or you need some other features of a DI container, adding a DI container to the project is quick and easy.
“No serious Guice user will use the injector directly in order to obtain some object.”
True, unless you need to inject instances which are created by some other system. I’ve had one situation where the Injector had to be used directly: some Java objects are deserialized from a database and they need to have some runtime dependencies injected. This means that when the objects are deserialized, they are passed to Injector.injectMembers() – that is done by a tiny class that does nothing else than hold the injector and is completely decoupled from the rest of the application.
And even in that case the use of Injector could have been avoided by hard coding that which class requires which dependency (there are only one or two classes which require this special handling), although using the Injector keeps the system more decoupled (if the injectMembers() call proves to be slow, then hard coding it is a potential performance optimization).
“You think the injector is not a global?”
You can have multiple injectors in the same JVM, even within the same application, and they will not know anything about each other – if the application is structured well, they will not even be able to get access to each other even if they tried. When an injector is not anymore used, it will be garbage collected from the memory.
The injector is not a global variable, unlike the horrible mutable static BillingService.instance/factory field. (Such fields are usually needed only temporarily, when incrementally refactoring a large Service Locator based application to use DI.)
Like others have said, a DI example with just 3 classes can not be used to discuss the pros and cons of manual DI vs. container-assisted DI. You’ll need an example (a real application) with tens or hundreds of classes to discuss the benefits of container-assisted DI.
Jesse Wilson about 13 hours later:
Yes, it is possible to do DI by hand. And in small applications, the amount of code required to construct objects is comparable. But for multiple-developer applications, you’ll write less code if you use a framework.
Before you abandon Guice, consider a few things that your post has overlooked…
Lazy initialization via Providers. Wherever you want you can defer initialization of a dependency by injecting a Provider rather than a Foo. Doing this with by-hand DI is possible, but your code size will blow up significantly. Particularly since you’ll need to rewrite every path that uses a given dependency.
HTTP sessions and request scoping. Without a framework, working with session objects is ugly. You need to think about concurrency, mapping keys to values, and casting. Guice takes care of all of this for you with just an annotation: @SessionScoped.
Modularity. You can reuse Guice modules across applications. The module is a unit of encapsulation, and no single piece of code needs to know the implementation classes of multiple modules.
J. B. Rainsberger about 14 hours later:
Holy shit, Bob, is this what you see actual programmers doing? They’re inverting the dependencies, all right, but apparently for fun and not for profit.
As I understand the DIP, we benefit from pushing the decisions about which implementations to choose for our interfaces up towards the entry point. At the entry point, we make as many of those decisions as possible, creating a graph of loosely-coupled objects that request services primarily through abstractions. Then we invoke go() and magic happens. As I teach design, our goal is to wrangle all those pesky “new” calls into a single place, so we no longer need crazy things like Singletons and the only Factories we need are Abstract Factories, which have a real purpose, rather than just confusing people learning how to depend on more abstractions.
I might just have to riff on this later. Thanks.
Pablo about 16 hours later:
Interesting. Your point is that by overusing DI frameworks, we are creating an application that has a heavy dependency on them, which we need to invert.
I like the idea of using the factory to encapsulate the framework, very interesting post.
Indrit Selimi about 16 hours later:
Yes, Guice is framework…yet an elegant and rigorous Dependency Injector implementor. The problem is that too many people confuses the dependency injection paradigm with the framework of the moment, too many people thinks that Pico, Guice, Spring and DI are the same thing… Manual DI is perfect for small projects!
An injector is automation tool for wiring dependencies and in the case of Guice this is done rigorously following the DI concepts (key, scope,... etc); I see no problem with this approach.
- “I don’t want a bunch of secret modules with bind calls scattered all around my code” There are no secrets, simply there is a “declarative way” wiring implementor without using an external language like xml and having a compile time check capability. Probably only in the “main” method the dependency are “hidden”, in the rest of the code the Dependency Inversion Principle predominates. Said that , I will add that the Guice module code is part of the production code so everybody must know in which way the dependencies are wired (in the same way if the wiring was done by hand in a “application factory”).
- “I don’t want to write a Guice application.” Nor do I, who said that having some annotations (dependency keys) on my code that means that is automatically a Guice Application? (I have many other type of annotations on my code…)
- You think the injector is not a global? Yes I think so, at least not in the evil sense. Remember that we are not speaking about globals on business logic… Scope is an VERY IMPORTANT dependency injection concept that Guice, Spring etc implements. (also you can have different injectors in the same application if you prefer).
- “After all, Guice is just a big factory” I think that this definition is too simplistic, it doesn’t address important DI concepts like keys, scope, lifecycle … I would add also that it is “boiler plate code”-less automatic factory.
-“if I wanted to replace Guice with some other DI framework” No problem, the classes are written in DI style mode declaring dependencies following DIP, Guice doesn’t matters.
I strongly agree that speaking of DI doesn’t mean speaking of a particular framework but everybody must study well the DI own concepts! Starting to write DI by hand is a good starting point for understanding its concepts and some constructs used by Guice (like Provider) are very useful.
Roy van Rijn about 16 hours later:
The problem is that most JEE applications have their entry-point defined in the web.xml as servlet/filter. From that point you need a factory to retrieve your dependencies. Even if you use some web framework, you still need a factory (or DI-plugin) to get to your dependencies.
And once you need a factory its almost always easier to use a DI-framework. Because all DI-frameworks have a factory build-in, but can also wire the dependencies for you.
The other big advantage of using a DI-framework is that everybody in larger projects will manage their classes in a similair way. This will help maintainability and extendibility.
But I have to agree on the concept DI being confused with DI-frameworks. I’ve seen a lot of times, people using something like Spring or Guice without really understanding the pattern. This is very bad! I, myself, give Spring courses to collegues, and the first thing I teach them is to write their own “Spring”, their own dependency injection code.
First I present them with some unmanaged code and ask them to write a unit-test. Of course this can’t be done because the service itself creates the layers below. They don’t have a way to replace the dependencies, so no way to use stubs/mocks. After that I show them how to write/use a factory, and then I show them how to use the DI-pattern… And finally we use Spring as a generic DI-solution.
MM about 20 hours later:
- “I don’t want a bunch of secret modules with bind calls scattered all around my code.”
So don’t scatter them. Put them all one place.
- “I don’t want lots of concrete Guice dependencies scattered through my code.”
I agree with this. I first learned about DI containers in the .NET world and when I saw that Guice requires constructors to be annotated I was a bit disappointed.
John Sonmez about 23 hours later:
Some very good points. There seems to be a widespread overuse of DI frameworks to solve every problem. I am beginning to feel that we need a language solution to eliminate the problem at the source instead of trying to cure it with frameworks. Anytime I see frameworks abounding, I think language evolution.
Dave LeBlanc 1 day later:
I think I’m going to have to side with J.B. on this one – I don’t believe that this advice is really leading to a big payoff for most developers.
In particular, there’s the ‘propagation of dependencies’ antipattern (http://www.picocontainer.org/propagating-dependency-antipattern.html), which you don’t seem to show any solutions to. And I’m concerned that the non-DI container steps you would probably take to avoid that antipattern would actually be more complicated than just using a lightweight DI library. (Passing around a context object that contains common dependencies being a common approach).
Dependence on a specific DI framework – agreed, that’s not a good thing. Should we preemptively spend developer time just in case we may need to switch out our DI implementation? I don’t think so – not if I was paying for the project. I don’t abstract away from the fact that I’m using a particular GUI toolkit (or JS toolkit, etc) these days – sure I might change it, but odds are I wont, and the cost of that abstraction is very real. Truth be told, all the projects I’ve been on have just stuck with what they were using for DI stuff, and the cost to change an @Inject annotation to a synonymous approach is near-zero.
Though I think I agree with the core of your sentiments – if our POJO’s were free of DI specifics, and just loosely coupled via interface dependencies (which are resolved clearly at the top level), then that’s a good place to be. And for small projects, manual DI is almost certainly preferable.
Dean’s suggestion of the Scala way to do it is interesting – use language level features that don’t really bind you in any way, and still allow alternate implementations to be used in a test environment. But truth be told, I’ve found that guice still reads better for me (right now) in this role.
cn 1 day later:
Just a fyi.. The @Inject annotation along with a bunch of other DI related annotations have been standardized in javaee 6 (JSR-299 and JSR-330). So once we upgrade to javaee 6 (or use a DI container like Spring 3.0 which implements JSR-330) we will not have framework specific annotations (and imports) scattered all over the place.
FShehadeh 1 day later:
Thanks for the nice article; it raises some very interesting questions. I think that the key point is that we are not interested in the DI frameworks per se, but we should be interested in the basic notion of DI: objects shouldn’t know about their surroundings, and an external entity should be responsible for instantiating the objects and wiring them together. We can do this manually, but as we do this over, a pattern will eventually emerge and we will end up with some form of a framework to help us do DI. If we reach this point, then I think that is better to reuse a standard DI framework rather than rolling one of our own. At the very least, the third-party framework (be it Guice or Spring) will be familiar to more developers, and it will have more experienced developers supporting it.
One key area where flexible DI frameworks shine is where we need to have different object-wirings for different situations. For example, when running unit tests, or on a mobile device, or so on. In each of these cases, we might want different implementations to be plugged in to address the specific problem at hand, and a DI framework would provide more flexibility in doing this.
Howard Lewis Ship 1 day later:
Yes, this tiny example is worthless. I use DI extensively in Tapestry and it solves a lot of problems that Uncle Bob is glossing over.
First of all, late binding is very important when building a framework that must allow for extensions by third party libraries or by specific applications.
A DI container makes thread-safe just-in-time instantiation possible in a way that is not feasable for an ad-hoc collection of objects. Further, Tapestry IoC adds other features, such as service decoration & advice wherein different concerns of a service can be layered together.
My experience is that on any large system, DI is quite necessary (in Java, at least … higher level languages like Clojure have less need, because the language itself provides the benefits of a DI container).
Eirik Maus 1 day later:
I think we all (more or less) agree that most systems need some kind of dependency injection mechanism, or else they become a total mess.
I, however, still stick to the “xml-god-help-us”-solution, as this is the only way to ensure that the implementation classes are independent of the dependency injection framework (well, most are, at least).
I haven’t much experience with the annotation-based systems, but as far as I can tell they seem to make it very difficult to exchange dependency implementation to use for a specific test case. If find it very similar to early j2ee dependency resource lookups, which is nearly the opposite of dependency injection. The syntax is a whole lot better, though.
For systems where responsiveness or consistency in various scenarios is extremely important (and probably a lot of other cases too), you get quite some amount of tests simulating various interleavings of concurrent actions, different kinds of integration-point breakdowns etc where a specific ‘bean’ or two must be replaced in each test case in order to simulate the breakdown. Re-binding implementation classes can easily wreck the other tests in the test suite or make the execution order significant. Seems to me that the simple solution is to not have anything magically @inject’ed.
Also: dependency injection framework fashion is extremely short lived. You might want to switch.
Roy van Rijn 1 day later:
I took some time to describe how I usually teach Spring/Guice.
Like I commented before, its based on the fact that the DI-pattern is much much more important then the actual framework of choice.
You have to understand why you are using a certain pattern/framework, what problem are you in fact trying to tackle or avoid? That is the single most important thing.
You can read my tutorial/write-up here:http://www.redcode.nl/blog/2010/01/dependency-injection-dissection
Colin Decker 1 day later:
Uncle Bob, I noticed in a comment elsewhere that you thought it was funny that people were saying your example was too simple when it was straight from the Guice tutorial. There are a couple of issues with that. The Guice tutorial, as a basic introduction to how Guice is used, is naturally going to be simple. The problem with you using that example to say “look, you don’t need a DI framework!” is that Guice is considerably more powerful than the example suggests and scales very well with increasing size and needs of a system (scopes, etc.) where DI by hand does not (it requires explicit wiring of every object your system needs and provides nothing in terms of scoping, delayed instantiation, etc). In other words: in a tiny example, DI by hand looks like a perfectly acceptable solution while Guice looks unnecessary (though even in such a tiny example it doesn’t require more code than doing it by hand)... there’s a strong bias toward the frameworkless code. In a real system that will likely have considerably more dependencies and more complex dependency graphs, a framework will shine by making your code simpler and more focused and overall reducing the amount of code you have to write.
I also get the feeling that part of your motivation for this post is seeing code where a DI framework has been misused, such as injecting the Injector (where it isn’t truely needed) or, god forbid, using a static reference to it all over the place as a Service Locator. In that case I would suggest that the solution is not static references to factories or DI by hand but proper use of the framework. I do agree with you that using some kind of DI is the most important thing and I think that someone who doesn’t yet have a grasp on DI should understand DI by hand before using a framework. However, I’d prefer to see you encourage understanding and proper use of DI frameworks rather than suggesting they are largely unnecessary, as they DO provide significant benefits.
Jeffrey Palermo 1 day later:
When I read this post, I made it mandatory reading for all of my employees. Having use an IoC container for 5 years now, I have recognized the pendulum swing to abuse it by lying to ourselves by believing that is is not a global and that it in itself is not a dependency.
Late last year, I made an architectural move across the company to officially decouple ourselves from our IoC container (StructureMap). there were too many code files throughout the application calling it’s API directly.
We have now (in some projects) isolated it to a single startup project. These projects configure the specific factories we need as well as wire in extensibility points.
I now consider it just as heinous a dependency as NHibernate or the UI toolkit in play. Our core project (the one with the most code) should not have anything to do with concrete dependencies.
Thanks for the good post.
Kees Overboom 1 day later:
BillingModule and BillingServiceFactory both extend AbstractModule and do the same binding. Is this necessary to make things work? To me this seems a violation of SRP.
Morten 2 days later:
Ok, so you have the “we need an abstraction layer, just in case we want to replace X” argument. Have anyone ever heard this actually being followed up a year later by; “good thing we created that abstraction layer, now we can change X for Y”??
Gal Ratner 2 days later:
I think the key to this post was “I think these frameworks are great tools. But I also think you should carefully restrict how and where you use them.”
I personally find they help me think clearly on how to design my modules. I have my own factory based framework, and yes, I prefer XML configuration, simply because of the added behavioral attributes and the fact that they save me from any specific code tags such as @Inject.
I think this post is probably aimed more at Google’s Guice framework and less at DI in general.
Jeffrey Palermo 2 days later:
Here is an extension of this post with my opinion added.
SeeR 3 days later:
How about use of generics as a DI. No framework required.
http://seermindflow.blogspot.com/2009/07/c-generics-free-but-ugly-dependency.html
Eirik Maus 3 days later:
@SeeR: The problem is that you are still doing dependency lookup instead of dependency injection. Using XML for configuration setup is not elegant, but at least it keeps configuring the services separate from the application logic. And IDEs provide the same level of coding support as they do for java these days, so it is in fact not more error prone anymore.
The key to easily testable classes is to never mix configuration/setup with use. That is what this blog article is all about, as far as I can tell. If you need references to the DI framework inside the code, you are not keeping these apart. The result is easily a messy web of dependencies where it is not easy (/possible) to change any relationships for simple tests or for future program modifications.
If you do dependency resolution in java code, you need to keep a strong focus on you coding style to prevent configuration code from sneaking into the init-validation or business logic code.
The reason I still stick to XML is that it is not a programming language, making such mistakes impossible. That way you can always create code such as in this blog article, knowing that no service will ever try to “request” any “service” from the “environment” while it is running. The dependencies are injected before you run any program logic.
Okay, sometimes framework- or infrastructure code do need to request other stuff at runtime, but since it requires additional effort to do this, it will be the exception, not the norm.
Gavin Bong 3 days later:
Why are people so afraid of annotations ? i.e. @Inject
Although in Guice’s case, I would prefer that Guice specific annotations be shipped as a separate jar dependency (from framework code).
Kees Overboom 3 days later:
Off course I mean DRY instead of SRP. Sorry about that.
Paulo Silveira 3 days later:
Your solution seems not more decoupled than using Guice from outside the factory: if you need to change the DI framework (which is much more improbable than the need to change a component implementation) you will need to change every single factory.
Having an @Inject annotation is not coupling! If you remove the framework, you dont need to remove the annotation.
Also, for your simple example, wiring by hand is a perfect choice. Now, if you have lots of objects with different lifecycles and instantiation policies, you will have a lot of code just to tackle this. I think this is waht you mean with “externalized dependency injection of the kind that Guice provides is appropriate for those classes that you know will be extension points for your system.”, but I would say not only extension points, but also expesive objects that require some lifecycle attention (Hibernate Sessions, Http Sessions, Files, Threads, Connections and so on)
Eliud 3 days later:
Why not enable feed (RSS) on you blog. It would be nice.
Greetings!
freddy rios 4 days later:
I generally agree with your posts, but not on this one.
MM already mentioned 2 of the assumptions/generalizations taken on this post:
—-—-—-—-—-
- “I don’t want a bunch of secret modules with bind calls scattered all around my code.”
So don’t scatter them. Put them all one place.
- “I don’t want lots of concrete Guice dependencies scattered through my code.”
I agree with this. I first learned about DI containers in the .NET world and when I saw that Guice requires constructors to be annotated I was a bit disappointed.
—-—-—-
In my case I’ve been using StructureMap in .net, and I don’t need any attributes/annotations on the classes. Pretty much all the dependencies are configured in a single place, so there is no issue involved with that.
Only a single time I had a situation where I needed to get an instance from elsewhere in the code. Although I did made a factory to make more explicit the code into the DI container, I don’t think going without is an issue to change containers – take out the reference to the DI container, compile & u get the 0-3 lines of code that referenced it (besides the one in the main registration code of course).
Fred 5 days later:
I think this post is a little misleading and leaves out the most importend things about IoC. Reading Ayende’s answer to it should make this clear:
http://ayende.com/Blog/archive/2010/01/22/rejecting-dependency-injection-inversion.aspx
MikeHoss 5 days later:
I posted my response here but the short answer is: it’s about knowing what you are getting into before you start, and the costs you may incur for your decisions when you start.
shane kercheval 5 days later:
I have two major concerns with this post. First. To say that “the goal of these frameworks is to help you create instances without having to resort to new or Factories”, in my opinion, is not at all what dependency injection is about at all. Dependency injection is about, as its name suggests, removing dependencies from your code, decoupling your code, making it more maintainable, and TESTABLE, among other things. The second concern i had was your examples didn’t show why someone would ever use DI. As you stated “My goal is to create an instance of BillingService.” While i agree that you shouldn’t use something just because its cool or everyone is talking about it, or without reason, I just really feel like your example missed the point.
And i wasn’t sure why you were suggesting to use instances or factories?
BillingService.factory = new BillingServiceFactory(injector);
// Deep in the bowels of my code. BillingService billingService = BillingService.factory.make();
??
The goal is NOT to stop or reduce using new (although it is a side effect of the pattern but not the purpose), and you dont have to use singletons or factories, which i extremely dislike that solution because you are changing the way you design/implement your classes because you use a IOC container, which i think is bad. Not only that but are you really going to make a factory for each class that you want to use DI with? no. The point is to reduce dependencies between concrete classes and program to an interface. So if you dont want Guice all over your code, which i wouldn’t want either because that creates a dependency which is the opposite of what we are trying to do, so what i would do is create a wrapper for Guice that way the application would not depend on that framework and it can be swapped out with any other framework. Now you dont have factories, instances everywhere and you are not tied to a DI framework.
Svein Arne Ackenhausen 7 days later:
Brilliant post! It created enough of a stir for people to post replies on their blogs leading to valuable insight into various frameworks. Now my DI framework usage is clean, simple and does wonders. Thanks, it really made my day!
Mark Seemann 8 days later:
After having re-read this post carefully, I think this particular piece of guidance is redundant in .NET.
Eelco Hillenius 8 days later:
Not my experience at all. I’ve gone full circle in first not buying into the DI hype and doing everything manually much like you describe, to using Guice as an important part of our architecture. For a long time I thought DI was an example of YAGNI, and I still feel this way when looking at e.g. Spring’s XML configuration, but since adopting Guice, our code got a lot cleaner and easier to configure.
Manually constructing object graphs like you suggest here works fine for small-ish projects but easily gets out of hand in larger ones, particularly if such projects are broken up in multiple projects/ modules/ libraries. Modules provide an excellent mechanism to hide complexities of how such libraries are composed. You could achieve the same by providing builders and such, but then you’d be handwriting what a DI framework already provides. Also, @ImplementedBy and lazy binding provide an excellent way of reducing dumb setup code; in my experience, an composition of a module system uses defaults maybe 70 or 80 % of the time, so your bootstrapping code only has to configure composition for a relatively small number of cases.
> There will always be globals to deal with. You can’t write systems without them
I don’t agree with that. In fact, I am working on a system right now that has no globals to speak of. It requires discipline because it is often easier to rely on globals, but over the years I’ve learned – as many in our industry – that relying on global behavior almost always backfires, and like it is worth the extra effort to think your abstractions through, it is worth the effort of trying to keep the globals down.
Craig McClanahan 9 days later:
> Ok, so you have the “we need an abstraction layer, just in case we want to replace X” argument. Have anyone ever heard this actually being followed up a year later by; “good thing we created that abstraction layer, now we can change X for Y”??
At my new digs (Jive Software), this exact capabity enables us to satisfy unique customer requirements on essentially every install. All the DAOs, managers, etc. are DI injected (currently based on Spring 2.5, would personally prefer @Inject style, we’ll see how long it takes to encourage the other developers in this direction :-), with an ability to install a “plugin” that overrides the default injected resources for any or all of the standard implementations. This is critically important in at least a couple of important use cases:
Customer wants to add functionality to an “off the shelf” capability.
Professional Services needs to tune the standard functionality of a particular capability, to deal with the fact that a particular customer has billions of records, instead of thousands of records, of this particular type.
In a COTS world, anyone who thinks they know the only abstraction points where a customer might want to change things is pretty naive.
Mike 9 days later:
I thought you were being crazy until I read through half-way, and then I realised I had the same problem using IoC containers, they were all-over the place.
Good lesson, thanks!
Bob Lee 9 days later:
Uncle Bob,
You should take a closer look at Guice and DI in general.
1) In a typical Guice application, you only use Injector in one place—at your applications entry point. Using Injector elsewhere is equivalent to using reflection. Injector is like ClassLoader, another class I hope you don’t use everywhere.
2) To answer your question, no, the injector is not global, nor is the binding to BillingService.class. See private modules. You can easily bind BillingService to different implementations in different parts of your app.
3) You suggested that “TransactionLog tl = new DatabaseTransactionLog()” is preferable to “bind(TransactionLog.class).to(DatabaseTransactionLog.class)”. What happens when you need to inject TransactionLog into a 2nd constructor? You have to type “TransactionLog tl = new DatabaseTransactionLog()” again. With Guice, you do nothing. What happens when you use TransactionLog in 100 places? You type “TransactionLog tl = new DatabaseTransactionLog()” 100 times in 100 different factories. With Guice, you only write one bind statement. Your approach scales O(N). Guice scales O(1). Perhaps you didn’t realize it because N=1 in your example.
Further, if TransactionLog is a concrete injectable class to begin with, you don’t even need a bind() statement. If you decide to replace it with an interface later, you can do so without touching the 100 injection points. Can you do that with your approach?
4) If you don’t use javax.inject.Inject in your code simply because you don’t “want framework code smeared all through [your] application,” you’re making a pretty painful tradeoff.
5) Static fields are notoriously bad for unit testing. We walk you through examples of why in just about all of our Guice videos.
Bob
Donnie 14 days later:
Hah,that was really funny. I even ordered an essay paper on it.These online essay writers made an excellent essay for me.
Derek Smyth 18 days later:
I’ve never really used a dependency injection framework in a project for exactly the reasons mentioned. I’ve experimented with a few frameworks and most of them (if not all of them), by their design or by my mistake, added some level of noise and misdirection to the code.
Just didn’t seem worth it, the additional noise.
Really glad this was posted as I wondered whether I was really doing DI even though it felt like it.
Ok some people will argue I am still not doing DI properly, and maybe a situation will arise when I’ll reach for a framework, sure ok I’m easy… but all my code is testable and it’s obvious where and why concrete classes are created; don’t need a framework.
Omar Gomez 25 days later:
Your point seems to be that you should not use dependency inversion frameworks to make simplistic samples like the one above. A good frame work support many other things like aspects, and transaction handling (to name just two). I want to see how you refactor your code to support that.
—Omar