Are IoC containers a case of “the Emperor’s new clothes”?

! Warning: this post hasn't been updated in over three years and so may contain out of date information.

Someone, using a gun labeled 'IoC container', aiming at their footI don’t use IoC containers. Many of the best developers I know swear by them. More, three incredible people who have taught me so much over the last few years – Shaun Smith, Stray and Till Schneidereit – even developed their own, very popular, IoC container: RobotLegs. Yet I don’t use IoC containers. I’m a big fan of dependency injection and a passionate advocate for the return of the death penalty for the singleton and service locator patterns. Yet I still don’t use IoC containers. Is the reason I don’t use them because IoC containers are a case of “the Emperor’s new clothes”?

This post was inspired by a conversation with Wiktor Zychla on Stack Overflow regarding dependency injection (DI). My answer involved one of my favourite ways of minimising coupling between aspects of my code. When class A depends on a method in class B, I don’t just avoid exposing B to A, I even try to avoid exposing an interface implemented by B to A. Instead, I favour injecting the required method as a callback into B. To my mind, I have reduced the coupling between the two classes to the absolute minimum possible, without using any hacks or tricks. In fact, I’ve simply used good functional practice.

Wiktor challenged my answer by pointing out that IoC containers don’t work that way, instead working at the level of the interface. I intended to reply that that was a good reason not to use IoC containers, but played safe and suggested it was a limitation of some containers, for surely there must be some that can handle mapping callbacks like this? Wiktor called my bluff and asked for an example of a container that could do this. At that point I had to admit: I don’t use IoC containers and so wasn’t aware of any. A quick check of some .NET IoC container frameworks yielded none that boasted they could handle function mapping, so it’s likely that there are none.

This set me thinking though: why don’t I use IoC containers? Why do I “roll my own” DI? To answer that, I went looking for why people use IoC containers to try and understand what I was missing, if anything, by not using them. After a couple of hours, I’d reached my conclusions, which is what this blog post is about.

The first thing I came across was this question on Stack Overflow. First of all, let’s consider the accepted answer. I think a fair summary of Ben Scheirman’s answer is that he constructs two strawmen of dreadful quality, and then does some IoC hand waving in order to demolish them. It’s a truly dreadful answer in my view. Do the masses tear it to pieces? No, they award him over 400 positive votes. Clearly this set alarm bells ringing in my head: the most popular answer for why one should use IoC containers appears to be little more than a clarion call to the fanboys to upvote without thinking. This really wasn’t a good start for me trying to find positive reasons for using IoC containers.

There are a whole bunch of other answers to the question and they are worth reading. Something I did pick out though, which resonated with me, is that IoC containers are complex and hard to learn. The previously mentioned Robotlegs has a book available to help you learn how to use it: ActionScript Developer’s Guide to Robotlegs. It’s 140 pages long. As I mentioned at the beginning, I’m a big fan of DI. I don’t need 140 pages to explain the approaches I use though. Why does an IoC container need that much explaining therefore?

Looking at popular C# IoC containers. things are a little different. Castle Winsor has very little documentation. Does this mean it’s simple? No, it simply means the documentation is incomplete, it’s a “work in progress”. So that means it’s both complex and badly documented. Another popular one is Ninject. The author clearly realised explaining how to use an IoC container was so hard, he gave up trying four years ago.

The other thing I discovered about IoC containers is that it’s really hard to find examples of how to use them in a meaningful way without pouring huge dollops of anti-patterns all over your lovely clean code in the process. The root cause of this problem I think is that IoC container advocates like to sell them as the solution to all your DI needs and folk fall for that promise. Then, having just coupled their entire application to a container, folk then face the issue of how to expose that container to every aspect of the application.

Some IoC advocates seem to miss the whole point by suggesting using the very service locator anti-pattern that DI sought to destroy, as the means of accessing that container. Others head off down the route of injecting the container into all aspects of their application. Yes that’s right, the IoC container, which is supposed to simplify DI ends up relying on DI to expose itself to the application. Not only isn’t the IoC container providing a solution to injecting dependencies throughout the code, the container ends up as a huge God Object. It appears that the container usage options are either using an anti-pattern to expose it, or allowing it to become an anti-pattern itself. As you can see, by this point I was despairing of finding anything positive to say about IoC containers.

My previous StackOverflow link contained an answer by Mark Seemann, well known advocate of dependency injection in all forms. I found this article by Mark too. This article highlights another flaw with IoC containers: you all too easily get to swap a small amount of type-checked code for unchecked, harder to read “declarative” container definitions that in Mark’s example, end up twice as long. I think I can suggest to Mark that he probably should have said “Smart man’s DI”, rather than “Poor man’s DI” in his article, for his article just reinforced my view that doing my own DI by hand is the easier option. I accept that Mark himself uses “Poor man’s DI”, but that doesn’t change the fact that it is a bad way of describing it.

No article by me, on IoC containers, would be complete without dragging Mike Hadlow into the fray. I had reached the point of feeling that IoC containers weren’t just in the “chocolate teapot” category, rather they were in the extreme “chocolate teapot, constructed by first building a nuclear reactor to provide heat to melt the chocolate to pour into the teapot mould…” category. The answer to Mark’s “When to use a DI Container?” question appeared to be: never! So I sought Mike’s views, by gently goading him with my conclusion that IoC containers were of no use to anybody.

Mike offered me a link to an article he written: ” The first Commandment: Thou shalt not reference the IoC container!”. It’s a good read and in it, Mike offers a third alternative to the “faux DI via global locators” and “injecting god objects” options previously discussed. His option is to set up the IoC container such that through “a single call to the container to get the root object of our application … all the cascading dependencies from that root object are discovered, constructed and supplied by the container”. Does that sound good to you? If yes, that means you like the idea of exposing every single class in your application, that has a dependency on another class, to the container. Encapsulation? Don’t be silly, you can’t encapsulate, not when the container needs access to everything. So I put this to Mike and I think I finally got to the bottom of IoC containers from his reply. Of course you wouldn’t really do that. The container’s job is to set up the dependencies between the macro level aspects of an application. “Poor man’s DI” is still used to resolve dependencies between internal and other lower-level classes.

Finally, I had something positive to say about IoC containers. The problem up until that remark by Mike, is that I hadn’t once come across an IoC advocate admitting a simple truth about IoC in plain terms: IoC containers are only one small part of the solution to an application’s DI needs. A well constructed application will have many modules, which have interdependencies. As a result, the application start-up code ends up having to resolve those interdependencies and plumb the applications parts together. An IoC container is a really good fit for this task. But, the container’s job stops there and simpler forms of DI should be used internally within those modules. Sadly, this message doesn’t seem to get told. Even developers of IoC containers seem to have missed this point, which probably explains why they are so complex: they are trying to do too much with their container frameworks.

Going back to that original discussion, I finally therefore feel I have an answer that satisfies both myself and Wiktor Zychla. If you are looking to resolve dependencies between two high level “module” classes, then injecting an instance of an interface – via an IoC container – is the way to go. If you are dealing with a dependency between two low level “helper” classes, then opt for callback injection to minimise the coupling.

Finally, are IoC containers a case of “the Emperor’s new clothes?” What I initially meant by this question is are they a case of too many people thinking “the smart guys use IoC containers, so if I don’t use them, does that mean I’m not smart?” Does no one question their use simply through fear of looking stupid? I thought so and even felt I’d found enough evidence to argue the case until Mike injected (pun intended) some sanity into the matter. The answer I feel is no. Instead they are more akin to the “PPI mis-selling scandal” that hit the UK a couple of years back. Sure, we won’t be seeing container vendors paying out large amounts of compensation to developers who’s time has been wasted. Hopefully though, people might start fighting back against the claims that IoC containers are a “one size, fits all” solution to all our DI requirements. They are a solution to one specific part of an application’s DI needs. If you hear someone claiming otherwise, just point out that he “has nothing at all on!”… 😉

(Incidentally, the image at the start of this post was found using a Google image search. It appears associated with Rob Conery’s blog, but I couldn’t find where. It is used here, cropped, without his permission)

14 thoughts on “Are IoC containers a case of “the Emperor’s new clothes”?

  1. “When class A depends on a method in class B, I don’t just avoid exposing B to A, I even try to avoid exposing an interface implemented by B to A. Instead, I favour injecting the required method as a callback into B”

    Would this Gist meet what you describe (it uses Autofac)?

    My experience with and feelings towards containers is very different to yours. Of course, context is king!

  2. @Ben, it does indeed look like it fulfils the requirement. Of course there is the small problem of its length, compared with not using a container, but it’s certainly an interesting intellectual exercise.

  3. FWIW, I don’t particularly disagree with the overall conclusion in this article. In my “When to use a DI Container” article (quoted above) I also explicitly explain that Poor Man’s DI is a better option than the way people normally use DI Containers; for the record, most code I’ve written throughout my career has used Poor Man’s DI (and still does).

    However, since some of my writings are quoted in this article, I think I should respond.

    Where, in any of those two articles of mine, do you see me advocating “injecting the container into all aspects of their application”?

    Never have I (consciously) advocated that – in fact, I have often advocated the opposite. Here’s an example:

    If those quoted articles give reason to believe the opposite, I’d like to understand how, so that I can clarify them.

    In my “When to use a DI Container” article that you also quote, I repeatedly link to publicly available source code on GitHub. Is there anywhere in that code where the DI Container is injected into the code?

    As a final note, the use of functions (or delegates) instead of interfaces is an interesting option in some languages (including C#). The last time I wrote coherently about this subject was a couple of years ago:

    This is a topic I’m still exploring, but at the moment, my philosophy around this is:

    Function Composition instead of DI is the way to go in Functional Programming. Thus, in my F# code, I use very little DI.

    In OOP, I prefer interfaces over functions for Constructor Injection. However, functions/delegates can be great as method arguments.

    Part of the reason I still prefer interfaces in OOP is because it make the roles more explicit, and it also enables Structural Inspection:

  4. @David – Personally, I would not consider code length an important factor when choosing to use a container or not. However, if you want it shorter, you can remove the lifetime scope call. Autofac component registrations default to InstancePerDependency and this is fine for our sample. I’ve updated it here

    I like and use the functionality provided by Autofac to deliver a product that is highly customisable. This customisation is isolated to new components and changes in the container configuration. Existing calls sites remain unchanged. If I did not need this, I may not use a container. However, I have found starting with a container often drives better component design (for me personally) and I imagine it might be hard to retrofit a container.

    Just in case you think my gist was purely an intellectual exercise, it is not. I register and resolve delegate types from the container where more suitable the alternatives.

    If you are worried about a giant container object knowing all, you can structure with modules – I use this for swappable features, isolating feature registrations within a module. This also means you can expose a configurable module to the container, rather than all your types.

  5. I believe you are talking about Dependency Infection ( where you get dependency on IoC container through out your code base. This is just a bad design on IoC part.

    In thought through containers (Autofac is my favorite) you don’t have that. All IoC code is contained within few modules and you rarely have to touch that (providing you have your conventions sorted and applied in DI).

    Also you can do crazy things with IoC container which would not be easy without container. For example multi-tenancy: different customers mostly get the same implementations of interfaces, unless there is a client-specific implementation which is only supplied just for that client. Or have different implementations of authentication classes depending on the http request – weather it goes from WebApi or MVC.

    Also application I work with at the moment has about 180 controllers and about 400 command handlers and another 250 implementations registered by convention. Imagine a amount of boiler-plate code to manually register all that? Autofac does that in about 100 lines of code and no other piece of code knows about any DI framework.

  6. “I favour injecting the required method as a callback into B”

    Well. imho that’s functional programming and not OOP.

    The way I see it you either have to fat interfaces or your trying to use C# as a functional programming language.

    Of course you get no benefit from containers then.

    The dependency injection is just a small part of the container. The resolution, cleanup and lifetime scoping is in my opinion the more important features.

    “IoC containers seem to have missed this point, which probably explains why they are so complex: they are trying to do too much with their container frameworks”

    I agree. a lot of containers have way to many features trying to solve all world problems. The sad part is that many users then try to do just than, instead of keeping some things out of it.

  7. @Mark, I have removed the suggestion that you support injecting the container via constructor injection, as I accept I misrepresented you with this statement. I still think “Poor man’s DI” is a bad description of the DI that one should use even when using IoC, so I have left that unchanged.

  8. @Jonas,

    I just cannot begin to understand the “that’s functional programming and not OOP” statement. It’s all programming. Use the tool that best fits the task. Pure OOP and pure FP are both broken models. Sometimes a class suits. Sometimes an interface. Other times a function is the best fit.

  9. When I discovered Spring and XML configuration, it was an epiphany. It finally made the promise of OO — reusable code — come true.

    Prior to dependency injection, functional code was never reusable — it always required usage & configuration-specific glue.

    Complex code was always prone to dependency & order-of-init problems.

    Post- dependency injection, it became possible to easily substitute algorithms or implementations for different clients (the Strategy pattern), reuse common code, maintain an exact same codebase for all & deploy just one changed XML file.

    It generally assists in advancing the use of Strategies and effective composition/ delegation techniques, overall.

    In short, Spring Framework & DI have been the biggest breakthru in OO over the last 15 years. The best thing since sliced bread.

  10. @Thomas,

    You neatly highlight how different people can have very different views. For me, the idea of giving up type-checked, “proper” code for the vileness that is XML sends shivers down my spine. Yet others, such as yourself, seem to prefer this approach. I cannot begin to understand why, but I accept others have different approaches to me.

    I guess your “sliced bread” analogy neatly sums it up. For many, sliced bread is a great technology breakthrough. For others, it’s a grotesque, manufactured imitation of real bread. I guess I’m in the “real bread” camp when it comes to writing code, so I hate Spring, I hate XML and – if honest – I struggle with why anyone bothers with classic OO, when better alternatives exist.

  11. “I don’t need 140 pages to explain the approaches I use though.”

    Is there a 5-page version for somebody who doesn’t even understand what DI is or why you’d use it? Or a URL you’d recommend as a good introduction?

Comments are closed.