Basic to Basics: Understanding IoC Part 2 (Creation)
In my last back to basics post we talked about what inversion of control (IoC) is in regards to inverting control of interfaces.
We looked at how we can benefit from changing the control of the interface from the service to the client of that service.
This time we are going to tackle the more common form of IoC that is quite popular these days, and I’m going to show you why dependency injection is only one way to invert the control of the creation of objects in our code.
What is creation inversion?
In a normal everyday code we usually create objects by doing something like:
MyClass myObject = new MyClass();
We usually do this creation of objects inside of the class that is going to use or needs that object.
If we used interface inversion, we would probably end up with a declaration like:
IMyInterface myImplementation = new MyImplementation();
You can see that even though the interface may have been inverted we are still controlling the creation of the object from inside the class that uses the object.
Let’s withhold our judgment of whether this is a bad thing or not until we fully understand the idea of creation inversion and the problem it is trying to solve.
So we can see clearly that the normal control is that objects that are used by a class are created by the class using the object.
If we wanted to invert this control, we would say that objects that are used by a class are created outside of the class using the object.
There, you understand IoC in regards to creation. If you create the object you are going to use inside your class, you are not inverting control. If you create the object somewhere else, you are inverting control.
Before we talk about how, let’s talk about why
Why would you want to invert control of the creation of your objects?
If you are familiar with design patterns, factory pattern should have just popped into your head when you read that statement. If you are not familiar with design patterns, let me suggest either reading the original gang of four Design Patterns book, or the highly recommended Head First Design Patterns.
I mention the factory pattern because you might want to implement inversion of control for the same types of reasons why you would want to use the factory pattern.
Shh… I’ll tell you a little secret if you promise not to tell the cool IoC container / DI kids. The factory pattern is inversion of control!
Let’s use factory pattern to tell us why we would want to invert control. The description of factory pattern is:
Centralize creation of an object of a specific type choosing one of several implementations.
From that description we can deduce that we might want to use the factory pattern or some other form of inversion of control anytime we have an object or interface that has several different implementations and we want to put the logic of choosing which implementation to use in a single location.
Let’s use the classic example of having a skinnable UI.
If we have a UI framework that includes classes like Button, DropDownList, TextBox, etc, and we want to make it so that we can have differently skinned implementations of each UI control, we don’t want to put a bunch of code into all of our screens in our application like:
If we can somehow move the creation of the right kind of object outside of our classes and put it in one place, then we can eliminate all this duplication. This prize comes at a price. The price is control. For convenience sake we must rip the control of the creation of button from our UI screens and give them to a central authority who doles out buttons at this whim.
We need a mediator that says to our UI screen classes, “You want a button? I got button for ya, and you don’t need to know what kind, cause it’s none of your business. All you need to know is it’ll be a button.”
I’ll harp on this more later, but I want to bring up the point here before we move on. Why would you use inversion of control when you don’t have a problem of needing to select from more than one implementation of an interface or class?
How can I gets me some of this IoC goodness?
So let’s talk about how to implement inversion of control.
I’m not going to cover every conceivable way that you could invert control in regards to creation, but I will focus on a few common ways to do so.
Let’s start here since we already mentioned it. In our case above we could easily create a button factory that would be able to hand us the correct kind of button. We would put all the logic for determining which button to use inside of the factory and let it hand us the correct kind of button. Our code from the above example would be simplified to:
A service locator is very much like a factory. You can even use a service locator to get you the right kind of factory that can make your object. The difference is a factory creates a specific kind of object and a service locator can create different kinds of objects.
Using a service locator pattern, we might rewrite our example as:
We could also use generics here and do
(Notice I’m not saying IoC container based dependency injection. I’m talking about dependency injection in general here. You can use an IoC container to do it, but it is not required.)
This is the one most people are most familiar with. We can use a special class that maps interfaces to their implementations, and then injects those implementations into our class via one of several ways.
Some of the common ways to inject the implementation into the class are:
- Constructor injection – pass the dependency into your class via the constructor.
- Setter injection – pass the dependency into your class by setting it on your class.
- Interface injection – implement an interface that allows another class to call your class to give it the dependencies.
Using constructor based dependency injection we could rewrite our example like:
Notice in this example, we are showing how to create our class. We don’t have to do anything special inside our class besides provide a constructor that take our dependency.
But dependency injection looks silly in this example
Right you are!
What if we have more than one button we are going to use in our screen? Seems pretty silly to put a single button in the constructor.
If you already know about IoC and dependency injection, there are two important things you should be taking away from this look back to the basics of creational IoC patterns.
- IoC doesn’t even require interfaces, it just requires that an object be created outside of the class that uses it.
- IoC does not always mean IoC container and dependency injection. Many times the best solution is to directly instantiate an object or use a factory or service locator. (Especially when you are using multiple instances of a class.)
Before embarking on an IoC journey, it is important to understand what problem you are trying to solve by introducing IoC and to understand the differences between using IoC to invert interfaces, using IoC to invert flow control, and using IoC to invert creation control.
In almost all cases the correct application of creational IoC involves solving one of two possible problems.
- I have multiple implementations of an interface or class and I need to be able to have the logic to choose which one all in one place.
- I have only one implementation of an interface or a class, but I need to completely decouple the interface from the implementation for a really good reason. (A really good reason is something like: “I am writing the code that will use the implementation of this interface, but another company is going to provide the implementation in another library.)