Is Dependency Injection only useful for Unit Testing?

January 7th, 2008 by Oscar Huseyin

The rise in popularity of Dependency Injection over the last three years has been an interesting observation. “Lightweight containers” like Spring and Pico have really intrigued and excited the masses of Java Developers, so much so, that Spring (for example) is automatically adopted and accepted to be mandatory for almost all J2EE applications.

Looking back to when I was first reading about Spring, I clearly recall how the DI concepts and simple semantics of the XML configurations really got my creative juices flowing. I remember thinking about all the possibilities the framework could offer; specifically the view of configuring all my components so they had no knowledge of their dependents. Just after I created my “Hello World!” application, I quickly realized that the concepts of the Abstract Factory had just been reinvented, this time under the “Lightweight Container” marketing. Sure, the framework provides externalised definitions of object dependencies and promotes coding to interfaces, but its no different than my trusted old Abstract Factory pattern. Ignoring my cautious voice, the shiny marketing got the better of me and I convinced myself Spring could present a better alternative to my novel approaches; I’d decided to use it on my next project.

After about three months of using Spring in angst, I recall moments where I was enjoying the flexibility I’d attributed to Spring. Spring promoted the definition of loosely coupled Java classes which really gave me an advantage during unit testing. Heck, with a bit of thought, I could wire every one of my java classes using Spring bean definitions and define all my dependents as a reference to another Spring bean. Now, I can pass in Mocks, Stubs, basically anything that implemented the contract. What power! It gave me incredible leverage to test my primary test object by mocking or stubbing my fixtures or dependents; now, obtaining higher levels of code coverage was really easy. I just had to ensure that all the java classes that I needed to test were defined as a Spring bean, making sure that all the primary test objects dependents were also defined as bean references. This way, by overriding specific bean definitions with Mock or Stub ones, I could replace them at runtime to exercise every concern of my application code.

One observation that I made during this time was the reduced number of the new operator usage. Looking though my source, everything was injected into my classes and the new operator had practically vanished. I recall the infamous “Dont call me, we’ll call you” cliche had whispered in my mind.

Looking back over my first Spring project, I’d say we achieved a test code coverage of about 80%. This was really exciting and I’d give all the credit to our decision to use Spring. A few years later, a few more gray hairs and a few more Spring enabled projects, I’ve realised that Spring is only an enabler to achieve high unit test code coverage. Sure, Spring privides some really nice JDBC, JNDI, JMS etc helpers, but the XML configurations aspect that it gives to an application can get really messy; so much so that it can become a real development impedance. How is this possible? Read my Aspects of Spring on a Monolithic Codebase blog; it sums up my growing pains.

So, the one resounding question that I have in my mind is “What real benefit does Spring offer to a system?”. After many discussions and hours of mental deliberation, I categorise the benefits of Spring by percentage as 90% unit testing flexibility and 10% utility.

Where to from here? Well, that depends on the importance you place on code coverage. Period. If your aiming for high levels of code coverage, then Spring’s your answer; just expect to deal with a pervasive XML configuration aspect of your codebase.

Proposing alternatives to Spring could be futile given the wild acceptance of the framework. In my humble view, Abstract Factories are formidable alternatives and can also be configuration driven and, again, cause a proliferation of dependency descriptor externalisation, however, they force you to think about your providers and give you a break from the Spring alternative to think about when you need to abstract your providers. This way, your decisions to define your configurable components can be made with more pragmatism and care.

In conclusion, using Spring has many advantages, most of which are, sadly, concerned with the testability requirements of your codebase. Separating your application tiers by demarcating with a layer of Spring configuration will be my next approach. This way, I can achieve my provider view using the attractive semantics of Spring bean definitions.

8 Responses to “Is Dependency Injection only useful for Unit Testing?”

  1. Steve Freeman Says:

    I’m surprised at your conclusion since most of the noise I’ve seen about Spring is to do with combining components, managing transactions, that sort of thing. I’ve not heard it pitched as test support.

    As you say, excessive XML configuration is a killer and there’s a failure case where /everything/ is in the configuration. MIght as well just use Ruby…

    I’ve been involved in a couple of “despringing” exercises, moving more code back into Java, sometimes even to configure Spring directly, and leaving in XML just the stuff that really will need configuring.

  2. Jeremy Weiskotten Says:

    There’s more to the Spring framework than the bean factory/DI stuff, including the ORM templates, MVC, etc. It all leverages the DI core, of course.

    Another alternative to Spring (which I have no experience with) is Guice. It’s an even lighter-weight solution, using annotations instead of external XML configuration to wire dependencies.

    Of course, you can do dependency injection without any kind of container by writing your own factory methods. I discussed this in detail in a Dr. Dobb’s article back in April 2006 (http://www.ddj.com/architect/185300375), coincidentally with testability as the primary focus.

  3. Paul Says:

    To follow-up Steve. One of the interesting things about using Spring is that (as long as you minimize using classes that extend Spring classes) it is pretty easy to write a Java class to assemble the application the same way the XML files do.

    Granted, it could be big and ugly, but type checking is useful.

    OTOH, writing the code to replace the AOP goodies like transactions and caching are going to take a little time.

    The latest version of Spring offers quite a bit to reduce the size of the configurations, and make them more manageable. The schemas help a lot and then there are the annotations. Personally, I think the annotations should be used very carefully or, they could make things worse.

  4. James Law Says:

    I agree that use of Spring has made our teams better testers, but really, thats because Spring encourages better design I think- no more statics that can’t be tested (easily)… and of course, j2ee without an appserver = easier integration type of testing.

    With the number of annotations in spring 2.5, and 2.1, I can say our xml count is reduced by at least 70%. I am not sure why everyone equates spring with tons of xml at this point.

  5. Yagiz Says:

    Steve,

    It’s interesting to hear about the “deSpringing” exercise. Could you tell what was the main reason behind it?

  6. jbisotti Says:

    It’s only useful for unit testing?

    What about the various Templates that make working with JDBC/Hibernate/JMS, etc much less painful?

    What about the well thought out Exception hierarchy when dealing with JDBC?

    What about its AOP usage/support?

    For me, there are far more benefits than just improving code coverage (though that’s not a bad benefit in itself).

    Cheers,
    Jamie

  7. Oscar Huseyin Says:

    Jamie,

    When you talk about JDBC, Hibernate, iBatis, JMS etc Templates, your talking about “Utility” support that Spring offers - the %10 that l talk about:

    “Sure, Spring privides some really nice JDBC, JNDI, JMS etc helpers”

    … and …

    “I categorise the benefits of Spring by percentage as 90% unit testing flexibility and 10% utility”

    Granted, these utilities are very useful, but count how many of them you have in your Spring XML files with respect to custom bean definitions, eg, Your Services, DAO’s and general POJO’s. What did you find?

  8. Bill Bartmann Says:

    Cool site, love the info.

Leave a Reply