This is the Last principle in SOLID. Definition of DIP is as below, basically, it has 2 points,
- High-level modules should not depend on low-level modules. Both should depend on the abstraction.
- Abstractions should not depend on details. Details should depend on abstractions.
DIP is used to convert Tightly Coupled Architecture to Loosely Coupled Architecture.
To implement DIP firstly we need to understand Abstraction. In simple words, Abstraction means something which is non-concrete. abstraction in programming means to create an interface or an abstract class which is non-concrete. This means we cannot create an object of an interface or an abstract class.
For example, try to understand below code,
- public class CustBL
- {
- public CustBL()
- {
- }
-
- public string GetCustName(int id)
- {
- DataAccess _dataAccess = DAFactory.GetDAObj();
-
- return _dataAccess.GetCustName(id);
- }
- }
-
- public class DAFactory
- {
- public static DataAccess GetDAObj()
- {
- return new DataAccess();
- }
- }
-
- public class DataAccess
- {
- public DataAccess()
- {
- }
-
- public string GetCustName(int id) {
- return "Dinesh";
- }
- }
The above CustBL and DataAccess are concrete classes, meaning we can create objects of them.
Now if we want to create loosely coupled architecture, we need to implement DIP as below.
- public interface ICustDA
- {
- string GetCustName(int id);
- }
-
- public class CustDA: ICustDA
- {
- public CustDA() {
- }
-
- public string GetCustName(int id) {
- return "Dinesh";
- }
- }
-
- public class DAFactory
- {
- public static ICustDA GetCustDAObj()
- {
- return new CustDA();
- }
- }
-
- public class CustBL
- {
- ICustDA _custDA;
-
- public CustBL()
- {
- _ custDA = DAFactory.GetCustDAObj();
- }
-
- public string GetCustName(int id)
- {
- return _ custDA.GetCustName(id);
- }
- }
In this way we can implement Dependency Inversion Principle - DIP using very basic concept of Object Oriented Programming concept - Abstraction. The advantages of implementing DIP in the above example are CustBL and CustDA classes are loosely coupled and CustBL does not depend on the concrete DataAccess class, it includes a reference of the ICustDA interface. With the help of this, we can easily use another class that implements ICustDA with a different implementation. And here we achieved both the points in DIP
- High-level modules should not depend on low-level modules. Both should depend on the abstraction.
- Abstractions should not depend on details. Details should depend on abstractions.
At last, we always need to implement loosely coupled architecture in our application to accommodate changes at any point or phase of development and support. Without loosely coupled architecture it is very difficult to maintain, test and accommodate changes in the application. DIP is one of the most important principle to implement loosely coupled.
Here S.O.L.I.D. article series completed. Even if we only follow SOLID principles, we will be safe and good in terms of architecture and coding standards. It will help us to maintainable, testable, readable, extensible and easily accommodate changes.
--Happy Coding--