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
A, I even try to avoid exposing an interface implemented by
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)