Showing posts with label DI. Show all posts
Showing posts with label DI. Show all posts

Wednesday, July 6, 2011

Introduction to IoC Containers and Dependency Injection using StructureMap

In a previous article, I discussed the nature of the IoC principle as a separate entity from Dependency Injection. In this article I want to explain IoC Containers, and show how these can be used alongside Dependency Injection to create clean, testable, scaleable code, via decoupled architectures.

But before I explain what IoC Containers and DI are, let's talk about why you would want them.

Decoupled Architectures
In my IoC post, we looked at an example in which we handed over control to a GUI framework. I'm going to continue with that example here, and have included a cut-down version of the class in the codeblock below.

(I've renamed the class GuiFramework to GraphicUserInterface, because the original naming was only intended to highlight the differences between libraries and frameworks.)

public class BusinessLogic {

    private GraphicUserInterface gui = 
                    new GraphicUserInterface();

    public void Run(){
        gui.NamePrompt("Please enter your name");
        gui.AddNameChangedHandler(OnNameChanged);
    }
}

public class Program() {
    public static void Main() {
        BusinessLogic busLogic = new BusinessLogic();
        busLogic.Run();
    }
}

One of the main benefits of the IoC approach is that we have a separation of concerns. The GraphicUserInterface class handles all of the stuff to do with GUIs. The BusinessLogic class handles all of the stuff to do with business logic.

The business logic class manipulates the GUI class in order to implement business logic functionality, but it doesn't know anything about how, when or where the GUI does it's job. It simply uses the GUI's services and that's it.

So our architecture is almost decoupled. The only thing that still couples our architecture is that the business logic class directly instantiates an instance of the GraphicUserInterface class. With this setup we say that the BusinessLogic class depends on the GraphicUserInterface class, or that the GraphicUserInterface class is a dependency of the BusinessLogic class.

If we can properly decouple these components, then they become like 'plugins':

  • entirely independent of each other
  • entirely interchangeable with other components that provide the same or similar services
  • but still entirely inter-operable with each other - any plugged in component will work without adapting or making config changes to other components in the system - they will just 'plug and play'

Why That's Good
If you've worked with enterprise-level applications, or any application with more than a trivial number of components, it will be clear why this is positive. Here are a few important reasons:

  • Requirements changes - It is practically inevitable during any project that requirements will change. Decoupled architectures allow you to replace components in an existing system without having to adapt and recompile other components to match.
  • Unit testing - A decoupled component can be tested in isolation from it's dependencies, by mocking the dependencies. In this way unit tests can be run continuously throughout the project - and it becomes easy to have a development process in which your software always in a testable state. This is a huge advantage because it provides certain guarantees and confidence throughout. It also paves the way for TDD, which i'll discuss in another post.
  • Separation of concerns - it enforces an architecture where responsibilities are meted out to components neatly. This is nicer to work with, but it also has the practical benefit that if you bring a new developer onto the project, they can start work very quickly, and with a minimum of knowledge about the system. For example, if they are working on a data-access abstraction they need not ever have seen the UI - the responsibilities that this developer has will end at the boundary of the data-access abstraction, or whatever other component they are working on.

So let's see what that really means, by decoupling the example code, step by step.

Step 1: Use an Interface
Instead of referring to the implementation class directly by name, we'll use an interface. I've commented out the old declaration and added a new one.

public class BusinessLogic {

    //private GraphicUserInterface gui = new
    //                GraphicUserInterface();
    private IUserInterface userInterface;

    public void Run(){
        gui.NamePrompt("Please enter your name");
        gui.AddNameChangedHandler(OnNameChanged);
    }
}

public class Program() {
    public static void Main() {
        BusinessLogic busLogic = new BusinessLogic();
        busLogic.Run();
    }
}

First, notice the rename. The interface is called IUserInterface - not IGraphicUserInterface. This is important, because our business logic class doesn't need to know what kind of implementation it is dealing with. All it needs is the services of some kind of user interface, in order to prompt and accept a user's name. Exactly what kind of UI is unimportant - it could be a GUI or a web form or a speech recognition component - the BusinessLogic class doesn't care.

All the BusinessLogic class wants to know is that the class is capable of providing the services it requires. Implementation classes can indicate this capability by implementing the relevant interface - in this case IUserInterface.

Second, notice that we are not instantiating our new private userInterface member, only declaring it. Ofcourse if our application is going to work, the member will need to be instantiated - but how?

Step 2: Use Dependency Injection
We 'inject' a pre-instantiated object into our class:

public class BusinessLogic {

    private IUserInterface userInterface;

    public void BusinessLogic(IUserInterface aUserInterface){
        this.userInterface = aUserInterface;
    }

    public void Run(){
        gui.NamePrompt("Please enter your name");
        gui.AddNameChangedHandler(OnNameChanged);
    }
}

public class Program() {
    public static void Main() {
        BusinessLogic busLogic = new BusinessLogic();
        busLogic.Run();
    }
}

The approach used above is called Constructor Injection. Alternatively you could use Setter Injection, which is where you inject a dependency via a method (a setter method). In either case, the dependency is instantiated outside of the dependent class and injected in.

We'll use Constructor Injection in this example, and you'll see why a little later on.

Step 3: Set up an IoC Container
So where is the object instantiated? We need an IoC container.

These 'contain' the mappings required to wire up our dependencies. You'll hear them called DI containers too, but it means the same thing (there's a brief discussion on terminology at the bottom of this article).

I'm going to use StructureMap as an example because it's easy to use and has an intuitive syntax. First, we create a Bootstrapper. This becomes the single location within our program where concrete types are mapped to interfaces:

using StructureMap;

public static class Bootstrapper
{
    public static void Bootstrap()
    {
        ObjectFactory.Initialize(x =>
        {
            x.For<IUserInterface>().Use<GraphicUserInterface>();
            x.For<IBusinessLogic>().Use<BusinessLogic>();
        });
    }
}

StructureMap is one of a number of IoC Containers for .NET. Regardless of which container you use, you would expect to see all mappings declared inside a Bootstrapper, and the Bootstrapper to be created during initialisation (Global.asax for web applications, or the main routine for a desktop application).

StructureMap's Object Factory
The ObjectFactory mentioned in the codeblock above is a static wrapper for the StructureMap container. Whenever you use the ObjectFactory static class anywhere in your code, you are always referencing the same singleton container (it is possible to use more than one container object but this is not standard).

Once you have bootstrapped your mappings, you can use the static ObjectFactory reference anywhere in your code to instantiate an object by describing the service you require (passing in an interface name):

public class Program {
    public static void Main()
    {
        Bootstrapper.Bootstrap();
        var userInterface = 
            ObjectFactory.GetInstance<IUserInterface>();
    }
}

In the above example, the implicitly-typed var userInterface will now hold an instance of the GraphicUserInterface class.

Auto-Wiring
You might think at this stage, great - now we can just create a BusinessLogic object and send the userInterface object as an argument. But it's simpler than that, and this is one good reason to use Constructor Injection for your dependencies.

If you decouple all of your components, including (in this case) the BusinessLogic class, then StructureMap will figure out your dependencies for you using Auto-Wiring:

public class Program {

    public static void Main()
    {
        Bootstrapper.Bootstrap();

        //var userInterface = 
        //  ObjectFactory.GetInstance<IUserInterface>();
        var businessLogic = 
            ObjectFactory.GetInstance<IBusinessLogic>();

        businessLogic.Run();
    }
}

Notice that I have commented out the top line. Auto-wiring basically means that unless you tell the bootstrapper differently, any time you instantiate an object with dependencies StructureMap will create an instance of the dependency and inject it for you.

More With StructureMap
There's a lot more you can do with StructureMap, or any IoC Container. For example, you can wire up a singleton so that all dependencies resolve to a single instance:

x => x.For<IFoo>().Singleton().Use<Foo>()

You can use 'open generics', so that you can decouple your genericised classes. For example you might have a class Repository which could handle Book objects or Magazine objects, i.e. Repository<Book> or Repository<Magazine>. Using this syntax, you can declare mappings that are generics-agnostic:

x => x.For(typeof (IRepository<>)).Use(typeof (Repository<>))

You can specify an instance to use for particular constructor arguments. For example, if your class Foo is constructed with a string called argName:

x.For<IFoo>().Use<Foo>().Ctor<string>("argName").Is("arg");
//or
x.For<IFoo>().Use<Foo>().Ctor<string>("argName").
                           .EqualToAppSetting("app-setting-id");

This is ofcourse a whirlwind tour. Here are a few recommended links if you want to run off and figure out StructureMap now:

When To Use Which Approach
There will be times when Constructor Injection is not appropriate, and you need fine-grained control of object instantiation during program execution. In these circumstances you can use the ObjectFactory object as we did in the examples earlier:

var newFoo = ObjectFactory.GetInstance<IFoo>()

This gives you the same type of control over when things are instantiated as you get with ordinary coupled code. But it should be clear that the easiest approach whenever possible is to use Constructor Injection and let Auto-Wiring do the work for you. When this isn't possible move to Setter Injection, and when that isn't possible, use ObjectFactory to create an instance.

Decoupling Your Container
Ofcourse, ObjectFactory is a class defined within the StructureMap namespace. If you pepper it around your code (i.e. using GetInstance), then you are coupling your code to StructureMap. Some people prefer to ensure full decoupling from IoC Containers by housing Container references within custom object factories, and accessing those factories via an interface.

In another post I will discuss Autofac, a google code project and DI/IoC Container. Autofac, unlike StructureMap, ensures the container is fully decoupled by design. Instead of using a generic static Object Factory, Autofac allows you to create and inject custom object factories for use in your code.

The IoC/DI Name
You can see Martin Fowler here discussing the evolution of the name. Three different techniques / approaches have merged together to form a pattern, and so we have this composite name - IoC / DI / Container.

You can see what I mean if you consider that it's perfectly possible to use Dependency Injection without inverting control, or decoupling via interfaces:

public class BusinessLogic {

    private SomeLibrary someLibrary;

    public void BusinessLogic(SomeLibrary someLib){
        this.someLibrary = someLib;
    }
}

It's also possible to invert control without using DI, or to use containers without DI or IoC. However these approaches have grown to compliment each other and have become a mainstream approach to creating clean, testable, scaleable application architecures.

Wednesday, June 22, 2011

What is the Inversion of Control Principle?

Inversion of Control and Dependency Injection, IoC and DI. You hear them so often together in day-to-day lingo that it has become hard to separate them.

But they're not the same thing! DI is a specific form of the abstract IoC principle. So in this article I want to discuss and briefly explain IoC without going into DI. In another post I discuss IoC Containers, DI, and how to use the IoC/DI pattern to create clean, testable code.

But for now, what is IoC? To explain i'm going to very briefly jump back to basics - to explain what it is not.

Traditional Control of Flow
When I learned to program console applications, I learned to write functions (this is C-style pseudocode):

void printName(string name){
    print(name);
}

string readName(){
    print("What is your name?");
    string name = readLine();
    return name; 
}

... and to execute those functions from an execution-path entry point, i.e.:

void main(){
    string name = readName();
    printName(name);
}

If you expand much further from this simple example it quickly becomes clear that there is a central 'trunk' of execution (i.e. main()). This central trunk is flanked by large amounts of supporting code, in the form of functions (which in turn call more functions). All of the power to control program flow resides in the central trunk.

When we move on to OO, the functions became wrapped in classes, but the principle of centralised program flow control remained.

public class BusinessLogic {

    private string name;

    public void Run(){
        name = this.ReadName();
        Console.WriteLine(name);
    }

    private string ReadName(){
        Console.WriteLine("Please enter your name\n");
        name = Console.ReadLine();
    }
}

public class Program() {
    public static void Main() {
        BusinessLogic busLogic = new BusinessLogic();
        busLogic.Run();
    }
}

Ofcourse, with OO you end up with many more layers - your main Program class will instantiate objects and those objects will instantiate objects. But what we ended up with was a cluster of classes in the middle that control program flow, and you can draw a single line of execution through them. The classes in this cluster hand off tasks to a variety of library-style components (other classes, or 3rd-party libraries):

public class BusinessLogic {

    private string name;
    private CaseLibrary lib = new CaseLibrary();

    public void Run(){
        name = this.ReadName();
        name = this.UpperCase(name);
        this.PrintName();
    }

    private string ReadName(){
        Console.WriteLine("Please enter your name\n");
        name = Console.ReadLine();
    }

    private string UpperCase(string name){
        name = lib.UpperCase(name);
        Console.WriteLine(name);
    }
}

But libraries have very little freedom to control program flow. They can do what they like in responding to your requests, but they are little more than calculators, waiting for your application to give them some values and a specific task to do. They do the task and then return flow control to your central trunk.

So What is Inversion of Control?
IoC is all about handing control of program flow to somewhere other than the central trunk. It's a mainstream concept and the central principle of many event-driven architectures. IoC is commonly found in GUI applications, so in this example we'll use a framework to implement a GUI. This will mean handing over control to the (fictional) GuiFramework:

public class BusinessLogic {

    private string name;
    private GuiFramework gui = new GuiFramework();

    public void Run(){
        gui.NamePrompt("Please enter your name");
        gui.AddNameChangedHandler(OnNameChanged);
    }

    public void OnNameChanged(object sender, NameEventArgs e){
        name = e.Name;
        Console.WriteLine(name);
    }
}

Note that our application logic is still able to react to events in the GUI. This is done by assigning an EventHandler to the relevant framework object as a listener for NameChanged events. We hand over flow control to the framework, but we are able to insert our own code to respond to certain specific events. In this way we can customise the framework, but control is clearly inverted. Hence, Inversion of Control.

The Hollywood Principle
It's the oft-quoted phrase of IoC: "Don't call us, we'll call you." Once you hand over control to another component, you don't need to badger it with requests, or re-assume control. You just set up a listener and wait for the framework to call you back. You retain just enough code to handle your business logic, no more, no less.

So when using IoC with a number of framework-style components, control of the program is spread, and each component takes care of it's own responsibilities. Which is good, because a GUI framework knows more about how to render a GUI than does my application logic.

Frameworks vs. Libraries
As Martin Fowler points out, the IoC principle gives us a clear way to distinguish between libraries and frameworks:

"Inversion of Control is a key part of what makes a framework different to a library. A library is essentially a set of functions that you can call, these days usually organized into classes. Each call does some work and returns control to the client. A framework embodies some abstract design, with more behavior built in. In order to use it you need to insert your behavior into various places in the framework either by subclassing or by plugging in your own classes. The framework's code then calls your code at these points."

For more info, see Martin Fowler's article on Inversion of Control.

Or you can jump ahead to my article on IoC/DI Containers, and learn about the IoC/DI pattern.