Dependency Injection

How do you define real?

What Dependency Injection

Dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client's state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

The intent behind dependency injection is to decouple objects to the extent that no client code has to be changed simply because an object it depends on needs to be changed to a different one. This permits following the Open / Closed principle.


Intent

"You think that’s air you’re breathing now?” Morpheus, the Matrix

How can an application or class be independent of how its objects are created? How can the way objects are created be specified in separate configuration files? How can an application support different configurations?

These are questions that Dependency Injection seeks to solve.

Creating objects directly within the class that requires the objects is inflexible because it commits the class to particular objects and makes it impossible to change the instantiation later independently from (without having to change) the class. It stops the class from being reusable if other objects are required, and it makes the class hard to test because real objects can't be replaced with mock objects.


Clean Code

Dependency injection is one form of the broader technique of inversion of control. As with other forms of inversion of control, dependency injection supports the dependency inversion principle. The client delegates the responsibility of providing its dependencies to external code (the injector). The client is not allowed to call the injector code; it is the injecting code that constructs the services and calls the client to inject them.

This means the client code does not need to know about the injecting code, how to construct the services or even which actual services it is using; the client only needs to know about the intrinsic interfaces of the services because these define how the client may use the services. This separates the responsibilities of use and construction.


Why should I use Dependency Injection ?

"Welcome to the Desert of the Real."

Let’s say we have a car class which contains various objects such as wheels, engine, etc.

class Car
{
  private Wheels wheel = new MRFWheels();
  private Battery battery = new ExcideBattery();
  ...
  ...

}

Here the car class is responsible for creating all the dependency objects. Now, what if we decide to ditch MRFWheels in the future and want to use Yokohama Wheels?


We will need to recreate the car object with a new Yokohama dependency. But when using dependency injection (DI), we can change the Wheels at runtime (because dependencies can be injected at runtime rather than at compile time).

You can think of DI as the middleman in our code who does all the work of creating the preferred wheels object and providing it to the Car class.

It makes our Car class independent from creating the objects of Wheels, Battery, etc.


Types of Injection

There are basically three types of dependency injection:

constructor injection: the dependencies are provided through a class constructor.

  Car(Wheel wh, Battery bt)
  {
    this.wh = wh;
    this.bt = bt;
  }

setter injection: the client exposes a setter method that the injector uses to inject the dependency.

void setWheel(Wheel wh)
{
    this.wh = wh;
}

Interface injection: the dependency provides an injector method that will inject the dependency into any client passed to it. Clients must implement an interface that exposes a setter method that accepts the dependency.


So now its the dependency injection’s responsibility to:

Create the objects Know which classes require those objects And provide them all those objects If there is any change in objects, then DI looks into it and it should not concern the class using those objects. This way if the objects change in the future, then its DI’s responsibility to provide the appropriate objects to the class.