As an Agile Coach, Miško is responsible for teaching his co-workers to maintain the highest level of automated testing culture, allowing frequent releases of applications with high quality. He is very involved in Open Source community and an author of several open source projects. Recently his interest in Test Driven Developement turned into http://TestabilityExplorer.org with which he hopes will change the testing culture of the open source community. Misko is a DZone MVB and is not an employee of DZone and has posted 38 posts at DZone. You can read more from them at their website. View Full User Profile

When to Use Dependency Injection

01.15.2009
| 11371 views |
  • submit to reddit

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:

  1. Should I be using dependency-injection?
  2. Should I be using manual dependency-injection or automatic dependency-injection framework?
  3. 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.

From http://misko.hevery.com/

Published at DZone with permission of Misko Hevery, author and DZone MVB.

(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

Why do you dislike Spring and setter injection? Do you mean that constructor injection with XML in Spring is not nice enough especially when you define a class with multiple contructors?

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

Automatic DI from the various frameworks is a mistake, IMO. It makes your code hard to read and hides the relationships between implementation and interface.

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 Karussell 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: Peter Karussell

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: Jakob Jenkov

"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: Jakob Jenkov

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

Using Spring DI via Autowiring is probably the easiest. No xml configs required :) I've only used Spring, so i'm biased

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.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.