Advertisements
Posted by: jsonmez | November 30, 2010

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.

take_control_pic

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:

Button button;
switch(UserSettings.UserSkinType)
{
   case UserSkinTypes.Normal:
        button = new Button();
        break;
   case UserSkinTypes.Fancy:
        button = new FancyButton();
        break;
   case UserSkinTypes.Gothic:
        button = new VampireButton();
}

 

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.

Factory pattern

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:

Button button = ButtonFactory.CreateButton();

Service locator

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:

Button button = ServiceLocator.Create(Button.class)

 

(We could also use generics here and do Create<Button>())

Dependency injection

(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:

Button button = GetTheRightDangButton();
OurScreen ourScreen = new OutScreen(button);

 

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.

  1. IoC doesn’t even require interfaces, it just requires that an object be created outside of the class that uses it.
  2. 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.

  1. 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.
  2. 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.)

As always, you can subscribe to this RSS feed to follow my posts on Making the Complex Simple.  Feel free to check out ElegantCode.com where I post about the topic of writing elegant code about once a week.  Also, you can follow me on twitter here.

Advertisements

Responses

  1. […] Basic to Basics: Understanding IoC Part 2 (Creation) – John Sonmez continues his back to basics series looking at Inversion of Control looking at how IoC can provide a means of replacing your object creation statements with calls to the container (or even better, and abstraction over the container such as the Common ServiceLocator) […]

  2. (Just a small note, the first amazon link is broken)

    • Thanks! Fixed.

  3. Although I really like your style of writing and I understand ur trying to make things easy to understand, it isn’t working as well as it can. You need to give us more detail, like the objects your dealing with – are they our implemented objects or something else? Etc… And tie each object/item back to what or when youngest mentioned it so we can get a good flow… Really please assume we know nothing apart from the actual language… If you take a look at how Scott Guthrie explains concepts in his long posts, and states the obvious and simple things, it really adds to comprehension, try to do what he does. I hope I was able to provide good feedback. Keep up the great work.

  4. For instance, constructor, setter and interface injection could be better explained with code added, but the code should be described meticulously – telling us what each object is and how it relates to what your saying and each line of code clearly explained and what it means, why etc…if you do this for all part of your article, it will add so much more value. Thanks.

    • Thanks for the feedback. I will try to give more detail in general. For the injection, I didn’t want to go into detail there, because I will have a separate post that will talk specifically about those. I try to balance the length of my post vs the detail I go into as I know it can be difficult to read a long post with lots of code in it. Not trying to make excuses, and I do thank you for the input. I will try and look at some of Scott Guthrie’s posts and implement your suggestions.
      Thanks again!

  5. Hello, thank you for your understanding. I just wanted to give you an example of ine of scottgu’s good posts, here it is: http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

    Notice how he assumes we know nothing but the base language, and even describes new or usually unfamiliar language features assuming we know nothing of that either. Notice how he emphasizes the connections between things that are usually implied and understood, but is useful for people who don’t see the implied connections, but on top of this, even for people who do see the implied connections, this reenforcement gives the reader more confidence that what they are thinking is correct and therefore goes a long way in adding value to comprehension and flow. See how he enforces code with good descriptions? That really ads to users or readers confidence and comprehension.

    Just as a general rule, if you assume we know nothing then you’ll add lots of value to your already great descriptions.

    As someone on the opposite side, for example, how brad Wilson writes, he assumes everyone has his background when writing his tutorials, and the truth is, most people don’t, so when you read his tutorials, people have to reread, or usually go figure out a lot of background stuff usual written by people with hhis experience in the same way, the hope that we have enough to understand the usage concepts he is trying to describe. To hihs credit though, if he wrote whie assuming reader knows nothing, I think he would be worried that it might make him look less knowledgable especially to the people with his background. But ine can always place a disclaimer at the start saying “this assumes you know nothing but the base language itself” – to bring brad wilson into my point, even though he writes well, the audience he captures is very minimal and therefore is a worst-case example of how not to write blog posts in my opinion, since is should be writing for a large audience with particular intention for beginners of which there are many entering MVC.

    Once again I thank you for your valued posts and (as an example) your general concept descriptions which are very well put together from analogy to description – this clarifies the concepts in our heads very well.


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

Categories

%d bloggers like this: