Los Techies : Blogs about software and anything tech!

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.

Kick It on DotNetKicks.com
Posted Sep 12 2008, 08:10 AM by bogardj
Filed under:

Comments

Colin Jack wrote re: Some IoC Container guidelines
on 09-12-2008 8:24 AM

Good guidelines one and all.

Derick Bailey wrote re: Some IoC Container guidelines
on 09-12-2008 8:35 AM

'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 wrote re: Some IoC Container guidelines
on 09-12-2008 9:17 AM

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.

Arjan`s World » LINKBLOG for September 12, 2008 wrote Arjan`s World » LINKBLOG for September 12, 2008
on 09-12-2008 9:58 AM

Pingback from  Arjan`s World    » LINKBLOG for September 12, 2008

Ted wrote re: Some IoC Container guidelines
on 09-12-2008 10:07 AM

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.

Bogard’s IOC Container Guidelines wrote Bogard’s IOC Container Guidelines
on 09-12-2008 12:20 PM

Pingback from  Bogard’s IOC Container Guidelines

bogardj wrote re: Some IoC Container guidelines
on 09-12-2008 7:47 PM

@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 wrote re: Some IoC Container guidelines
on 09-13-2008 12:42 AM

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.

joey wrote re: Some IoC Container guidelines
on 09-13-2008 5:57 AM

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.

Dew Drop - September 13, 2008 | Alvin Ashcraft's Morning Dew wrote Dew Drop - September 13, 2008 | Alvin Ashcraft's Morning Dew
on 09-13-2008 8:53 AM

Pingback from  Dew Drop - September 13, 2008 | Alvin Ashcraft's Morning Dew

Reflective Perspective - Chris Alcock » The ‘Morning’ Brew #179 wrote Reflective Perspective - Chris Alcock » The ‘Morning’ Brew #179
on 09-15-2008 7:52 AM

Pingback from  Reflective Perspective - Chris Alcock  » The ‘Morning’ Brew #179

bogardj wrote re: Some IoC Container guidelines
on 09-15-2008 9:10 PM

@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.

DotNetKicks.com wrote Universal Guidelines for IoC Containers
on 09-16-2008 12:31 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Code Monkey Labs wrote Weekly Web Nuggets #30
on 09-21-2008 11:21 PM

General Some IoC Container Guidelines : Jimmy Bogard presents some good guidelines for working with your IoC container of choice. Lambdas – Know Your Closures : Jason Olson exposes a tricky behavior of lambdas that can bite even folks that consider themselves

new ThoughtStream("Derick Bailey"); wrote DI and IoC: Creating And Working With A Cloud Of Objects
on 10-07-2008 8:18 PM

A few months ago, I posted some thoughts and questions on the proper use of Inversion of Control (IoC

Code Monkey Labs wrote Weekly Web Nuggets #30
on 02-22-2009 9:45 PM

General Some IoC Container Guidelines : Jimmy Bogard presents some good guidelines for working with your IoC container of choice. Lambdas – Know Your Closures : Jason Olson exposes a tricky behavior of lambdas that can bite even folks that consider

Ryan Rauh wrote re: Some IoC Container guidelines
on 04-08-2009 11:55 AM

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

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems