Friday, March 1, 2013

Why Dependency Injection is a powerful concept


Dependency Injection (DI) is a type of  Inversion of Control (IoC) focused on decoupling and inverting the way an object obtains its collaborators.

In order to achieve its purpose, almost every object interacts with other objects, so there must be some code that materializes "the wiring" among them. 

The easiest way to do this would be to place that code in the object definition, that is to say, the object is responsible for obtaining its collaborators and one of the places of choice is its constructor.

Let's exemplify this with some Java code:

public class MyBusinessObject {

       private OtherBusinessObject obo;

       public MyBusinessObject(){

           obo = new OtherBusinessObject();

       }

      ...
}

Very simple, but it has some flaws. Let's say you programmed your objects thinking on
polymorphism and its underlying concept exchangeable objects, for leveraging code scalability. In Java, this can be achieved by defining the collaborator type as a superclass (probably abstract) or as an interface.

What if a new business requirement makes your object interact with a different class of its collaborator? 

Although small, some changes have to be made in the code (the collaborator instantiation in the constructor).

Furthermore, what if there are some scenarios in which the object has to interact with different definitions of the collaborator (needless to say all polymorphic among each others)? 

This is very common when unit testing: the object is tested isolated so you make it interact with a "fake" version of its collaborator (aka mock).

Clearly this approach is not flexible enough. So, how can we avoid modifying the code and support the ability of interacting with different objects at different scenarios? 

Here is where DI comes to action.