Tuesday, 4 June 2019

Design Principles | Dependency Inversion Principle


Dependency Inversion Principle is one of the SOLID object-oriented principles invented by Robert Martin (a.k.a. Uncle Bob).

The basic idea behind the Dependency Inversion Principle is that we should create higher level modules with its complex logic in such a way to be reusable and unaffected by any change from the lower level modules in our application. To achieve this kind of behavior in applications, we introduce abstraction which decouples higher from lower level modules.

Dependency Inversion Principle Definition
  • 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.
Problems without DIP
Now, see below code of naive design without any dependency inversion and the loopholes in that design.

import java.util.ArrayList;
import java.util.List;

class Developer {

    Developer() {
        System.out.println("Developer added");
    }
}

class Designer {

    Designer() {
        System.out.println("Designer added");
    }
}

class Manager {

    private List developers;
    private List designers;

    Manager() {
        this.developers = new ArrayList();
        this.designers = new ArrayList();
    }

    public void addDeveloper(Developer dev) {
        developers.add(dev);
    }

    public void addDesigner(Designer des) {
        designers.add(des);
    }
}


public class DIPFailure {

    public static void main(String[] args) {
        Manager a = new Manager();
        a.addDeveloper(new Developer());
        a.addDesigner(new Designer());
    }
}

Design loopholes are,
First, we have exposed everything about the lower layer to the upper layer, thus abstraction is not mentioned. That means Manager must already know about the type of the workers that he can supervise.
Now, if another type of worker comes under the manager let’s say, Tester, then the whole Manager class needs to be rejigged i.e. new List need to be introduced for the Tester in Manager Class. This is where dependency inversion principle pitches in.

Design using the Dependency Inversion Principle

import java.util.ArrayList;
import java.util.List;

class Employee {

    Employee(String emp) {
        System.out.println(emp+" added");
    }
}

class Developer extends Employee {

    Developer() {
        super("Developer added");
    }
}

class Designer extends Employee {

    Designer() {
        super("Designer added");
    }
}

class Tester extends Employee {

    Tester() {
        super("Tester added");
    }
}

class Manager {
    private List employees;

    Manager() {
        this.employees = new ArrayList();
    }

    public void addEmployee(Employee emp) {
        employees.add(emp);
    }
}


public class DIPSuccess {

    public static void main(String[] args) {
        Manager manager = new Manager();
        manager.addEmployee(new Developer());
        manager.addEmployee(new Designer());
        manager.addEmployee(new Tester());
    }
}

Now if we want to add any other kind of the employee, it can be simply added without changing Manager explicitly. Now to add another class of employee we can simply call.

The creation of the abstraction between different employees and Manager has resulted in a very good looking design code which is easily maintainable and extendable.

Benefits of Implementing the Dependency Inversion Principle
Reducing the number of dependencies among modules is an important part of the process of creating an application. This is something that we achieve by implementing DIP correctly. Our classes are not tightly coupled with the lower-tier objects and we can easily reuse the logic from the high-tier modules.
Modularity and reusability are the main reason to make DIP so important in the application modules.

It is also important to mention that changing already implemented modules is risky. By depending on abstraction and not on concrete implementation, we can reduce that risk by not having to change high-level modules in our project.

Finally, DIP when applied correctly gives us the flexibility and stability at the level of the entire architecture of our application. Our application will be able to evolve more securely and become stable and robust.


No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...