DIP - Dependency Inversion Principle
1994 , Robert C. Martin
According to Martin, Inter-dependency causes coding problems :
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
- Interface Injection
Inversion of Control




No comments:
Post a Comment