Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Foundations of Programming – pt 4 – Dependency Injection

It’s common to hear developers promote layering as a means to provide extensibility. The most common example, and one I used in Part 2 when we looked at interfaces, is the ability to switch out your data access layer in order to connect to a different database. If your projects are anything like mine, you know upfront what database you’re going to use and you know you aren’t going to have to change it. Sure, you could build that flexibility upfront – just in case – but what about keeping things simple and You Aren’t Going To Need IT (YAGNI)?

I used to write about the importance of domain layers in order to have re-use across multiple presentation layers: website, windows applications and web services. Ironically, I’ve rarely had to write multiple front-ends for a given domain layer. I still think layering is important, but my reasoning has changed. I now see layering as a natural by-product of highly cohesive code with at least some thought put into coupling. That is, if you build things right, it should automatically come out layered.

The real reason we’re spending a whole part on decoupling (which layering is a high-level implementation of) is because it’s a key ingredient in writing testable code. It wasn’t until I started unit testing that I realized how tangled and fragile my code was. I quickly became frustrated because method X relied on a functional class Y which needed a database up and running. In order to avoid the headaches I went through, we’ll first cover coupling and then look at unit testing in the next part.

(A point about YAGNI. While many developers consider it a hard rule, I rather think of it as a general guideline. There are good reasons why you want to ignore YAGNI, the most obvious is your own experience. If you know that something will be hard to implement later, it might be a good idea to build it now, or at least put hooks in place. This is something I frequently do with caching, building an ICacheProvider and a NullCacheProvider implementation that does nothing, except provide the necessary hooks for a real implementation later on. That said, of the numerous guidelines out there, YAGNI, DRY and Sustainable Pace are easily the three I consider the most important.)

Sneak Peak at Unit Testing
Talking about coupling with respect to unit testing is something of a chicken and egg problem – which to talk about first. I think it’s best to move ahead with coupling, providing we cover some basics about unit testing. Most importantly is that unit tests are all about the unit. You aren’t focusing on end-to-end testing but rather on individual behavior. The idea is that if you test each behavior of each method thoroughly and test their interaction with one and other, you’re whole system is solid. This is tricky given that the method you want to unit test might have a dependency on another class which can’t be easily executed within the context of a test (such as a database, or a web-browser element). For this reason, unit testing makes use of mock classes – or pretend class.

Let’s look at an example, saving a car’s state:

public class Car
{
   private int _id;     
   public void Save()
   {
      if (!IsValid())
      {
         //todo: come up with a better exception
         throw new InvalidOperationException("The car must be in a valid state");
      }
      if (_id == 0)
      {
         _id = DataAccess.CreateInstance().Save(this);
      }
      else
      {
         DataAccess.CreateInstance().Update(this);
      }
   }
   private bool IsValid()
   {
      //todo: make sure the object is in a valid state
      return true;
   }
}

To effectively test the Save method, there are three things we must do:

  1. Make sure the correct exception is thrown when we try to save a car which is in an invalid state,
  2. Make sure the data access’ save method is called when it’s a new car, and
  3. Make sure the Update method is called when it’s an existing car.

What we don’t want to do (which is just as important as what we do want to do), is test the functionality of IsValid or the data access’ Save and Update functions (other tests will take care of those). The last point is important – all we want to do is make sure these functions are called with the proper parameters and their return value (if any) is properly handled. It’s hard to wrap your head around mocking without a concrete example, but mocking frameworks will let us intercept the Save and Update calls, ensure that the proper arguments were passed, and force whatever return value we want. Mocking frameworks are quite fun and effective….unless you can’t use them because your code is tightly coupled.

Not ALL coupling is bad
In case you forgot from Part 1, coupling is simply what we call it when one class requires another class in order to function. It’s essentially a dependency. All but the most basic lines of code are dependent on other classes. Heck, if you write string site = “CodeBetter”, you’re coupled to the System.String class – if it changes, your code could very well break. Of course the first thing you need to know is that in the vast majority of cases, such as the silly string example, coupling isn’t a bad thing. We don’t want to create interfaces and providers for each and every one of our classes. It’s ok for our Car class to hold a direct reference to the Upgrade class – at this point it’d be overkill to introduce and IUpgrade interface. What isn’t ok is any coupling to an external component (database, state server, cache server, web service), any code that requires extensive setup (database schemas) and, as I learnt on my last project, any code that generates random output (password generation, key generators). That might be a somewhat vague description, but after this and the next part, and once you play with unit testing yourself, you’ll get a feel for what should and shouldn’t be avoided.

Since it’s always a good idea to decouple your database from your domain, we’ll use that as the example throughout this part.

Dependency Injection
In Part 2 we saw how interfaces can help our cause – however, the code provided didn’t allow us to dynamically provide a mock implementation of IDataAccess for the DataAccess factory class to return. In order to achieve this, we’ll rely on a pattern called Dependency Injection (DI). DI is specifically tailored for the situation because, as the name implies, it’s a pattern that turns a hard-coded dependency into something that can be injected at runtime. We’ll look at two forms of DI, one which we manually do, and the other which leverages a third party library.

Constructor Injection
The simplest form of DI is constructor injection – that is, injecting dependencies via a class’ constructor. First, let’s look at our DataAccess interface again and create a fake (or mock) implementation (don’t worry, you won’t actually have to create mock implementations of each component, but for now it keeps things obvious):

internal interface IDataAccess
{
   int Save(Car car);
   void Update(Car car);
}
internal class MockDataAccess : IDataAccess
{
   private readonly List<Car> _cars = new List<Car>();
   public int Save(Car car)
   {
      _cars.Add(car);
      return _cars.Count;
   }
   public void Update(Car car)
   {         
      _cars[_cars.IndexOf(car)] = car;
   }
}

Although our mock’s upgrade function could probably be improved, it’ll do for now. Armed with this fake class, only a minor change to the Car class is required:

public class Car
{
   private int _id;
   private IDataAccess _dataProvider;
   public Car() : this(new SqlServerDataAccess())
   {
   }
   internal Car(IDataAccess dataProvider)
   {
      _dataProvider = dataProvider;
   }
   public void Save()
   {
      if (!IsValid())
      {
         //todo: come up with a better exception
         throw new InvalidOperationException("The car must be in a valid state");
      }
      if (_id == 0)
      {
         _id = _dataProvider.Save(this);
      }
      else
      {
         _dataProvider.Update(this);
      }
   }
   private bool IsValid()
   {
      //todo: make sure the object is in a valid state
      return true;
   }
}

Take a good look at the code above and follow it through. Notice the clever use of constructor overloading means that the introduction of DI doesn’t have any impact on existing code – if you choose not to inject an instance of IDataAccess, the default implementation is used for you. On the flip side, if we do want to inject a specific implementation, such as a MockDataAccess instance, we can:

public void AlmostATest()
{
   Car car = new Car(new MockDataAccess());
   car.Save();
   if (car.Id != 1)
   {
      //something went wrong
   }
}

There are minor variations available – we could have injected an IDataAccess directly in the Save method or could set the private _dataAccess field via an internal property – which you use is mostly a matter of taste.

Frameworks
Doing DI manually works great in simple cases, but can become unruly in more complex situations. A recent project I worked on had a number of core components that needed to be injected – one for caching, one for logging, one for a database access and another for a web service. Classes got polluted with multiple constructor overloads and too much thought had to go into setting up classes for unit testing. Since DI is so critical to unit testing, and most unit testers love their open-source tools, it should come as no surprise that a number of frameworks exist to help automate DI. The rest of this article will focus on StructureMap, a Dependency Injection framework created by fellow CodeBetter blogger Jeremy Miller. (http://structuremap.sourceforge.net/)

Before using StructureMap you must configure it using an XML file (called StructureMap.config) or by adding attributes to your classes. The configuration essentially says this is the interface I want to program against and here’s the default implementation. The simplest of configurations to get StructureMap up and running would look something like:

<StructureMap>
  <DefaultInstance PluginType="CodeBetter.Foundations.IDataAccess, CodeBetter.Foundations" 
                   PluggedType="CodeBetter.Foundations.SqlServerDataAccess, CodeBetter.Foundations" /> 
</StructureMap>

While I don’t want to spend too much time talking about configuration, it’s important to note that the XML file must be deployed in the /bin folder of your application. You can automate this in VS.NET by selecting the files, going to the properties and setting the Copy To Ouput Directory attribute to Copy Always. (There are a variety of more advanced configuration options available. If you’re interested in learning more, I suggest the StructureMap website).

Once configured, we can undo all the changes we made to the Car class to allow constructor injection (remove the _dataProvider field, and the constructors). To get the correct IDataAccess implementation, we simply need to ask StructureMap for it, the Save method now looks like:

public class Car
{
   private int _id;
   public void Save()
   {
      if (!IsValid())
      {
         //todo: come up with a better exception
         throw new InvalidOperationException("The car must be in a valid state");
      }
      IDataAccess dataAccess = ObjectFactory.GetInstance<IDataAccess>();
      if (_id == 0)
      {
         _id = dataAccess.Save(this);
      }
      else
      {
         dataAccess.Update(this);
      }
   }
   private bool IsValid()
   {
      //todo: make sure the object is in a valid state
      return true;
   }
}

To use a mock rather than the default implementation, we simply need to inject the mock into StructureMap:

public void AlmostATest()
{
   ObjectFactory.InjectStub(typeof(IDataAccess), new MockDataAccess());
   Car car = new Car();
   car.Save();
   if (car.Id != 1)
   {
      //something went wrong
   }
   ObjectFactory.ResetDefaults();
}

We use InjectStub so that subsequent calls to GetInstance return our mock, and make sure to reset everything to normal via ResetDefaults.

DI frameworks such as StructureMap are as easy to use as they are useful. With a couple lines of configuration and some minor changes to our code, we’ve greatly decreased our coupling which increased our testability. In the past, I’ve introduced StructureMap into existing large codebases in a matter of minutes – the impact is minor.

Conclusion
Reducing coupling is one of those things that’s pretty easy to do yet yields great results towards our quest for greater maintainability. All that’s required is a bit of knowledge and discipline – and of course, tools don’t hurt either. It should be obvious why you want to decrease the dependency between the components of your code – especially between those components that are responsible for different aspects of the system (UI, Domain and Data being the obvious three). In the next part we’ll look at unit testing which’ll really leverage the benefits of dependency injection. If you’re having problems wrapping your head around DI, take a look at my more detailed article on the subject at http://dotnetslackers.com/articles/designpatterns/IntroducingDependencyInjectionFrameworks.aspx.

This entry was posted in Featured, Foundations. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

11 Responses to Foundations of Programming – pt 4 – Dependency Injection

  1. karl says:

    Part 5 dealt with nunit and rhinomcoks:
    http://codebetter.com/blogs/karlseguin/archive/2007/12/20/foundations-of-programming-part-5-unit-testing.aspx

    As for your specific questions, I’m not too sure. StructureMaps should look for the .config file in the /bin folder..essentially it looks for it where its own .dll is deployed (which should be along with all your other code).

    Every .NET application has an AppDomain..you can’t host a .NET application on without loading it within an AppDomain

  2. Bill Campbell says:

    Karl,

    Just what I was looking for! What a great article with most of the info that I was looking for. It all makes perfect sense to me – but I still couldn’t run with StructureMap. As it turns out, S/M couldn’t find the config file and it was looking for it down in C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE. I put it there and everything works. It appears that when I am running in my MSTest context for my unit tests that there is not an Application Domain set up. I am still trying to figure out how to do that, but wondered if you have to do that so S/M knows where to find your StructureMap.config? I didn’t see it in any of the articles that I read. It appears that my application also does not have a app domain set up either so I need to figure this out as well. Anyhow, just wondered if there was a simple answer to the test case?

    Again – thanks for the information and great articles. You haven’t written in depth about RhinoMocks have you? If you have, I sure would enjoy the kind of detail that you had written about StructureMap.

  3. karl says:

    Bill:
    I generally put a “References” folder inside my core assembly (say CodeBetter.Foundations, which has all my domain logic), and have all other projects reference the dll’s in there. For the .config file, your best bet is to put it at the root of your project, and in the properties of the file select “copy always”. You’ll need to a StructureMap.config in each executable project..but aside from that, there should be no extra initialization steps required.

    Take a look at:
    http://dotnetslackers.com/articles/designpatterns/IntroducingDependencyInjectionFrameworks.aspx which is an older structuremap article I wrote, and see if it doesn’t help…it’s a bit more hands-on.

  4. Bill Campbell says:

    Karl,

    This whole series has been excellent!. After re-reading them all several times and coming back to ths one, I have been trying to figure out how to use StructureMap for my DI instead of constructor injection – which has been getting a little messy. To be honest though, I can’t figure out how to make this work in my project. I am sure that I”m overlooking something. I have multiple projects (about a dozen) with one being a WPF smart client. I can’t quite figure out where to put everything – like the dll can go anywhere just everyone needs to ref it, right? And if I put the .config file in the bin\debug directory where some of the dll’s live that include the assy’s that I want to use, is that correct as well? I only need one copy of the structuremap.dll, right not one in each project. And it sounds like there is some startup code that needs to be written and I haven’t been able to figure that out. Right now I am trying to use one interface and one concrete class and then use unit tests to inject a mock class. Any pointers would be greatly appreciated as I’ve been reading on the sourceforge site most of the day and still haven’t been able to figure it out. It looks like there are many different ways to set this up, but I’m not sure.

    Again, thanks for the great articles!
    regards,
    Bill

  5. Great article! As Brad mentioned, these articles are great for all developers.

  6. Bill Campbell says:

    Great Job! Keep ’em coming!

  7. Brad says:

    These are awesome Karl! You’re really helping Morts like me ramp up on concepts I’ve been trying to wrap my brain around. I hope there are a lot more of these in the pipeline.

  8. Dima says:

    Great post!

  9. karl says:

    John: Yes, I’ve hidden the specific DI implementation away into a static call before. So I keep my DataProvider.CreateInstance which uses StructureMap. It’s a pretty small change and one that can net some good gains. To be honest though, it hasn’t come in handy yet…On a large project I’d probably take the safe route and do it that way though.

    Fedde: Just don’t know it. It’s a goal of mine to learn a different .NET DI framework than StructureMap.

  10. Fedde says:

    Why not use Castle Windsor? That way you could also use setter injection and/or a facility to inject stuff..

    Disclaimer: I haven’t had the chance to look into structuremap so I can’t compare them

  11. John Chapman says:

    Great post. I just finished a post of my own where I was talking about how impressed I was with mocking frameworks to allow for improved testability in cases like you show.

    One question for you though, at what point do you consider StructureMap itself a dependency on the your business objects? I’m not sure I’m sold on the business objects having direct access to the DI framework. It seems like a developer could get themselves in to a bit of trouble here accessing services which they have no business accessing. What do you think?