Do it Yourself – Dependency Injection

May 26th, 2010 · 13 Comments ·

A friend of mine has put together a set of documents which talk about do-it-yourself dependency-inject. Being that I am a fan of DI and how it helps with testability I wanted to share it with you. It is a good read for anyone interested in getting better at DI.

by Chad Parry

I want to evangelize this technique so that people know a lightweight way they can adopt DI. I think we need to refine the definition of dependency injection. It shouldn’t mean the use of a framework like Guice, because that’s just one possible implementation. It should mean the separation of glue code from business logic. The glue code, (which is represented by annotations in Guice, but could just as well be static helpers), is neither easy nor important to test. On the other hand, the business logic should be made easy to test. The secret to testability does not lie in removing untestable code as much as in segregating the untestable code.

The “dependency injection” (DI) technique is a way to improve testability and maintainability of object-oriented code. Typically adoption of dependency injection is coupled with adoption of a dependency injection framework, such as Guice [1] or Spring [2]. These materials show how dependency injection can be accomplished without any framework. The same benefits provided by frameworks can be realized using “do-it-yourself” (DIY) handcrafted code. This model is named DIY-DI, pronounced die-die.

Tags: Uncategorized

13 responses so far ↓

  • Giorgio Sironi // May 26, 2010 at 10:48 am

    Well said, when I work with PHP for example there is no standard DI container but I achieve the same thing with plain old factories.

  • Hans // May 26, 2010 at 2:47 pm

    While an interesting programming exercise, and probably insightful to those new to DI, but obviously Spring or Guice are already pretty much as lightweight as it gets, especially (in the case of Spring) if you only use the core DI facilities.

    Implicitly billing Spring and Guice as heavyweight does not do those frameworks justice.

  • Pedro Newsletter 27.05.2010 « Pragmatic Programmer Issues – pietrowski.info // May 27, 2010 at 12:25 pm

    [...] Misco Hevery new article about dependency injection made by ourselves. [...]

  • misko // May 27, 2010 at 4:12 pm

    @Hans,

    I love GUICE, but I would not call it lightweight, it is not about the size or the speed. It is the mental model which is involved, also they may not run in J2ME for example. Manual DI, is good to understand and use.

  • Alexandre Gazola // May 27, 2010 at 5:02 pm

    Good post, misko!

    It´s always important to emphasize that dependency injection is just plain-old good OO design.

  • Markos Charatzas // May 28, 2010 at 6:39 am

    Missing your posts on testability and OO principles Misko.

  • Markos Charatzas // May 28, 2010 at 7:50 am

    One question related to the new operator.

    How would you handle classes like “parsers” that create instances on a “need-to-know” basis?

    Would you inject a factory into such a class? (Doesn’t sound right)

  • Nitin // May 28, 2010 at 10:58 am

    Hi Misko

    Good article. Have you checked out EasyGloss for J2EE dependency injection testing. It is similar to adding our own injections to our unit tests to avoid heavy weight external dependencies like EJBS

  • Chad Parry // Jun 7, 2010 at 8:23 pm

    Markos, the kinds of objects created by parsers are usually simple value objects. Since they don’t have behavior and their state is simple, you can depend on them without needing to write complicated tests. Here’s my opinion on page 6 of the DIY-DI manual:

    There are exceptions when it is acceptable to invoke “new” or a static method. Developers should just be aware that tests will be forced to exercise the product code and these hard-coded dependencies together. As long as the dependencies are trivial, this does not pose any practical problem. For example, it is normal to use “new” to construct a simple value object. As another example, it is good to invoke stateless static helpers such as “Collections.max.”

  • Konstantin Fadeyev // Jul 27, 2010 at 7:16 am

    Misko and Chad, first I want to thank you both for your great ideas on DI, for your blogs, videos and articles – your insights helped me and my colleagues a lot to write better code.

    Although I have a question about the article:
    In step 7 you introduced SettlementCalculator to decouple two service objects so they collaborate through the value object – settlementAmount. But while you were doing that, you actually moved execution of your business logic from bookingService.buy() method to the phase of object graph creation. Isn’t it something we should avoid? What if statementCalculator.getSettlementAmount() throws an exception or reads from hard drive? I thought that first line in the main() method is just about object graph creation and ALL work should done after that, i.e. in bookingService.buy().

  • Chad Parry // Jul 27, 2010 at 9:47 am

    Great observation, @Konstantin. We say that the first phase is exclusively object creation and the second phase is exclusively business logic. But we are telling a white lie. Really, the two get mixed together freely. This interleaving must happen every time you inject a dependency that gets created by a factory.

    In DIY-DI, exceptions will be propagated normally, regardless of which phase they are thrown from. So my opinion is that it’s not a problem. With Guice, some exceptions can get swallowed, so you should use ThrowingProviders liberally, and then it’s not a problem.

    It’s important that your source code shows a clear separation between glue code and business logic, but less important that there is a strict boundary at runtime between the two.

  • Martin Norbury // Aug 16, 2010 at 3:30 pm

    Hi Chad,

    Many thanks for the DIY DI guide. It was a very enjoyable read.

    One thing I’m currently puzzling over at the moment is how one would go about implementing configurable injectors. For example, if you were using DI injectors in an application that is capable of connecting to multiple database types. Is the correct way to do this to use providers?

  • Chad Parry // Aug 18, 2010 at 7:35 pm

    @Martin, the most straightforward way is to use the factory pattern. The factory can ask the injector to provide parameters like all the various database hosts and ports, plus a flag that indicates which database to use. Then the factory’s responsibility is to produce the appropriate connection object.

Leave a Comment