< Back to Blog

Inversion and Injection of Dependencies

Inversion and Injection of Dependencies

In my line of work at Distillery I conduct a lot of interviews, and 90% of what I hear when I ask a question about dependency injection, frankly speaking, is complete nonsense. I even came across an interpretation of IoC as Injection of Container. Somebody seriously assumes that there is a mechanism for injecting containers which is similar to DI. Only it does it with containers. Hmm.

Richard Feynman was an amazing story teller, able to explain complex things clearly and intelligibly (see, for example, this video). Joel Spolsky believes that a truly intelligent programmer should necessarily be able to speak in layman’s terms (and not just in the C programming language). And almost everyone knows Albert Einstein’s aphorism, “If you can’t explain something to a six-year-old child, then you don’t understand it yourself”. Of course I’m not comparing you to a six-year old, but I will try to tell you about DI, IoC and another DI in the most clear and intelligible way.

Inversion of Control

What do you do on your day off? Maybe you read books. Maybe you play videogames. Maybe you write code, or maybe you sip beer while watching another TV series (instead of planting apple trees on Mars). But whatever you do, you have the whole day at your disposal, and you have sole control of your schedule.

Unfortunately, the weekend ends, Monday comes, and you have to go to work (assuming you have a job). According to the terms of your employment contract, you have to be at work by 8 a.m. You work until noon. Then you have a lunch break and after that four more hours of feverish activity. Finally, at 5 p.m. you get out of the office and head home where you can relax again and grab some brewskis. Can you feel the difference? You do not control your daily schedule anymore. This is done by somebody else—your employer.

Let’s take a look at another example. Let’s assume that you’re writing an application with a text interface. In your Main function, you request user input, wait for a sequence of symbols from the user, call subroutines for processing the received data (maybe even in separate threads), and request general functions from the connected libraries. Thus, total authority is concentrated in your hands, and the code you wrote controls the flow of execution of the application. But one fine day the boss comes into your office with unpleasant news—consoles are out of fashion, graphic interfaces rule the world, and you have to redo everything. Being a modern and flexible programmer (and I’m not talking about your yoga classes), you get started on the changes immediately. To do this, you connect a GUI framework and write the event processing code. If this button is clicked, then this or that should happen. And if the user changes his selection in the drop-down list, then you can’t do without this and that. All is well. But then you realize something’s different. Who’s calling these event handlers that you’re programming so diligently? Who determines what the user clicks on and when? What’s going on here? Where are my socks? The GUI framework was trickier than you thought and intercepted control over the flow of execution of the application from you.

This is Inversion of Control—an abstract principle that indicates that flow of execution is controlled by an external entity. The concept of IoC is closely connected with the idea of a framework. IoC is the main difference between a framework and another formalization of reusable code—a library—a collection of functions which you simply call from your program. A framework is a shell that provides predefined extension points. You can insert your own code in these extension points, but the framework determines when that code will be called.

As homework, think about why Jeff Sutherland insists that SCRUM is a framework, and not a methodology.

Dependency Inversion

Dependency inversion is the letter D in the acronym SOLID. The principle says:

  • High-level modules should not depend on low-level modules. Both types of modules should depend on abstractions.
  • Abstractions should not depend on details. Details should depend on abstractions.

It’s a little confusing, so let’s take a look at an example (I’ll use C# for the examples).

public class Foo {
  private Bar itsBar;

  public Foo() {
     itsBar = new Bar();
  }
}

The problem here is that class Foo depends on the specific class Bar. For one reason or another—for the sake of extensibility, re-usability or testing—you might have to separate them. According to the principle of Dependency Inversion, you should introduce an intermediate abstraction between them.

public class Foo {
  private IBar itsBar;

  public Foo() {
     itsBar = new Bar();
  }
}

The UML diagram shows both variants graphically.
Dependency Inversion Development

The trouble comes when you ask, where is the actual inversion here? The essential idea which allows us to answer this question is that interfaces do not belong to their implementations but to their clients. The name of the interface, IBar, is confusing and makes us see the pair IBar + Bar as a single entity. But the true owner of IBar is class Foo, and if you take that into consideration, then the direction of the communication between Foo and Bar actually does invert.

Distillery App Development

Dependency Injection

Looking at the resulting code, an attentive reader will notice that despite the introduction of an intermediate abstraction, class Foo is still responsible for the instantiation of class Bar. Obviously this is not the separation we were expecting.

public class Foo {
  private IServer itsServer;

  public Foo() {
     itsServer = new Bar();
  }
}

To relieve class Foo of this unpleasant duty, it would be nice to move the instantiation code somewhere else and encapsulate it there (since we are all extremely pragmatic and do not like to write anything twice). This can be done in two ways—using either the Service Locator pattern or Dependency Injection.

A Service Locator is a registry of abstractions and corresponding implementations. You feed it the interface you’re interested in, and receive a fresh instance of a particular class. It looks like this:

public class Foo {
  private IServer itsServer;

  public Foo() {
     itsServer = ServiceLocator.Resolve<IServer>();
  }
}

The nuance is that now class Foo does not depend in anyway on class Bar, but it still controls its instantiation. As we already know, this can be avoided by inverting the flow of control, which means passing control into the hands of an external mechanism. Dependency Injection is that very mechanism that is implemented in frameworks called IoC-containers:

public class Foo {
  private IServer itsServer;

  public Foo(IServer server) {
     itsServer = server;
  }
}

Conclusion

Frankly, an IoC-container is such a foolish name that it is hard to think of anything worse. The term says nothing about what it actually does, confusing dozens of new programmers every day. Absolutely any framework can be called an IoC-container because, by definition, it implements inversion of control and is a container for general purpose code. This term was (and continues to be) so awful that Martin Fowler invented another—Dependency Injection.

Let’s sum up. We use Dependency Inversion to separate the modules by abstraction and Dependency Injection to eliminate manual instantiation. We implement it all through a framework according to the principle of Inversion of Control. And none of these are synonyms, so IoC-containers is a vivid example of how you can confuse everyone with a single unhappy term. I hope, in this small opus, I managed to clarify the difference between these concepts, and that you’ll never again confuse them. And if one of your colleagues is confused, you’ll be able to explain the distinction clearly and intelligibly.


BACK TO TOP >