Inversion of Control, Dependency Injection and Service Locators oh my!

This post is part of my “Software Development” series. The TOC for the entire series can be found here.



In this post, we’re going to look, at a higher level, at the reasons for and benefits of using a framework for Inversion of Control (IoC), Dependency Injection (DI) and Service Location. I’m not going to spend a large amount of time in this blog series describing the intimate details of what IoC, DI and Service Locators are.  Martin Fowler did a fantastic job of it and there’s no point in me just regurgitating his work.


Instead, I’ll give my vision of what they are and how they are relevant to how I architect and develop solutions.  It’s important to note that I’m starting out this series with high-level thoughts about architecture and design.  I’m not just laying down some code, leaving the decisions about how things will interact to some arbitrary, organic process.  This is how software development gets done. 


You’ve got to think about not just the next step, but visualize the end point several months, or even years out and try to connect the dots back to where you are today.  If I implement something in a certain way today, is it going to screw me 3 months down the road?  Spending an extra day now thinking about architecture is going to turn into saving weeks of the customer breathing down your neck and you pull out your hair and work late night trying to hammer a square peg into a round hole.


So let’s look at IoC, DI and Service Location and how they’re going to help us build better software.  Inversion of Control as a concept is something that’s really broad.  It’s really anything that turns the older procedural way of developing upside down (i.e. inverts program control, hence the name).  Moving from a console app to a windowed, event-driven app is technically inversion of control, so you’ve already been using IoC. 


To talk about IoC as a useful concept that’s actually going to be of use, we’ll be using some smaller units/principals of IoC.  The two we’re going to look at are Dependency Injection, or DI, and Service Location.  Neither one is complex or arcane, and you probably already use them to some degree.


Let’s assume we have two arbitrary classes, A and B, and that A uses an instance of B internally.  There are, essentially, 3 ways that A can get the instance of B. 


First, it can directly create it by calling new B().  While this is simple, it’s the least preferred, and generally worst, way to do it.  By directly creating B, A is now tightly coupled to B’s implementation.  B can’t be easily changed out to something else.  If B is in another assembly, A has to have a reference to it.  It’s also difficult to test A by itself. 


The second way that A can get B is that whoever created the instance of A could pass into it an instance of B.  Maybe through a constructor

var b = new B();
var a = new A(b);

or through a property

var b = new B();
var a = new A();
a.B = b;

This is called Dependency Injection. The former is constructor injection, the latter is property injection – not so complex, eh?  This is useful because, if B is an interface, it’s really easy to swap out the implementation passed to A and the assembly containing A doesn’t necessarily have to have a reference to the assembly holding the implementation of B – it only needs a reference to the interface.  This is really nice when we want to do mocking.


The third way that A can get B is to go get it from some central repository or “factory”.

B B { get; set; }

public A()
{
this.B = MyClassFactory.GetB();
}


This is service location.  A doesn’t really know what B is, it lets the service locator (MyClassFactory) resolve that.  This is really helpful for plug-in architectures as well as for lazy loading objects.


Generally speaking, your code should only be doing #2 (DI) and #3 (service location) for objects of any complexity.  This is not to say that you shouldn’t ever call the new operator in your code.  There’s obviously a grey line out there below which it would be pretty stupid to not just use new for.  If you need to use a simple entity class or structure, then creating one makes sense.  If you need access to the DAL and I see you creating a DAL object in your View, you’re fired.


There are plenty of framework out there that provide DI and service location –  Ninject, Unity, CastleWindsor, StructureMap, Autofac – the list goes on and on.  Instead of using one of them, however, I chose to roll my own.  Normally I wouldn’t recommend such a drastic action – after all reinventing the wheel isn’t usually wise – but in my case it was essentially required, so I’ll give you the short back story.


My team and I had been working on a large desktop application.  We had designed it from the start using Microsoft’s SCSF/CAB framework, which provide DI, service location and a load of other stuff.  It turned out that we were using maybe 10% of the framework, and that the framework’s Studio plug-ins were causing fits with some installations of Studio.  Spending time screwing with Studio plug-ins and trying to get things to compile is a terrible waste of manpower, so we were already getting close to jettisoning it when we decided that we wanted the core of our app logic to be Compact Framework compatible.


Well Microsoft’s “port” of the SCSF to the Compact Framework, called the MCSF, turns out to be a bloated, unbelievably slow, steaming pile of dog crap.  Side note: just because something compiles under the Compact Framework does not mean it should be used in the Compact Framework.  Well, I didn’t want to refactor everything we’d done to some other IoC framework, plus I couldn’t find one at the time that actually worked for the Compact Framework, so I decided to create one. 


I took the tack that I’d create it for the CF first, with a high emphasis on small footprint, minimal resource usage and speed and I simply matched the SCSF object model where our code base interfaced with it and where it made sense – in some places I didn’t like how the SCSF had done things, so I “fixed” their mistakes.  The end result was the OpenNETCF.IoC framework, which turns out to stack up quite well against the other frameworks.  It also has the huge benefit of working on the Full Framework, Windows Phone 7 and MonoTouch (probably MonoDroid as well, though I’ve not tested that). We’ll be looking at OpenNETCF.IoC in a lot more depth in this series.

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