The religion of dependency injection

A quick way to explain a set of differing opinions is to label it as “a religious argument”.  In a post about using MEF on NerdDinner, Scott Hanselman showed an example on using poor man’s DI versus regular DI.  Now, the post wasn’t about that topic, but more on how to integrate MEF with ASP.NET MVC.  I do get rather annoyed at comments like this however (emphasis mine):

The second constructor takes an IDinnerRepository, allowing us to make different implementations, but the default constructor says, "well, here’s a concrete implementation if you don’t give one." It’s a slippery slope and by adding the default implementation I get to sidestep using dependency injection while making the controller testable, but I’ve tied my controller down with a direct dependency to the DinnersController. This is sometimes called "Poor Man’s IoC" and many would say that this is a very poor man. That’s a religious argument, but Hammett takes a stand by removing the default constructor.

I see a religious argument is an argument whose opposite positions aren’t based in facts, but opinions.  It’s reasoning based on assumptions that are grounded in either faith, ignorance or a matter of opinion.

Something like poor man’s DI versus actual DI is different.  Let’s compare the code.  First, poor man’s DI:

public class DinnersController
    private readonly IDinnerRepository dinnerRepository;

    public DinnersController() : this(new DinnerRepository())

    public DinnersController(IDinnerRepository repository)
        dinnerRepository = repository;

Now, regular DI:

public class DinnersController
    private readonly IDinnerRepository dinnerRepository;

    public DinnersController(IDinnerRepository repository)
        dinnerRepository = repository;

In comparison, the poor man’s DI example:

  • Has more code
  • Is coupled to a specific implementation
  • Decides its component’s lifecycle

This isn’t just in the controller, every component used must use this technique.  Anything that DinnerRepository uses also would have to employ this technique, as we’re using the no-argument constructor for DinnerRepository.

I don’t know about you, but if I can write less code and gain the benefits of looser coupling and externalizing component lifecycle, that’s a win.

Let’s review.

Poor man’s DI: more code, more coupled, no flexibility

Regular DI: less code, less coupled, high flexibility

It was a failure in teaching dependency injection that the argument was made based on testability.  It only helps those already doing TDD to shape design, rather than just writing tests.

Instead, DI is about creating highly flexible components, both in lifecycle and component selection.  DI removes component resolution responsibilities from classes, therefore removing code.  And less code is ALWAYS a good thing.

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 DependencyInjection, Rant. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Matt Hinze

    One problem is the term “dependency injection”, used as if that’s the only thing going on. We should just stop using it.

    “Inversion of control” is a more accurate description of what we want to be doing.

    Hammet himself talks about this, in and elsewhere

  • Agreed. Testability is only one of the many beneficial side effects of DI, but the main purpose of DI is to enable loose coupling:

    Every time someone uses Bastard Injection, they introduce tight coupling. As you say: that’s not a religious argument. It’s a fact.

  • Sukant Hajra

    Regarding the nomenclature of “DI” versus “IoC,” I always thought that Martin Fowler had a strong influence in the movement towards calling the concept “DI” because the term “IoC” was beginning to get overloaded [1].


    So I’m definitely an advocate of can-afford-it DI, but just to voice the other side, I think there are some subtle points not mentioned here. For instance, some people are really sensitive to the strong coupling to a DI framework. Personally, for me, this is not so strong an argument, but it’s an interesting point. Maybe I’ll reach a context where it has more value for me.

    Which gets to my position on religious debates, which I /think/ is in line with Jimmy’s. I don’t see a reason to rename “DI” back into “IoC,” especially given the arguments in [1]. But I would love to see us stop calling everything that’s mildly controversial or unresolved “religious.” That’s just a silly way to dismiss an entire conversation. In this occupation, we’re steeped in unresolved discussions. I think we can figure out a way to be opinionated without being dogmatic.

  • @Matt,

    “Inversion of Control” is a more generic design concept. Dependency Injection IMO, is a pretty apt description of a particular application of IoC. Data Mappers like NHibernate or Data Mapper in Ruby are an example of IoC. “Pushing” data into a piece of logic code instead of letting the logic code go find the data for itself is another example of IoC..

  • jdn

    Uh, I think the ‘religious argument’ was over whether poor man’s IOC is “a very poor man”, not whether it was better than Regular DI.

    Sometimes (like in a corporate environment or two), poor man’s IOC is all you can achieve.

  • Gabe Moothart

    I’m going to speak up in favor of poor man’s DI. I don’t find the disadvantages you list very compelling:

    * Has more code

    Poor mans DI has slightly more code *in the constructors*, but in exchange for that you get more straightforward code (you don’t have to go digging for the DI initialization to find out your concrete types) and freedom from the cognitive weight of knowing yet another complicated framework. That’s a net win.

    * Is coupled to a specific implementation

    Oh the horror! I won’t be able to switch out my repository implementation at runtime! Honestly for 99% of the cases this is not an issue. The Gang of Four principle is “encapsulate the concept that varies”. Runaway DI says “encapsulate everything” and that needlessly complicates your codebase.

    * Decides its component’s lifecycle

    This is the most valid point, but it’s never caused a problem for me. In an MVC app you usually want something alive for the course of a request, and creating it in the controller constructor is “good enough”.

    * Poor man’s DI: more code, more coupled, no flexibility
    * Regular DI: less code, less coupled, high flexibility

    Of these, the most compelling by far is “high flexibility”, and you have to admit that in exchange for the flexibility you complicate your code flow and add a dependency on another library. This may be worth it, but it may not and I think you need to acknowledge it. Watching the gyrations you go through to use DI comprehensively in Asp.Net MVC has only strengthened my opinion on this.

  • >> It was a failure in teaching dependency injection that the argument was made based on testability.

    Well said :)

  • @Gabe

    One thing out of the gate – poor man’s DI is not DI at all. It’s a legacy code technique. It’s something I use when a code base is horribly coupled and I need to safely make changes.

    I do admit that getting DI to work in a framework where DI wasn’t a design goal can be tricky. However, the cognitive weight of designing all the components up front is far greater than only designing one layer at a time, as you do with DI.

    Talking with the Fubu guys, they look extensively at the MVC codebase. One number I got was that they estimated that about 50% of the code there exists solely because the team did not design with DI in mind. That also matches my own experience. Codebases that are not designed with DI have far more code, coupling and duplication than those that are.

    Not just in constructors, either. I see pointless factories, arbitrary extension points, hard-coded decision points, static gateways, etc etc that all just go away when it’s DI turtles alllll the way down.

  • That’s not poor man’s IoC, that’s just a piece of crap, called IoC by somebody who does not fully understand IoC/DI

  • Sorry jimmy i thought poor’s man DI was implementing a factory class to create a dependency instead of using a DI framework … declaring the concrete type in the class is not DI at all … i think that was not clear on the post

  • rob

    This is polemic.

    PMDI clearly has it’s uses as you’ve admitted. I would not wade in to an IoC container until the codebase demanded it. Doing so before this point will add unnecessary indirection. Also, as you state it’s a very useful technique when trying to couple and make code more testable.

    It is what it is. It has it’s uses. whether you want to consider it DI or not I don’t really care.

    Also, don’t think your coupling’s necessarily gone away just because ndepend can’t see it. It’s effectively still there wired in to you IoC registry and sometime it’s preferable to see that in the codebase rather than hidden away.

  • @rob

    I’m only coupled to the interface now, not the implementation. That’s what I’m trying to achieve. With DI, WHAT I’m coupled to is explicit, and called out in the constructor. That’s why I put DI in place on the first day of a project, it makes the coupling explicit.

  • Steve

    50% more code because they don’t think about DI? How’s that even possible? Adding a second constructor can’t account for 50% more code. Especially considering that you then don’t need any bootstrap/config code.

    Listen, I’m pro-DI/IoC, but we really have got to stop over exaggerating in an attempt to scare people into doing it.

  • Peter

    Chad Myers posted about poor man’s dependency injection–I found it enlightening in that it uses an example to show how PMDI can be painful further down the road:

  • @Steve

    Pop open the code, and check out how much of it is passing stuff around, context objects everywhere, factories, static gateways, etc etc. It’s a LOT of extra code that just wires things up versus actually adding behavior. PMDI alone doesn’t add extra code, it’s NOT doing DI that adds all that extra code, sorry I wasn’t clear about that.

  • Regarding the comments above about whether to call it “dependency injection” or “inversion of control”, you guys need to slow down and pay attention to what you’re saying. DI and IoC go hand-in-hand but they are far from synonymous. Dependency injection is a pattern that says “I don’t know the implementation of this interface, but I need this interface here, because I’m going to call it. Please provide said implementation for me, please. Thanks.” Inversion of control, on the other hand, looks at the problem from the opposite perspective. It says, “I don’t know what to do here, I need someone else to do this for me. So I’m going to *invoke* this interface, or raise this event, or just set a state, and hopefully someone will finish the job.” Meanwhile, someone else comes along and says, “Ah, yes, I know what to do with you. Come on buddy, I’ll take care of you.”

    In other words, dependency injection is providing the implementor, whereas inversion of control is invoking an implementor.

  • @Gabe

    ‘The Gang of Four principle is “encapsulate the concept that varies”.’

    How often do you honestly know what is going to actually vary a month from now? How about a year from now? Or ten years, assuming you’re writing valuable long-lived software?

    I agree with the Gang of Four principle. Encapsulate the concepts that vary, or are likely to vary. I just can’t help but point out that, in any given code-base, literally everything tends to vary over time.

    What you call “runaway DI”, I call extremely modular testable code that is predictable and loosely coupled. The “poor man’s DI” that was illustrated in this article would provide no value to me. I may as well not DI at all, because it actually ensures that components can (and will) be constructed instead of injected. This leads to tight coupling that can slow down development cycles, inhibit testing, and just plain make my day bad.

    Others may have other experiences, and your mileage may vary, but I think it’s far past “religious debate” at this point. The strengths and weaknesses are well known, and it’s just an honest professional discussion on how far each of us believes is appropriate.

    • Neutrino .

      If you don’t know what classes in your codebase are likely to vary month from month, then that sounds like you don’t have an actual design at all, just a sea of objects all wired up via DI chattering away to each other.

      Compared to a simple new’ed up object graph with proper implementation hiding, I find DI saturated codebases to be an incomprehensible mess in which it’s extra effort to even identify what is genuine state data from the mass of pre-emptively created dependencies that are potentially only required for a fraction of an object’s lifetime.

  • @steve,

    I think the 50% figure is a bit high, but it isn’t just because of a few extra constructors. They’re cutting a lot of public properties for unit testing through setter injection that do the “if null, return the default” anti pattern from years back, which in turn begets yet more [SuppressMessage] noise.

    One of the other usages of an IoC container is to put things together, and they generally take care of lifecycle and scoping issues like objects that need to be scoped to a particular HttpContext or request. The MVC code doesn’t take advantage of this, and because of it, they need to write a lot more code to pass objects down inside an object graph to where it’s needed. *That’s* a bigger culprit for the “too much code” issue than the poor man’s DI.

  • Theo Andersen

    I’m still not sure i get why PMDI is always such a bad thing.

    What if you know that the class is always going to be using a specific implementation of the interface, but you don’t want the client code to know about this implementation? (but you still want the DI to be able to decouple the dependency in tests)

    Or is it wrong to use the PMDI because you don’t want every code using instantiating the class to create the same code implementing the interface. The code you say is ‘saved’ in the real DI, is only added to the instantiating code. Unless you would always use an IOCC.

    Sorry if i’m a bit slow here – I get that its not optimal with the constructor having the strong dependency, but you need to have the real coupling somewhere :) Would you then always instantiate it in the client code / IOCC.

    If I’m opening too big a topic here, then feel free to post links to more info .:) it’s a very interesting topic.


  • Mark

    Poor man’s DI is pretty insidious. If you’re working in a codebase where ‘proper’ constructor injection is used and maybe 1/20 classes uses poor man’s DI, then you have a problem. Everything is configurable and loosely coupled except … for that one type that is flying under the radar.

    I’ve used constructor injection for over two years, but when I first started using an IoC container (a colleague introduced it into our application) I didn’t understand it at all. I was sceptical and thought it offered very little over normal construction. I was so badly wrong. The caveat is that you only get the benefits if it’s set up properly, you use a consistent mechanism of obtaining types (read: use the container!) and all of the types involved play ball.(don’t use new for dependencies, don’t use poor man’s DI etc.)

    When you stumble upon a portion of your application that is going against the grain, it is tremendously irritating. We recently encountered a situation where our application had some functionality that was manually wired up (extensive use of new, static factories and poor man’s DI) which wrested control away from the container and did not go with the conventions.

    I was meant to re-use the functionality in a slightly different context, but couldn’t. The result was that we couldn’t wire it up, configure or re-use the modules. I.e. it was not loosely coupled; it was like a little enclave of hard-wired stuff.

    After they were refactored properly, the problem disappeared and all of the renegade functionality fell into line once more. I included the module, configured it differently and it worked beautifully.

  • Steve


    I’ll take your word for it as I haven’t dug deep in the MVC code, the 50% number just jumped off the page as such a huge number, I just can’t fathom how that’d even be possible.

    But, MVC is a complex beast, so I shouldn’t be surprised that a bad design decision can start causing problems exponentially and before you know it they’ve got thousands of lines of horrible code used to get around a problem.