Do it Yourself – Dependency Injection

May 26th, 2010 · 23 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

23 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.

  • mobile application testing // Sep 29, 2010 at 11:23 pm

    Many times i found no standers for DI container. Some time it is very hard to working with such conditions.

  • WW // Nov 1, 2010 at 5:13 pm

    @Chad:

    I’m wondering why you used statics in your injector code. Why not create an instance of your injector and then use that?

    I feel that this would be useful because others could extend your injector, overwriting perhaps just one method to wire together different service objects.

  • Chad Parry // Nov 1, 2010 at 8:58 pm

    @WW, when I explored using instance injection methods instead of static injection methods, it didn’t provide any benefits. Also, you run into the problem of having to find the right injection instance to bind to. I found that the code was always better if I used a context object and static methods to configure everything. Try it out yourself and see if you agree.

  • Luke // Feb 23, 2011 at 4:28 am

    We’re currently looking at switching to using a DI approach to coding, as our code is currently so untestable.

    We’ve found many articles on this site to be very helpful in educating us about our bad practices, and how we can improve matters.

    I found this link to Chad’s approach for DI particularly enlightening, as it was the first to give me a better idea of how it scales past trivial examples, and how it could be applied to our own code.

    However, one of my colleagues is strongly opposed to the use of statics anywhere in our code (they are, in a large part, what we are looking to remove, so why do so by adding new ones in?), and also isn’t a big fan of Chad’s injector pattern.

    We’re hoping someone could offer some insight on the benefits/negatives of using the static injectors over using the factory pattern Misko shows in articles such as: http://misko.hevery.com/2008/07/08/how-to-think-about-the-new-operator/

    Also, are the static methods in Chad’s version a temporary solution, to be refactored out later, or the final state?

  • Chad Parry // Feb 25, 2011 at 11:09 pm

    @Luke, I think you would be successful going with either Miško’s factory pattern or with DIY-DI. They’re almost the same thing with different names. The goal is always the same: relegate the glue code (like “new” operators) to their own place, so that the business logic is easier to test. The reason I used static methods in the glue code is because I’m not interested in unit testing either them or their callers. I focus all my unit tests on the business logic, where they are most effective and most needed. So statics in the injector are not harmful. On the other hand, if your co-workers feel more favorably about a DI idiom that uses only instance methods, you should probably humor them. If you get any flavor of DI adopted on your project, you’ll be happy you did.

  • Luke // Jul 1, 2011 at 2:28 am

    Right, I’ve been tasked with writing a new module, and so I am seizing this opportunity to finally dive into dependency injection. Though very quickly I’ve hit some walls, and I have a few questions, which are kind of related to this section from the PDF:

    “Clients may resort to guess-and-check programming to find all the methods that need to be invoked in order to make the object usable. The solution is to ask for fully-initialized dependencies in the constructor. For example, instead of connecting to a database in a constructor or an init method, add a constructor parameter for either an open Connection object or preferably for the actual queried data.”

    In my particular case I am using JMS, here you have QueueConnections, QueueSessions, Queues, and QueueReceivers. I have a class that is responsible for receiving messages, so requires a QueueReceiver. Now, based on the above, this class should ask for a queueReceiver. However, a QueueReceiver is created from a QueueSession (session.createReceiver(…)) and a session is created from a QueueConnection (connection.createQueueSession(…)).

    Now, depending on the way the session was created, messages received by the QueueReceiver need to be handled differently. In my particular case, I need the session created with the following parameters, createQueueSession(false, Session.AUTO_ACKNOWLEDGE), if different parameters are used, the application may not behave as expected. Where should this logic go, though, an inject method, a helper, a provider? and how does my class ensure it is passed a receiver created by the right kind of session?

    Additionally, the connection that was used to create the session needs to have had its start() method called, or the receiver won’t receive anything. Again, what is responsible for calling this start method? How does my class ensure the connection was started?

    I have a feeling that this is possibly the responsibility of providers, and I should have a StartedConnectionProvider and a NonTransactionalAutoAcknowledgeSessionProvider, and a NonTransactionalAutoAcknowledgeQueueReceiverProvider. The NonTransactionalAutoAcknowledgeSessionProvider would ask for a StartedConnectionProvider in its constructor, and the NonTransactionalAutoAcknowledgeQueueReceiverProvider would ask for a NonTransactionalAutoAcknowledgeSessionProvider in its constructor, and my class would ask for a NonTransactionalAutoAcknowledgeQueueReceiverProvider. Unit tests could then perhaps be written for the providers to ensure they return the correctly configured objects from their get() methods.

    Is that the right kind of approach, or is there a better alternative? I guess one answer could also be that it should just be the responsibility of the injectors, and it is down to scenario tests to ensure the glue is sticking things together correctly.

  • mini // Apr 12, 2012 at 12:41 am

    Hi Misko,

    Just curious, as factories shouldnt contain any logic other than code to wire the dependencies, where would that actual call to parse the command line go (suppose we are using apache cli)?

    excellent articles by the way.

  • Carl-Erik Kopseng // Jun 22, 2012 at 3:53 am

    Any chance of seeing a RTF or, even better, the original Word version? I love reading technical stuff offline, and preferably on my Kindle. But PDF viewing sucks, while word->mobi conversion is quite nice – even for code.

    Tried contacting Chad on his website, but was flagged as spam … so retrying here.

  • Fred // Jul 6, 2012 at 2:49 am

    Hello,

    loved DIY-DI! Are there any exceptions for not injecting? eg. Logger?

    import com.spinn3r.log5j.Logger;
    class myClass {
    private static final Logger logger = Logger.getLogger();

    }

  • Fred // Jul 6, 2012 at 3:01 am

    oh, never mind. just discovered the part in text