When to Use Dependency Injection
A great question from a reader...
The only thing that does not fully convince me in your articles is usage of Guice. I’m currently unable to see clearly its advantages over plain factories, crafted by hand. Do you recommend using of Guice in every single case? I strongly suspect, there are cases, where hand-crafted factories make a better fit than Guice. Could you comment on that (possibly at your website)?
I think this is multi-part question:
- Should I be using dependency-injection?
- Should I be using manual dependency-injection or automatic dependency-injection framework?
- Which automatic dependency-injection framework should I use?
Should I be using dependency-injection?
The answer to this question should be a resounding yes! We covered this many times how to think about the new-operator, singletons are liars, and of course the talk on dependency-injection.
Dependency injection is simply a good idea and it helps with: testability; maintenance; and bringing new people up to speed on new code-base. Dependency-injection helps you with writing good software whether it is a small project of one or large project with a team of collaborators.
Should I be using manual dependency-injection or automatic dependency-injection framework?
Whether or not to use a framework for dependency injection depends a lot on your preferences and the size of your project. You don’t get any additional magical powers by using a framework. I personally like to use frameworks on medium to large projects but stick to manual DI with small projects. Here are some arguments both ways to help you make a decision.
In favor of manual DI:
- Simple: Nothing to learn, no dependencies.
- No reflection magic: In IDE it is easy to find out who calls the constructors.
- Even developers who do not understand DI can follow and contribute to projects.
In favor of automatic DI framework:
- Consistency: On a large team a lot can be said in doing things in consistent manner. Frameworks help a lot here.
- Declarative: The wiring, scopes and rules of instantiation are declarative. This makes it easier to understand how the application is wired together and easier to change.
- Less typing: No need to create the factory classes by hand.
- Helps with end-to-end tests: For end-to-end tests we often need to replace key components of the application with fake implementations, an automated framework can be of great help.
Which automatic dependency-injection framework should I use?
There are three main DI frameworks which I am aware off: GUICE, Pico Container and Spring.
I work for Google, I have used GUICE extensively therefor my default recommendation will be GUICE.
However I am going to attempt to be objective about the differences. Keep in mind that I have not actually used the other ones on real projects.
Spring was first. As a result it goes far beyond DI and has everything and kitchen sink integrated into it which is very impressive. The DI part of Spring has some differences worth pointing out. Unlike GUICE or Pico, Spring uses XML files for configuration. Both are declarative but GUICE is compiled and as a result GUICE can take advantage of compiler type safety and generics, which I think is a great plus for GUICE.
Historically, Spring started with setter injection. Pico introduced constructor injection. Today, all frameworks can do both setter and constructor injection, but the developers using these frameworks still have their preferences. GUICE and Pico strongly prefer constructor injection while Spring is in the setter injection camp. I prefer constructor injection but the reasons are better left for another post.
Personally, I think all of the three have been around for a while and have proven themselves extensively, so no matter which one you chose you will benefit greatly from your decision. All three frameworks have been heavily influenced by each other and on a macro level are very similar.
(I personally would not chose Spring because XML and setter injection puts me off. However I am looking forward to using Pico on my next open-source project so that i can become more objective about the differences.)
Your milage may vary.
- Login or register to post comments
- 9268 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)




Comments
Dinh Pham Cong replied on Thu, 2009/01/15 - 3:55am
Cristian Vasile... replied on Thu, 2009/01/15 - 5:07am
I think there is another question concerning dependency injection: where should we use it?
There are some possibilities:
- use everywhere to wire ALL collaborators - I'm leaning to believe this is the answer and ease of testing comes to mind
- use it to wire only parts of the application. If so, which parts? Only services?
I think this kind of information is sorely missing from an article named "When to Use Dependency Injection".
Thank you,
Cristian Vasile Mocanu
Kristian Marinkovic replied on Thu, 2009/01/15 - 5:40am
have you looked at Tapestry 5 IOC; it shares quite a lot of ideas with Guice:
- no XML, everything is Java (Module classes)
- also prefers constructor injection (setter injection has to be done manually)
- 5.1. also supports field injections (as Guice does)
some sweet spots from my point of view:
- service decoration possibilities
- contributions
- any service with any scope (lifecycle=threaded, singelton) can inject any other service with any scope
g,
kris
Zviki Cohen replied on Thu, 2009/01/15 - 7:49am
The use of the term "manual/automatic dependency-injection" is a bit problematic. In Spring there is an auto-wiring option unlike the regular wiring, driven from configuration. I think the distiction should be between "hard-coded DI" or "static DI" and "configurable DI" or "dynamic DI".
Just for the record, the Spring Auto-wiring option is even more magical, which makes it even harder to predict (it'n not impossible, it's just requires more effort) and, thus, I wouldn't recommend using it de-facto.
Other than that, I think the major drawback of DI frameworks is the readability of the code. There are great tools for assisting in following code (like presenting a call hierarchy), but they stop when the DI starts. I'm working to improve that situation, so stay tuned :-). Another problem with DI is Java Classpath hell, which becomes more intense when classs are referenced dynamically from different JARs.
I think you missed some of the key advantages, which is extendability, maintainability and better code reusability. It's becoming too much for a simple comment, I will blog about it soon.
PS. Many (most?) tools implement their own DIs (e.g. take Log4J configuration files... classic...). It's high time people stop inventing wheels :-)
Jakob Jenkov replied on Thu, 2009/01/15 - 9:44am
I wrote a short article some time ago about when (and when not) to use dependency injection. This article talks more about in what situations it makes sense to use DI, and in what situations it doesn't.
You can find it here:
http://tutorials.jenkov.com/dependency-injection/when-to-use-dependency-injection.html
Constructor or setter injection... a good framework should allow you to do both. One problem that neither of above frameworks solve (as far as i know) is injecting into "add'ers"... methods called "add" instead of set. Spring can't do it with it's XML. Can Guice or Pico? It may seam like a little thing, but totally annoying when using DI to wire up Swing apps. Or, if you do not want an internal List exposed, but want to be able to add elements to it. getList().add(injectedObject) would be a nice thing to be able to do.
A comment on Spring... Spring's XML may feel clumsy, but Spring also comes with a Groovy builder (config via Groovy script), and it also comes with an annotation based configuration mechanism. This annotation based mechanism does not work the same way Guice's does, and frankly, I like Spring's way of using annotations better. It keeps the annotations in separate DI configuration code, rather than splattering your application with @Inject...
I have also developed a DI container, Butterfly Container, which can all *any* method during object configuration, and not just constructors or setters. Static methods included. It also has several minor features not found in Spring. It uses a script language for configuration, or you can plug in plain no-reflection Java factories. Here it is:
http://butterfly.jenkov.com
Jordan Zimmerman replied on Thu, 2009/01/15 - 3:59pm
Liam Knox replied on Thu, 2009/01/15 - 10:44pm
[quote](I personally would not chose Spring because XML and setter injection puts me off. However I am looking forward to using Pico on my next open-source project so that i can become more objective about the differences.)[quote]
I think the setter injection is upto you. Its certainly not a Spring speciality or recomendation. Obviously constructors have the immutability and test enforcement advantages. What I will say however is the xml declaration and injection gives in my opinion a far better standardised configuration framework for use with 3rd party APIs.
Also Spring supports annotation based injection so you have that option if you choose. Spring tome provides a greater superset of functions without any mandation of usage or big downsides. Therefore I would always favor Spring over Guice especially on the systems I work on which can leverage the excellent Transaction, JMX, JUnit etc etc integration.
Peter Karich replied on Fri, 2009/01/16 - 5:50pm
Again(As Liam Knox noted): Spring is not only hookable via xml!
So maybe only size is the main difference now ... ;-)
Liam Knox replied on Fri, 2009/01/16 - 7:14pm
in response to: peathal
I've always been curious about this size argument.
What is it based on ? Are people really concerend with the classpath footprint or the API's it uses, i.e. are they trying to run Spring on JME or something mad, or application context startup, i.e. trying to use it on the Space Shuttle? ;-)
Perversley I would take Josh Blochs 80-20 law in this argument, and say that its addressses that majority of systems that require the messaging, transaction etc,etc, where a Guice does not.
Jakob Jenkov replied on Sat, 2009/01/17 - 5:49am
Size Does Matter!
Have you ever been on a project where it takes 15+ minutes just to build and redeploy your application on the application server? That means you can only do 4 changes per hour... ! I have even experienced longer build/deploy times than that. A lot of that build time comes from zipping 40-50 megabytes of *unnecessary* jar files into a .WAR og .EAR file.
By *unnecessary* I don't mean that they are not used. Just that the guys who used them were thinking like you. Size doesn't matter. But size DOES matter, if you want an agile tool suite.
Size the main reason I dislike Spring... too many JAR files bundled, and too little help selecting the ones you really need.
Apache Axis has the exact same problem. A WS stack could probably be coded pretty efficiently in a 1 MB JAR file... yet Apache Axis approaches what... 40-50 MB?
No, size does NOT matter on the disk, nor in production, but during development it DOES matter quite a lot!
Philipp dsfgsdf replied on Sun, 2009/01/18 - 7:19pm
in response to: jj83777
"Size the main reason I dislike Spring... too many JAR files bundled"
This is not correct. Basically you need one file: spring.jar. Then the other files you need depend on which Spring features you use. If you don't know which files to use in a special context then why don't you read books?
" yet Apache Axis approaches what... 40-50 MB"
Completely wrong. The size of the whole Axis distribution (including documentation) is about 7 MB and axis.jar is 1.6 MB small.
"That means you can only do 4 changes per hour... ! I have even experienced longer build/deploy times than that. A lot of that build time comes from zipping 40-50 megabytes of *unnecessary* jar files into a .WAR og .EAR file."
Well, does ist make so much sense to redeploy all jar files (even the unmodified) each time?
Liam Knox replied on Mon, 2009/01/19 - 1:26am
in response to: jj83777
You seem to take me out of context. I am completely against the big build EAR J2EE approach, and yes I have suffered massive headaches with J2EE(EJB2) in the past with build/deployment times of 15+ mins.
Lets face it this form of J2EE is shockingly bad and tobe honest I have seen nothing in later versions to compell me to take a better look.
The same issues do not manifest when using Spring in a stand alone Java application deployment. Sure they ship with a lot of jars but if your app depends already on AOP, JDBC, JMS and Transactions its not a big downside, especially compared to J2EE history.
With respect to testing I have also found no downside to running tests agaist the full jar set although I am not really working with Web apps so can not comment on that. I still dont get you 1mb - 50mb statement , I cant really see how that applies directly to testing where persumably the metric you are interested in is time?
Jakob Jenkov replied on Mon, 2009/01/19 - 4:56am
> why don't you read books?
I did. No answers. But, I'd expect the *download* page to tell me exactly what I am downloading. Not some random book.
> Well, does ist make so much sense to redeploy all jar files (even the unmodified) each time?
No. But for big projects having run for years, this is what happens (sometimes). No one remembers who created the original build script. Everybody talks about it needing to be optimized. Yet no time is allocated for it. I am talking 20-30+ developer projects. If JAR file size had been kept down, this would have been less of a problem. I see absolutely no good reason to include a 1 MB external jar file, just because you are too lazy to write the 10-20 lines of code yourself, that you need from the included jar file. It is different if you need most of what that JAR file contains. Then there is no way around. Writing it all yourself would have taken up as much space as including that JAR fie.
Another downside of size is for desktop apps. People think differently about downloading and installing a 100 MB app and a 1 MB app. You may think they don't, but they do.
Omar Qureshi replied on Thu, 2009/01/22 - 6:07pm
Franz Wong replied on Sun, 2009/01/25 - 2:56pm
I like Xml configuration (actually user like that more than me), so I am using Spring. I like lightweight too, so I want to use Guice.
However, I don't know whether Xml configuration is built-in for Guice or I have to reinvent the wheel.