So this is the last of the 5 principles in the solid principles and is called Dependency Inversion principle. This principle is generally aimed at managing the coupling between two modules/classes with one of them dependent on the other and using it directly. This results in a very tightly coupled system. To avoid this type of situation, this principle is applied.
This principle has two points associated to it. These are
- High level modules should not depend upon low level modules. Both should depend upon abstractions.
- Abstractions should not depend upon details. Details should depend upon abstractions.
I will come to the reason i am using this AND between these two statements after the discussion of the concept.
So before we start with the code, lets try to understand, what is the meaning of dependency in code, with a simple example. Consider the following snippet of code :
As you can see, here we have a logger class and a DbInteraction class. Here, our logger class acts as a low level class and the DbInteraction class acts as a high level complex class and this class is directly using the logger class in it. This is an example of a tightly coupled system.
This is the violation of the Dependency Inversion Principle, as high level class is directly dependent on the low level class. This can result in problem in future. If we have to add another type of logger, say log in the notepad or database, the complex class will be dependent on another concrete class, which further adds another reason to change the DbInteraction class. This is the violation of Single responsibility principle as well.
So. to avoid this kind of situation, we use the concept of Dependency Inversion principle. We will be implementing this principle in two steps :
Step 1 : Introduce the abstraction
To achieve this, we will be introducing the abstraction layer, which can be done either using the interface or abstract class, and will be having a simple method declaration to perform the logging operation. So our low level class i.e. the XMLLogger will be implementing this interface and our high level class will be using this interface based function to perform the logging operation. So our code becomes like the following :
So now it seems that the our code is fine, but still it is not. XMLLogger is getting instantiated inside the main class. So any new logger added, will again require us to make this class dependent on the newly added logger classes and they will have to be instantiated in this method itself. This again results in the violation of the Open/Closed & Single responsibility principles. So dependency is till there. Its time for Step 2.
Step 2 : Implement Dependency Injection
So, we will now introduce the dependency injection in this code, and the required object creation will be from the client code, and will be passed to this class using the constructor. This is what is called Constructor Dependency injection. So the dependency is injected into the high level class by the client code in following manner :
So here we get the advantage that whenever a new logger is to be added, we simply create it and implement the logger interface for it. Then finally, depending on the requirement, client code can instantiate the dependency in its code and pass it into the constructor of the DbInteraction class.
Now, at the start of this discussion, we used the AND statement between the two points which this principle refers to. The first principle is straight forward which says use the abstraction layers for interaction between to components. The second one might be a bit confusing, which says abstraction should not depend on details…
To be specific about this point, what this point actually means is that when we are introducing the abstraction, it should also not be depending on any concrete classes to satisfy the requirements of the derived classes, which is what we had at the start of our example, where we had no principle followed. For more details related to this point, you can check out the explanation at this link : http://programmers.stackexchange.com/questions/64932/what-does-abstractions-should-not-depend-on-details-actually-mean.
This is the question for which even I have been looking for a long time which clarifies that the two points are different (this is what at-least i understood about the concept).
So this was all about the concept of Dependency Inversion Principle. Hope you enjoyed reading it…!!!