Tuesday, January 20, 2009

When to use Dependency Injection

by Miško Hevery

A great question from the 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.

Your milage may very.

13 comments:

  1. Don't forget Plexus. I think more people are unwittingly using Plexus every day than something like Pico, it is at the core of Maven.

    ReplyDelete
  2. I'll defend Spring here...

    Spring has a very good deployment package and you can easily only include the DI jars and not include all the others. Don't use what you don't need.

    Spring supports annotations, in fact I would have said it is the recommended configuration choice. There is no data to support the claim though.

    Spring supports constructor injection, and again I would have said it is the recommended approach. No data though.

    Spring also has great support for autowiring JUnit tests. Cool! Check it out: http://is.gd/gIcB

    ReplyDelete
  3. I agree with Hamelt here. I'm using Spring every day and I only use it with constructor injection.

    However, if you are referring to the Spring Documentation, you are indeed right.

    The Spring team generally advocates the usage of setter injection, since a large number of constructor arguments can get unwieldy, especially when some properties are optional.

    ReplyDelete
  4. Spring has a JavaConfig that is in beta which allows one to use DI in Java (or Scala code for that matter) without using any XML.

    I understand it is possible to mix JavaConfig with XML, but I haven't done that on any of my projects.

    ReplyDelete
  5. One of the problems I face with Guice is the fact that a Provider only provides a #get() method. Is there a feature to pass in parameters to a variant of the get method like AssistedInject ? Does Spring have a comparable thing to Providers ?

    ReplyDelete
  6. @andorra Yes Spring has "Factory" interfaces, which are the same thing, but they are not available by default and are not type safe last I checked.

    Spring also has an assisted inject equivalent with Factory methods (and interfaces), which uses method decoration. Again, it is a bit clunky but it's there.

    @Hamlet
    Annotations != type safety
    JavaConfig is also not type safe, like Guice's binder API.

    As for other features, Guice has much more compelling servlet and JPA stories, which are 90% of use cases in the kitchen sink.

    Disclaimer: I am a Guice team member.

    Dhanji.

    ReplyDelete
  7. @Dhanji

    Can you explain more the statement "JavaConfig is not ype safe". With JavaConfig, everything is done in Java code so it checks all the types.

    ReplyDelete
  8. @Blair

    Oops, I meant to say JavaConfig *AOP* is also not typesafe.

    Dhanji. =)

    ReplyDelete
  9. i am using spring in my dayjob and guice in my pet projects, both for about half a year.

    both have increased my productivity drastically.

    spring seems to have an advantage at the business side - as a manager, you will recruit a spring expert easier than a guice expert.

    on the other hand, it seems much easier to mess up the spring configuration, than the guice config. @Inject apeared more intuitive to my coworkers on the pet project than using the external config.

    what bothers me in both cases: there seems to be a tendency to view the injector/webappcontext as a super-factory.

    so i've seen the approach that should be used as a last resort more often than i should:

    StaticUtils.injectorFromservletContext(). getInstance( SomeDao.class );
    SpringUtils.getBean("someDao");

    in 99% of the cases, this is wrong, since you could simply inject the right class using @Inject or as a < property >. effectively you transform your class to a top-level class by abusing the DI container this way.

    ReplyDelete
  10. Use Ruby and you won't need a DI framework:

    * http://rubyconf.org/talks/18
    * http://rubyconf2008.confreaks.com/recovering-from-enterprise.html

    ...although I disagree with Jamis that DI is completely unnecessary (you can hear me on the video) - DI is still a valuable architecture, even in Ruby. Like testing, it generally leads programmers to do Good Things - such as loose coupling and high cohesion.

    Unfortunately, most Ruby frameworks (such as Rails) are architected in a way that pretty much precludes the widespread or high-level use of DI in your app.

    However, if you are not constrained by a framework, DI is an excellent way to structure your app. Start with a simple Registry pattern which builds your App and take it from there (like this: http://geminstaller.rubyforge.org/code/coverage/lib-geminstaller-registry_rb.html). Simple, maybe ugly, but the result of pure YAGNI TDD and completely functional (btw, this started out with Needle but I scrapped it because it was my only external dependency).

    -- Chad

    ReplyDelete
  11. We just developed a open source Light Weight Ioc / Dependency Injection framework. Can you have a look?

    http://blog.isilverlabs.com/2010/08/lightweight-ioc-dependency-injection-framework/

    ReplyDelete
  12. i am planning make my project on inversion of control/dependency injection.can anybody please suggest me from where actually my project should start????? reply as soon as possible...i need your help because i have understood the concept but unable to implement.

    ReplyDelete
  13. please let me know how to make framework using dependency injection??? and how to implement the concept of inversion control

    ReplyDelete

The comments you read and contribute here belong only to the person who posted them. We reserve the right to remove off-topic comments.