What is dependency injection?

Dependency injection means giving an object its instance variables. Really. That’s it.

The best definition I’ve found so far is one by James Shore:

“Dependency Injection” is a 25-dollar term for a 5-cent concept. […] Dependency injection means giving an object its instance variables. […].

He explains it very well:

When I first heard about dependency injection, I thought, “Dependendiwhatsit?” and promptly forgot about it. When I finally took the time to figure out what people were talking about, I laughed. “That’s all it is?”

“Dependency Injection” is a 25-dollar term for a 5-cent concept. That’s not to say that it’s a bad term… and it’s a good tool. But the top articles on Google focus on bells and whistles at the expense of the basic concept. I figured I should say something, well, simpler.

Part I: Dependency Non-Injection

Classes have these things they call methods on. Let’s call those “dependencies.” Most people call them “variables.” Sometimes, when they’re feeling fancy, they call them “instance variables.”

public class Example {
  private DatabaseThingie myDatabase;

  public Example() {
    myDatabase = new DatabaseThingie();
  }

  public void DoStuff() {
    ...
    myDatabase.GetData();
    ...
  }
}

Here, we have a variable… uh, dependency… named “myDatabase.” We initialize it in the constructor.

Part II: Dependency Injection

If we wanted to, we could pass the variable into the constructor. That would “inject” the “dependency” into the class. Now when we use the variable (dependency), we use the object that we were given rather than the one we created.

public class Example {
  private DatabaseThingie myDatabase;

  public Example() {
    myDatabase = new DatabaseThingie();
  }

  public Example(DatabaseThingie useThisDatabaseInstead) {
    myDatabase = useThisDatabaseInstead;
  }

  public void DoStuff() {
    ...
    myDatabase.GetData();
    ...
  }
}

That’s really all there is to it. The rest is just variations on the theme. You could set the dependency (<cough> variable) in… wait for it… a setter method. You could set the dependency by calling a setter method that’s defined in a special interface. You can have the dependency be an interface and then polymorphically pass in some polyjuice. Whatever.

Part III: Why Do We Do This?

Among other things, it’s handy for isolating classes during testing.

public class ExampleTest {
  TestDoStuff() {
    MockDatabase mockDatabase = new MockDatabase();

    // MockDatabase is a subclass of DatabaseThingie, so we can
    // "inject" it here:
    Example example = new Example(mockDatabase);

    example.DoStuff();
    mockDatabase.AssertGetDataWasCalled();
  }
}

public class Example {
  private DatabaseThingie myDatabase;

  public Example() {
    myDatabase = new DatabaseThingie();
  }

  public Example(DatabaseThingie useThisDatabaseInstead) {
    myDatabase = useThisDatabaseInstead;
  }

  public void DoStuff() {
    ...
    myDatabase.GetData();
    ...
  }
}

That’s it. Dependency injection is really just passing in an instance variable.

Or dependency injection can be understood as follows:

Dependency injection is basically providing the objects that an object needs (its dependencies) instead of having it construct them itself. It’s a very useful technique for testing since it allows dependencies to be mocked or stubbed out.

Dependencies can be injected into objects by many means (such as constructor injection or setter injection). One can even use specialized dependency injection frameworks (e.g. Spring) to do that, but they certainly aren’t required. You don’t need those frameworks to have dependency injection. Instantiating and passing objects (dependencies) explicitly is just as good an injection as an injection by the framework.

Answer #2:

Dependency Injection is passing dependency to other objects or framework( dependency injector).

Dependency injection makes testing easier. The injection can be done through constructor.

SomeClass() has its constructor as following:

public SomeClass() {
    myObject = Factory.getObject();
}

Problem: If myObject involves complex tasks such as disk access or network access, it is hard to do unit test on SomeClass(). Programmers have to mock myObject and might intercept the factory call.

Alternative solution:

  • Passing myObject in as an argument to the constructor
public SomeClass (MyClass myObject) {
    this.myObject = myObject;
}

myObject can be passed directly which makes testing easier.

  • One common alternative is defining a do-nothing constructor. Dependency injection can be done through setters.
  • Martin Fowler documents a third alternative, where classes explicitly implement an interface for the dependencies programmers wish injected.

It is harder to isolate components in unit testing without dependency injection.

In 2013, when I wrote this answer, this was a major theme on the Google Testing Blog. It remains the biggest advantage to me, as programmers do not always need the extra flexibility in their run-time design (for instance, for service locator or similar patterns). Programmers often need to isolate the classes during testing.

Answer #3:

Any application is composed of many objects that collaborate with each other to perform some useful stuff. Traditionally each object is responsible for obtaining its own references to the dependent objects (dependencies) it collaborate with. This leads to highly coupled classes and hard-to-test code.

For example, consider a Car object.

Car depends on wheels, engine, fuel, battery, etc. to run. Traditionally we define the brand of such dependent objects along with the definition of the Car object.

Without Dependency Injection (DI):

class Car{
  private Wheel wh = new NepaliRubberWheel();
  private Battery bt = new ExcideBattery();

  //The rest
}

Here, the Car object is responsible for creating the dependent objects.

What if we want to change the type of its dependent object – say Wheel – after the initial NepaliRubberWheel() punctures? We need to recreate the Car object with its new dependency say ChineseRubberWheel(), but only the Car manufacturer can do that.

Then what does the Dependency Injection do for us…?

When using dependency injection, objects are given their dependencies at run time rather than compile time (car manufacturing time). So that we can now change the Wheel whenever we want. Here, the dependency (wheel) can be injected into Car at run time.

After using dependency injection:

Here, we are injecting the dependencies (Wheel and Battery) at runtime. Hence the term : Dependency Injection. We normally rely on DI frameworks such as Spring, Guice, Weld to create the dependencies and inject where needed.

class Car{
  private Wheel wh; // Inject an Instance of Wheel (dependency of car) at runtime
  private Battery bt; // Inject an Instance of Battery (dependency of car) at runtime
  Car(Wheel wh,Battery bt) {
      this.wh = wh;
      this.bt = bt;
  }
  //Or we can have setters
  void setWheel(Wheel wh) {
      this.wh = wh;
  }
}

The advantages are:

  • decoupling the creation of object (in other word, separate usage from the creation of object)
  • ability to replace dependencies (eg: Wheel, Battery) without changing the class that uses it(Car)
  • promotes “Code to interface not to implementation” principle
  • ability to create and use mock dependency during test (if we want to use a Mock of Wheel during test instead of a real instance.. we can create Mock Wheel object and let DI framework inject to Car)

For example, consider these classes:

public class PersonService {
  public void addManager( Person employee, Person newManager ) { ... }
  public void removeManager( Person employee, Person oldManager ) { ... }
  public Group getGroupByManager( Person manager ) { ... }
}

public class GroupMembershipService() {
  public void addPersonToGroup( Person person, Group group ) { ... }
  public void removePersonFromGroup( Person person, Group group ) { ... }
} 

In this example, the implementation of PersonService::addManager and PersonService::removeManager would need an instance of the GroupMembershipService in order to do its work. Without Dependency Injection, the traditional way of doing this would be to instantiate a new GroupMembershipService in the constructor of PersonService and use that instance attribute in both functions. However, if the constructor of GroupMembershipService has multiple things it requires, or worse yet, there are some initialization “setters” that need to be called on the GroupMembershipService, the code grows rather quickly, and the PersonService now depends not only on the GroupMembershipService but also everything else that GroupMembershipService depends on. Furthermore, the linkage to GroupMembershipService is hardcoded into the PersonService which means that you can’t “dummy up” a GroupMembershipService for testing purposes, or to use a strategy pattern in different parts of your application.

With Dependency Injection, instead of instantiating the GroupMembershipService within your PersonService, you’d either pass it in to the PersonService constructor, or else add a Property (getter and setter) to set a local instance of it. This means that your PersonService no longer has to worry about how to create a GroupMembershipService, it just accepts the ones it’s given, and works with them. This also means that anything which is a subclass of GroupMembershipService, or implements the GroupMembershipService interface can be “injected” into the PersonService, and the PersonService doesn’t need to know about the change.

Dependency injection – another explanation:

The first answer is a good one – but I would like to add to this that DI is very much like the classic avoiding of hardcoded constants in the code.

When you use some constant like a database name you’d quickly move it from the inside of the code to some config file and pass a variable containing that value to the place where it is needed. The reason to do that is that these constants usually change more frequently than the rest of the code. For example, if you’d like to test the code in a test database.

DI is analogous to this in the world of Object-Oriented programming. The values there instead of constant literals are whole objects – but the reason to move the code creating them out from the class code is similar – the objects change more frequently than the code that uses them. One important case where such a change is needed tests.

Hope you learned something from this post.

Follow Programming Articles for more!

About ᴾᴿᴼᵍʳᵃᵐᵐᵉʳ

Linux and Python enthusiast, in love with open source since 2014, Writer at programming-articles.com, India.

View all posts by ᴾᴿᴼᵍʳᵃᵐᵐᵉʳ →