Dependency Injection and Inversion of Control are not rocket surgery

I see a lot of people talking about how “advanced” techniques like dependency injection and inversion of control are and how their team won’t understand either technique.

 

Folks, this isn’t hard. In fact, both of these things are so simple I simply call it “using the programming language”.

 

Let’s look at dependency injection.

    public class MyClass
    {
        private DataTableReader _reader;
        public MyClass()
        {
            _reader = new DataTableReader(new DataTable());
        }
        private void DoStuffWithTheReader()
        {
            while (_reader.Read())
            {
                //do fun stuff with the reader.
            }
        }
    }  

See the reader variable? That’s a dependency. You have to have it in there to do fun things later on. But we have to create it ourselves, which is one more thing that we have to do in our class constructor. In reality we also have to populate the DataTable. So what if we make the reader variable constructor parameter so that another class can do the work of creating the DataTable and the reader?

    public class MyClass
    {
        private DataTableReader _reader;
        public MyClass(DataTableReader dataTableReader)
        {
            _reader = dataTableReader;
        }
        private void DoStuffWithTheReader()
        {
            while (_reader.Read())
            {
                //do fun stuff with the reader.
            }
        }
    }

There, that’s better. Now our class doesn’t have to worry about creating the reader and the DataTable. This, in a nutshell, is dependency injection. It’s not very complicated is it? We’ve made our class construction a little simpler and if we want to unit test this, we don’t have to do any complicated mocking, we can just new up our own DataTableReader instance and populate it with whatever test data we want. If you run into any funny looking data in the DoStuffWithTheReader method, you know that you don’t have to look in this class at all to see where the funny data is coming from, only in whatever method is creating this class and passing in the DataTableReader.

Now is there anyone who thinks that developers on their team would have trouble understanding passing in a parameter? Should they really be a developer if they do?
Honestly, it's not that hard.

Ok, so let’s look at inversion of control. The original definition of inversion of control I read was by Martin Fowler:

There’s a big difference now in the flow of control between these programs – in particular the control of when the process_name and process_quest methods are called. In the command line form I control when these methods are called, but in the window example I don’t. Instead I hand control over to the windowing system (with the Tk.mainloop command). It then decides when to call my methods, based on the bindings I made when creating the form. The control is inverted – it calls me rather me calling the framework. This phenomenon is Inversion of Control (also known as the Hollywood Principle – “Don’t call us, we’ll call you”).

If you look at the previous example, you’ll see that we have already inverted the control a bit just by using dependency injection. But the class still has a degree of control over WHAT concrete object is created, in this case a DataTableReader. What if we need to switch over to a SqlDataReader or an OleDbDataReader? Well, we could create three other classes that all take the specific type of data reader we might want to use. But that’s a bad idea, you end up with the same logic spread all over the place. Instead we can use the IDataReader interface that all three classes implement.

    public class MyClass
    {
        private IDataReader _reader;

        public MyClass(IDataReader dataTableReader)
        {
            _reader = dataTableReader;
        }
        private void DoStuffWithTheReader()
        {
            while (_reader.Read())
            {
                //do fun stuff with the reader.
            }
        }
    }

Now our class not only doesn’t have to worry about creating the DataTableReader, it doesn’t even really care if it gets a DataTableReader at all. All it cares about is that the reader is referencing something that implements the IDataReader interface. This is a type of inversion of control. Most of the time people get confused between inversion of control and a container that enables inversion of control and dependency injection (like Ninject, StructureMap or Unity). You don’t have to use a container to utilize these two techniques, it just makes it a little easier.

update:Also check out this great post “It’s all about the delivery

update: I mistakingly thought it was hard to do D.I. in Python due to the inheritance mechanism in Python. Turns out, it’s just as easy.

class MyClass():

    def __init__(self, dataTableReader):
        self._reader = dataTableReader
        
    def DoStuffWithTheReader(self):
        while(self._reader.Read()):
            #Do Fun Stuff with the reader.
            print(self._reader.item)
  • “Rocket surgery” LOL

  • Wim Hollebrandse

    Dependency injection really is something that enables inversion of control. It doesn’t have to be the case. In your reader example IoC isn’t very clear at all.
    In my opinion IoC is more about having a container that really controls a fairly granular set of methods defined on the dependency interface definition but the container wraps its own logic, logging, and process of executing the interface methods.

    Good and sensible post though – you can easily roll your own specific IoC container, it’s just that some of the abstract factory and configuration aspects are mostly taken care of when using an existing IoC framework.

  • Pingback: uberVU - social comments()

  • Wim: Yeah, I struggled a bit to come up with a good example of IoC. I finally just went with the interface injection. I supposed that delegate event handlers would have been another good example, one that might have turned on the light bulb for a lot of people. “Oh, I’m already using IoC and I didn’t even know it”.

  • In a word – “Quality!”

    It’s posts like these that are driving home everyday something that we already know: these concepts are not tough to understand and use, it is the incessant resistance to change causing problems.

    The more of these great 1-pagers we have in evidence, the more I get to point out to those whining about “if it ain’t broke…blah” – that simple changes like this to future code at the very least will pay back dividends that they cannot yet fathom.

    That’s the real problem – the not being able to “fathom the benefits” part.

    Great post, keep ’em coming
    Rob G

  • That’s probably the best description of these concepts I’ve seen.

    I have to be honest, I was fairly confused by DI and IoC the first time I saw them. I wish I’d seen an article like this right at the start – it would have made things a lot easier.

    Thanks, I’ll be passing this link on.

  • Pingback: Reflective Perspective - Chris Alcock » The Morning Brew #469()

  • Pingback: Dew Drop – November 4, 2009 | Alvin Ashcraft's Morning Dew()

  • Pingback: Tweets that mention Dependency Injection and Inversion of Control are not rocket surgery | Lazycoder -- Topsy.com()

  • Great example. I have bookmarked this and will use it to show my colleagues just how simple DI and IOC are.

  • Dependency injection is really something that allows the inversion of control. It need not be the case. In the example reader IOC is not clear at all. In my opinion, the IOC is more about having a container that is actually a fairly granular control of the methods defined in the interface definition of dependency, but the package is wrapped its own logic, registration and implementation process of the methods interface. Very useful article. I love twitter.

  • Wim: Yes, I struggled a bit to get a good example of the IOC. Finally just went with the injection of the interface. I guess the event delegate handlers have been another good example, one that could have lit the light bulb for many people. ‘Oh, I’m already using the IOC and I do not even know it. This was an interesting read, however I am not sure I understand the main themes. Regardless it was a fun read!

  • It sounds like you’re creating problems yourself by trying to solve this issue instead of looking at why their is a problem in the first place

  • It allows for an increased level of testability as well as lower coupling between components of an application.