Some IoC Container guidelines

So Derick Bailey asked me the other day a few weeks ago to describe how we use our IoC container.  I wouldn’t call it “best practices”, though some of these tips came from the creator of our container of choice, StructureMap (Jeremy Miller).  Although IoC containers are everywhere these days, you don’t see many instructions on where and how to use them.  We’ve developed a consistent approach to using our favorite container of choice, StructureMap.  The basic ideals behind our approach are:

Hiding the framework

If you look through one of our projects that use StructureMap, you’ll be hard pressed to find any usages of StructureMap.  In fact, one recent project had exactly one file that used StructureMap.

Just like any framework, littering your code with references and usages can make it nearly impossible to change to a different container.  I’ve heard this quite a bit, that it’s nice to change the framework you use at any time.  This has never actually happened with me, so I’m still dubious that anyone designing their application to be able to change frameworks at any time, actually has.  However, the less we litter our code with the framework, the less impact the framework has on our code. Bending design to accommodate usage can spoil benefits of the framework.

Looking at StructureMap, hiding the framework means preferring the fluent configuration or the xml configuration.  With fluent configuration, I get compile-time safety of all my types, and it plays well with refactoring tools like ReSharper.

Minimize calls to the container

Following the first rule, we shouldn’t have a lot of calls to our container to instantiate things.  Ideally, we would like to reduce our interaction with the service locator (ObjectFactory in StructureMap) to one call to get an instance.  We like to relegate the ObjectFactory calls to infrastructure-level code, such as the IInstanceProvider for WCF.

Reducing calls to the container from our code also greatly eases the burden in our tests.  It’s possible, but just annoying, to configure the container just for a unit test because our class calls directly into the container.  When the ObjectFactory call resides in some infrastructure piece, our entire domain layer can be completely free of any knowledge of the container.  While nice from a swappability perspective, its true value lies in a higher cohesion and greater separation of concerns.  If I don’t have to worry about StructureMap calls when I need to change a class, I can focus more on its core purpose.

Prefer constructor injection

Dependency injection comes in (basically) two flavors:

  • Property injection
  • Constructor injection

Property injection should be used only with optional dependencies.  An optional dependency is one that the class will still function properly.  Examples of optional dependencies are things like logging frameworks.  Constructor injection should be used for required dependencies.  A required dependency is one that the class will not function properly without it.

For users of a class, constructor injection through constructor arguments conveys far more meaning for required dependencies.  If a dependency is required, then it should be required for instantiation.  If you can’t use a class without a dependency, don’t let anyone use the class without it.

Prefer interfaces over abstract classes

This one is another in the “conveys more meaning” category.  An interface is a contract that conveys a concise set of operations.  I can do far more with interfaces than abstract classes, as interfaces support multiple inheritance, while classes do not.  If some default behavior is needed, I’ll supply an additional abstract class that implements the interface.

Test your configuration

Just like anything else in our system, automated tests find bugs in our configuration much faster and more efficiently than manual testing.  Automated tests are also far more reliable, of course.

Typically, we test any interesting configuration.  This includes the top-most dependencies in our system (which will then load the entire object graph), as well as any custom configured dependencies.  For array dependencies, we test that the class has the correct array with the items in the correct order.  Before we tested our configuration, we would get burned with error messages after running the software.  With automated tests in place, we have confidence that our container is configured correctly.

No calls to the container in a test

Unless you’re testing the container, the container should not show up in your unit test.  If we’re following the first two rules laid out, we don’t have any work to do.  If I need to configure the container for a unit or integration test, it’s a good sign that I’m doing something wrong.  Configuring the container inside a test is possible, but it muddies the intent of the test.  The container then becomes another opaque dependency, which defeats the purpose of using an inversion of control container.

Guidelines aren’t rules

Of course, there are always exceptions here.  But I always take a second look at my code if I feel it’s necessary to not follow the above guidelines.  It’s a smell that I’m probably doing something wrong.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

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 StructureMap. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://colinjack.blogspot.com Colin Jack

    Good guidelines one and all.

  • http://www.derickbailey.com Derick Bailey

    ‘BOUT TIME! :)

    All of these guidelines are things that I’ve been learning the hard way, recently. I’ve come to many of the same conclusions in my own head, based on having done things “the wrong way” for the last 2 years. It’s a huge relief to see that I’m on the right track, and it’s also great to have some of these thoughts articulated in a manner that I can better share with my team.

    I do have one remaining question, though… the IInstanceProvider is an example I understand very well – I did this in my current project, about a year ago. But I’m having a hard time seeing other examples in my head. Can you give another example or two, of where you would hide the IoC calls, in a more simple application – just a winforms app, no client/server/soa stuff?

    thanks again! great info.

  • Kerry MacLean

    Great job. I’ve got a long way to go to implement, but this kind of quality post really helps keep my eye on where the right track is.

  • Ted

    For a winforms app, one of the things you’ll probably run into a lot is the need to create objects in response to a user event. One example would be a form with a datagrid popping open an edit form to edit the details of an item. For that I have an IApplicationController interface with a ShowEditView(object DataItem) method. The application controller implementation needs a reference to the container, but the rest of the code just depends on IApplicationController instance and doesn’t need to reference the container. I’ve actually wrapped my container in its own generic interface, which it registers itself in the setup, and all the other classes depend on that.

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @Ted

    That’s cool, I have very little experience with WinForms, so it’s cool to see how it would all work in that paradigm.

  • jorge

    Jimmy,

    Im in no position to argue with anything you’ve said, but exactly how often do you find yourself switching IoC containers? Although I have seen the exact same argument dozens of times in the past couple of years, I’ve used Windsor and Unity successfully on previous projects and have not once felt the need to suddenly scrap one to take advantage of another.

  • http://weblogs.asp.net/jvano joey

    You mentioned that you have IoC code typically only in one place. Is this because you are only developing Monorail, ASP.NET MVC or WCF applications? This affords you the luxury of declaring the IoC container in one location (global.asax or IInstanceProvider)

    @Jorge, the answer is in the article.

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @joey

    No, unfortunately I moved on from those technologies around the same time I “got” IoC containers. I’d suggest putting that question on the StructureMap (or container of your choice) users group, someone is bound to have solved those problems.

  • http://rauhski.blogspot.com Ryan Rauh

    Very good post thank you! Totally agree with everything mentioned… I’ve been looking for a good reference for IoC guidelines, Thanks

  • Pingback: Defining Symfony 2 controllers in two ways - nschoenmaker.nl