Thursday, January 7, 2016

Dependency Injection

DIP - Dependency Inversion Principle


1994 , Robert C. Martin

RFI problem


According to Martin, Inter-dependency causes coding problems :
  • Rigidity       :  hard to change because every change affects too many other parts of the system
  • Fragility      :  When you make a change, unexpected parts of the system break
  • Immobility  :  hard to reuse in another application because it cannot be disentangled from the current application


DIP rules to fix RFI


  • High level modules (which contain your business logic and all of the important meat of your application) should not depend upon low level modules, both should depend upon abstractions. 

The reason for this is if these lower level components were to change, 
the changes might affect the higher level components as well.

  • Abstractions should not depend upon details, details should depend upon abstractions. 

The interface or abstract class 
should find the common behaviors in the code and work backwards.
should cater to the intersection between the needs of your business logic 
and the common behaviors of the lower level modules.
should also leave the details of how these behaviors are implemented to the implementation classes.



non-DIP compliant program

VotingBooth class is directly dependent on VoteRecorder, which has no abstractions and is the implementing class.



DIP Dependency Inverted Version









Now the LocalVoteRecorder class, the implementing class of the VoteRecorder interface, is completely decoupled from the VotingBooth class.
We have removed all hard-coded references to lower level classes.
According to the rules of DIP, this is all we need to do in order to rid our code of RFI.
However, there is one problem with this implementation.
We don’t have a main method.
We definitely need one in order to run our application, and somewhere in this main method we will need to instantiate the LocalVoteRecorder.
By instantiating the LocalVoteRecorder in our main method, we would break Rule #1 of Dependency Inversion.
We have coded to the abstraction, we have integrated our changes, but our application would still have a dependency on a lower level class. 



DI - Dependency Injection

Dependency Injection takes the level of decoupling that began with the Dependency Inversion Principle one step further. 
Dependency injection has the concept of an assembler 4, or what in Java is commonly referred to as a Factory, that instantiates the objects required by an application and “injects” them into their dependent objects. 
In the case of a dependency injection-informed framework such as Spring, components are coded to interfaces, just as in the DIP example above. 
But now the IoC container manages the instantiation, management, and class casting of the implemented objects so that the application doesn't have to. 
This removes any true dependencies on low-level implemented classes.

Spring uses the concept of a BeanFactory as its assembler, and it is the BeanFactory that manages the JavaBeans you have configured to run within it. 
In the next section we will discuss Spring's IoC container and how it makes use of dependency injection patterns to make your code, well, RFI-free, and just better.

Types of Dependency Injection


  • Constructor Injection
                           The constructor arguments are injected during instance instantiation.
  • Setter Injection
                           Dependencies are “set” in the objects through setter methods defined in a Spring                                  configuration file.
  • Interface Injection
                           It’s a different type of DI that involves mapping items to inject to specific interfaces.



Inversion of Control





No comments:

Post a Comment