IoC containers: prozac for software architectures

I think Inversion of Control (and Dependency Injection, basically the only decent way to do IoC in OO languages) is a great idea. We do it all over our Izooble codebase, for example: it enables testability and encourages us to keep independent things separated. I believe that Dependency Injection is one of the few good design patterns that still make sense in modern OO languages. I suspect that it, too, will at some point be superseded by a programming language designer’s great idea, but right now I can’t imagine what that would be.

What I do think is wildly overrated, is IoC containers. I don’t see their added value over explicitly injecting a dependency into a class’s constructor. It’s the singleton antipattern in disguise, and with an IoC container it’s very difficult to see what is going on, because, magic. It’s even worse when the IoC container is configurable with something other than code (e.g. Spring.NET’s horrible, horrible, horrible XML abomination), because that actively encourages messing around with live servers* instead of fixing your damn deployment pipeline.

If you avoid IoC containers, you’ll typically end up with a Main method that instantiates a whole bunch of objects and passes them to other objects again. That Main method is an excellent summary for your entire application’s architecture. You can see how all the important components are tied together at a single glance.

Now, when your application grows, when you do this, two things tend to happen:

  1. Some class constructors, those high in the composition hierarchy, may need a very large amount of injected constructor parameters, just to pass them through to a class way down the tree. Well that’s cumbersome.
  2. Your Main method becomes a ginormous 100-line list of new operators.

Somehow, people take this as a sign that they need an IoC container, so they can hide the monolithic, highly coupled contraption they inevitably grew their application into.

The real solution, of course, is to fix the architecture. Split the application into multiple independent components that only have few dependencies on each other. In fact, you can use a nearby whiteboard to trivially turn your Main method into a tree diagram so you can see how to best cut your application into pieces. Maybe you’ll need to reverse some dependency arrows here and there (events to the rescue – or Observer if it’s 2002 and all you have is Java). You’ll end up with a bunch of independent parts, with the old content of Main spread across constructors of Facade-style entry point classes in these parts. Congratulations, you just forced yourself to fix your architecture by stubbornly avoiding IoC containers.

I really don’t understand why some programmers insist on hiding their bad designs from their own view. It’s like they don’t want to know that things are becoming a mess. IoC containers are to architecture what .NET regions are to classes.

* Or robots, or machines, or whatever your software runs on.

Advertisements

2 thoughts on “IoC containers: prozac for software architectures

  1. From my point of view if a programmer is using IoC container to hide an architecture weakness, it is a problem with immature developer rather than tool itself.
    I like the fact that I can configure once how to inject some interface (and have one place to do that) and I’m freed from keeping this knowledge in my brain’s cache. I can achieve this effect in other ways, but IoC containers seems to be exactly what I need for that purpose.
    What is more important to me, the container is maintaining object lifetime scope – and that is the value added of using IoC containers in right way.
    I totally agree that if the container is doing too much it is a good indicator to refactor the architecture.

    • Hi Matt,

      Thanks for commenting! I really can’t see the benefit an IoC container adds to object lifetime management. Aren’t you much more in control of that if you do it by hand? F.ex. if you want each query to open a new IDbConnection, you can just inject a DbConnectionFactory or a Func and have the factory/func decide whether to create a new object or not. How would hiding that away in a big chunk of magic and configuration be a benefit? I doubt you’d even save any lines of code.

      That said, I might be completely missing the point. Every time I needed to control object lifetime in an IoC container, it was because I needed to work around the default behaviour. Maybe there are cases that I’m missing where it’s a benefit and not a workaround.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s