Sunday, June 12, 2016

Inversion of Control [IoC] Vs. Dependency Injection [DI]

Inversion of Control [IoC] and Dependency Injection [DI]. They're both related, because DI is a pattern that applies the IoC principal, but they're not similar.

Inversion of Control [IoC]

This concept describes application control flow. Whenever the flow of control is inverted, that means that the responsibility for the order of execution of some code is relegated to a parent component, then you are in the presence of an inversion of control.

An event driven system is an example of IoC. Your methods are triggered by the events, but you are not in control of the order of these events, and when they trigger, meaning that you have lost control of the flow of your methods and delegated it to another component.

It doesn't have to be fancy, here's an example:

public class Plugin {
  public void onAction() {
    System.out.println("Action occured.");
  }
}

Now imagine you gave this class to some other component:

public void main() {
  Plugin plugin = new Plugin();
  MasterController master = new MasterController(plugin);
}

In this example, you don't know when onAction will execute, it's not under your control, the Plugin class is not in charge of its full flow anymore, the control is now in the hands of MasterController.

As in my example, IoC became prominent mostly as a way to produce a plugin architecture, where functionality could be extended at run-time, by dynamically loading new code that plugged into a framework at known extension points. And similarly, frameworks often rely completely on IoC, in fact, a lot of people including myself like to distinguish a library from a framework based on this fact. A library has you calling into it, when you want, but a framework calls you, when it wants. This is often known as the Hollywood principle, and is the basis of Inversion of Control.

Dependency Injection [DI]

This concept is even simpler to understand. Whenever the things a component depends on are passed to it, instead of having it acquire or create them, you've got DI.

public class Guy {
  private BestFriend bestFriend;

  public Guy(BestFriend bestFriend) {
    this.bestFriend = bestFriend;
  }

  public void makeImportantDecicion(String about) {
    if(bestFriend.thinksItsGoodIdea(about)) {
      ...
    }
  }
}

As you can see, Guy depends on BestFriend, but he does not create an instance of BestFriend or fetches one from anywhere, instead, it expects it to be passed in.

It doesn't matter how the dependencies are passed in, could be through the constructor, or through some setters methods, or any other means.

Note that the point is for the class to have all direct dependency be passed in to it. So its fine to have a Factory passed in, and then use the Factory to acquire instances of something else and use those, but it's not ok for the class to use a static factory method, since that would be a dependency that's not passed in and would go against DI.

Why they are often mistaken for one another?

The confusion between IoC and DI stems from the fact that Dependency Injection is a form of Inversion of Control. Think how a square is a rectangle, but a rectangle is not a square. It's the same thing here, DI is IoC, but IoC is not DI.

Let's revisit the Guy example. Does Guy have any say as to who his best friend is? Nope. Guy has no control over which friend he's going to ask for advice, the BestFriend is going to be passed in, and something else gets to decide what concrete instance of it to pass in. Guy has lost his control over what code to call into for the thinksItsGoodIdea method. A parent component is now in charge, which mean the control was inverted.

In frameworks like Spring, DI is used extensively as a method for implementing the plugin architecture and a form of IoC. You can choose between different components, and wire them all as you wish inside of Spring. Spring becomes responsible for a lot of the control flow decisions. Allowing you to plug in and out components.

Additional Readings

  1. https://github.com/google/guice/wiki/Motivation
  2. http://stackoverflow.com/questions/26378824/sample-ioc-that-is-not-di
  3. http://martinfowler.com/bliki/InversionOfControl.html

No comments:

Post a Comment