Poor use of DI versus need for DI

Surprise surprise, but Uncle Bob got the twitterverse all riled up with another opinionated post, “Dependency Injection Inversion”.  His basic advice from the post on DI tools is:

I think these frameworks are great tools. But I also think you should carefully restrict how and where you use them.

Couldn’t agree more!  Every call to Container.GetInstance should be carefully, carefully thought out.  In fact, our goal should be to reduce the number of calls to the container to hopefully exactly one.  But a slight problem with the example he gives to show that DI is not necessary in all cases:  It’s so simplistic that it no longer represents any real-world code using DI.

Uncle Bob also prefers hand-rolled mocks, which may be an artifact of the crappiness of Java mocking tools, which in turn is a reflection of how far behind Java the language is behind C#.  He also points out:

I don’t want lots of concrete [Container] dependencies scattered through my code.

Couldn’t agree more!  That’s why we limit the container calls in our application as much as possible.  If I have a bunch of container calls in my code, I’m doing something wrong.  When I read his post, I thought that they must have been looking at the MVC framework source code, one which was built with IoC hooks, but not with the Dependency Inversion Principle in mind.  If I have to tell MVC that I’m using an IoC tool, it takes quite a bit of work to configure all of the places where things get instantiated manually to work.  I often have to write new classes just to support IoC.  Whether he meant to or not, Uncle Bob’s entire post was a straw man argument.  He argues against bad use of IoC, but never shows good use of IoC.  Which may mean that he’s never built or seen an application built well with IoC.

If you want to see an application written with DIP, IoC and Dependency Injection in mind, check out FubuMVC.  One of its core principles from the get-go was “turtles, all the way down”, basically meaning that a container will be used, and you cannot use the application without an IoC tool.  Guess what?  The design is much cleaner for it.

If I want to use an IoC tool in my application, this is something that should be configured once and only once.  If I have to plug a bunch of hooks just to say, “Yes, I am using an IoC tool”, then I haven’t really improved anything for the end user, have I?  Instead, I’ve made my application favor configuration over conventions, forcing more coding and more moving parts to figure out, making it more difficult to configure as needed.

So while it’s a great read and has a lot of great points, all that post showed me was that poor use of DI leads to a poor DI experience.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in Design. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Agreed, if you are calling Container.GetService or something similar all the time then that really isn’t “Injection”. Well, other than the fact that you save satisfying the dependencies of that dependency.

    Having a bunch of classes with a dependency on ServiceLocator or some custom IoC static class is definitely a code smell. You shouldn’t need to call on the container anywhere but perhaps in the bootstrapper code.

    Heh, I was also mildly surprised at the “hand rolled mocks” preference. Though both of these comments may be more of a personal preference rather than a reflection on Java. Some people prefer hand-rolled cigarettes too.

  • I couldn’t agree more. Dependency Inversion is about managing dependencies, about reducing coupling. I won’t beat the dead horse that are the benefits of doing this; but exchanging one coupling for another (changingg a coupling from direct construction of one of your internal classes to use of an inversion container) doesn’t get you the full benefit. Sure, you’re now coupled to something more stable; but you’re still forcing the responsibility (and thus coupling) of creating these objects via the container on to types that shouldn’t have this responsibility.

    There should be very little calls to the IoC to create or initialize an object. You’ll need at least one; but if all creation/initialization of your objects involves a direct call into the IoC, you haven’t designed for DI; you’re simply using a DI container.

  • unclebob

    A number of people have pointed out that my example was so simple as to be meaningless. I think that’s funny because, I took the example from the Guice tutorial. In any case, I wrote the post because I have seen a fair bit of code lately that exhibits the problems I was talking about. The fact that some of us know how to use a DI container does not mean that a vast number of developers aren’t out there abusing them.

  • Well balanced response. I can definitely see your point here. I will check out FubuMVC. I have seen a large amount of hard to understand code due to overuse of IoC containers, but that doesn’t mean they can’t be used correctly. I think the core problem is we have so many containers and frameworks. I would like to see a language built around this core idea.

  • Wow, that was a great article. You very eloquently described the situation perfectly.

  • I totally agree with your article.
    There are in my opinion however some valid scenarios where a call to “container.GetInstance()” makes total sense, for example when the instance to retrieve implements IDisposable.
    In that case, you do want to dispose the object as soon as you are done with it and construction injection is not enough.
    A call would typically be
    using(var objectToRetriever = container.GetInstance(IDisposableObject))
    //do stuff here

  • @Michael

    Oh, there are definitely some valid calls to a container. We have places where we must use a container, especially in infrastructure code that serves as the backbone of certain areas.

  • unclebob: “A number of people have pointed out that my example was so simple as to be meaningless. I think that’s funny because, I took the example from the Guice tutorial. In any case, I wrote the post because I have seen a fair bit of code lately that exhibits the problems I was talking about. The fact that some of us know how to use a DI container does not mean that a vast number of developers aren’t out there abusing them.”

    Examples in a tutorial tend to be simple (easier to grasp the concepts). I you want to prove DI can go bad you may want to use a more realistic example (as you say… you have seen a fair bit of code lately that exhibits the problems => create an example based on that code)

    Still… everything pattern can be used and abused. Bad DI is bad, good DI is …?

  • Jonathan Perret

    @Michael Sevestre : in such a case, shouldn’t you take a dependency on an IDisposableObjectFactory instead ?
    Every time you take a dependency on the container, you’re basically saying that this class may instantiate pretty much any other class, and therefore no longer controlling your dependencies.
    It seems in fact that Uncle Bob was railing against this particular kind of “leaks”.

  • @Jonathan

    For those *very few* places where I need a container, I still wind up depending directly on the container, as a dependency. It’s just a personal preference thing…but I just prefer less code, over a facade.

  • Excellent response. I agree that this is an (exceptional) case where it’s best to respectfully disagree with Uncle Bob.

  • Jonathan Perret

    Thank you Jimmy for responding.
    I’m definitely with all of you on the “less code” argument. But two more points if I may, mainly to clarify my own understanding :

    1. When you do need the container, as you said the class takes an explicit dependency on it (“container” constructor arg, perhaps). Very good. So can we all agree that the often seen “IoC” global variable is an anti-pattern ?

    2. For the particular case, described above, of a class that must lazily (and/or multiple times) instantiate a class whose type is known at configuration time (i.e. we’re not writing a ControllerFactory), when I suggested using a factory I was not thinking of writing it manually (and my hint of a named factory interface was misleading in that respect). What I would actually do in that case is add a Func constructor argument, very easily configured with a lambda that captures the injector as a local variable, like so : ()=>injector.Create()
    I believe this keeps the dependencies under control for a modest cost.

    Hoping this makes some kind of sense,

  • @NeilRobbins

    Interested by your little swipe at Java mocking tools (agree about the lang). I’m not a Java guy (in any way), but I’ve been very impressed with Mockito (much like Moq), have you seen it? Even JMock has improved a lot over the years and whilst I find it slightly opaque compared to Moq (& mockito) & more of a PITA, I don’t think the state of it can properly explain Bob’s love for writing his own mocks (too many Kata’s creating a strange love of small, simple, pretty things might).

    Good response to U.B. though – fully agree with your general sentiment, just intrigued by the mock bit.