Sunday, March 8, 2009

Real World Dependency Injection

On Thursday I gave a talk on Real World TDD at the Perth .Net Community of Practices. I'm not sure what people were expecting but the turn out was incredible, standing room only.. Hopefully I gave the punters what they were hoping for. A lot of secondary topics were raised, one being the notion of design and allowing TDD to help shape good design by following the SOLID principles. Dependency Injection was probably the most notable and for some people this may have been somewhat unusual. This article hopes to explain why we use DI and how we can use it in the real world.

What is Dependency Injection

Dependency Injection or dependency inversion is the idea that we depend on abstractions not concrete implementations. The example I gave in the talk was a trivial one using a logger as an example. Most of us use some sort of logging in our code so a lot of our code has a concrete dependency to a logging class eg:

public void DoSomething()
{
Logger.Log("Entering Do Something");
//Do the thing you wanted
Logger.Log("Exiting Do Something");
}


Why do we use it



In the example above, if we wanted to change the logger we used we would have to go into this code and change it, in fact we would most likely have to change it in every method call for something as prolific as logging. That is a lot of changes. Not only this but the reuse of this code without DI is limited and you will have to pass around the concrete logger as a reference to anything that wants to use it. This is not a big deal for logging but what if you had some potentially reusable components? Those concrete dependency will be come painful, reducing reusability very quickly. An example that parallels DI that many .Net developer will be familiar with is the Plug In pattern. Asp.Net membership is an example of this, in which we specify what type of provider we are going to using for membership. Our code doesn't change all we need to do is change the config in one place and the implementation is changed.



When do we use it



I will use DI anywhere that I have a dependency that is not static. (This may not be the best rule of thumb but it is how I do it, the number of static helper classes I have are minimal so this is not a big deal for me.)



Take for example we are using the MVP pattern; the presenter has a dependency on a view and on the model. The view however does not have a dependency on the presenter (despite what many coding samples out there may say) and the model does not have a dependency on the presenter but may do on other models data access components or services etc. Assume we have decided that the presenter is not in a valid state without these dependencies; We therefore decide that these should be injected as constructor items.



public class FooPresenter
{
private readonly IFooView view;
private readonly IFooModel model;

public FooPresenter(IFooView view, IFooModel model)
{
//DBC checks eg null checks etc
this.view = view;
this.model = model;
}
//rest of the presenter
}


Note: by stipulating the dependencies are read only they must be assigned by the end of the constructor. To me, this helps clarify the intention and I tend to use this over private properties eg



//I dont like this for constructor dependencies, 
//but it is valid
public IFooView View { get; private set; }




The presenter is now only dependent on the interfaces of the view and model. we can change From Winforms to WPF without any dramas, we can move from a web service based model to an EF model... we don't care about how the dependencies do their job,, they just have to adhere to the contract that is the interface.



To me this is critical part of TDD. This allows me to focus on the task at hand, eg writing the presenter, without having to worry about coding the model and view at the same time; all I have to do is create the interfaces that they have to adhere to while I create the presenter. This is typically done all at the same pace. I may decide I need to raise an event from the view, say "AddFooRequest". I create a test to listen for that event in the presenter test, create the event on the view interface, create a handler for the event in the presenter and wire it up. I have not done any concrete code in the view, just view interface, concrete presenter and its test fixture. This to me is already a huge benefit of DI.



How do  use it



The first problem people run into when using DI is when they try and plug pieces together. Basically we have stated that the object should not know about its concrete dependency, but something has to! Is it the object that is calling it? It would be silly if presenter A did not know about its dependencies but when navigating to presenter B it new about those dependencies so it could construct presenter B... we there are 2 realistic ways around it, "Poor Mans DI" and "Inversion of Control" containers.



Poor mans DI is a way of saying "I don't want to code to implementations, but I will anyway". Its actually a pretty good place to start when DI is still a relatively new concept. You basically have defaults in your class and allow for them to be overridden eg:



public class FooPresenter
{
private readonly IFooView view;
private readonly IFooModel model;

//Poor mans DI
public FooPresenter()
:this(new FooView(), new FooModel())
{}

//Complete ctor allowing for DI
public FooPresenter(IFooView view, IFooModel model)
{
//DBC checks eg null checks etc
this.view = view;
this.model = model;
}
//rest of the presenter
}


The problem with this is that if you are using DI everywhere then (in this example) the presenter will have to know how to create the model or the model will have to have poor mans DI too.



A better option is to have one place that knows how to construct things, like a big object factory. This is called your Inversion of Control container and a usually third party API's that become a critical part of you framework. Such containers are godsends in large projects and allow for quickly changing dependencies for whole solutions very quickly and cleanly. The common containers are StructureMap, Castle (Windsor) , Spring.net, Unity, Ninject etc. You will most likely at first use a tiny portion of these container capabilities, generally resolve and setting the concrete type to construct for a given abstraction. eg



//set a default for the whole application
Container.AddComponent<IFooModel, FooNhibernateRepository>();
Container.AddComponent<IFooView, FooWinFormView>();
Container.AddComponent<IFooPresenter, FooPresenter>();

//Retrive a concrete instance from the container
var presenter = Container.Resolve<IFooPresenter>();


The Container.Resolve call on the last line asks for the concrete instance of IFooPresenter. We have defined that above as been the concrete FooPresenter. We know that the FooPresenter has dependencies on IFooView and IFooService so the container will look for registered components too and try to instantiate them. We have specified that we want the container to create a FooNhibernateRepository any time we ask for an IFooModel and a FooWinFormView any time we ask for an IFooView. Most IoC containers will tend to take the greediest constructor (the one with the most parameters) so you can even migrate from poor mans DI to an IoC implementation quite smoothly.



NB: This is a generic wrapper that I use as I tend to use a different container depending on the employer/contract I work on, so I use an adapter pattern to isolate me from the varying syntax. If this approach appeals then check out the Common Service Locator at CodePlex



I hope this helps people move towards better designed software and an easier to use and looser, decoupled API.



Rhys

1 comment:

RhysC said...

For more information on DI check out the for coming Manning publication on DI: http://www.manning.com/prasanna/