Dependency Inversion Principle

Namrata
3 min readFeb 28, 2024

--

Dependency Injection (DI) is a design pattern that implements the “Inversion of Control” concept for resolving dependencies. It is a technique whereby one object supplies the dependencies of another object. Dependency Injection is a part of the SOLID principles in Java.

The “D” in SOLID stands for Dependency Inversion Principle (DIP), which states that high-level modules should not depend on low-level modules, both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. Dependency Injection is a way to implement DIP.

Here’s a simple example:

Without Dependency Injection:

public class TextEditor {
private SpellChecker checker;

public TextEditor() {
this.checker = new SpellChecker();
}
}

In the above code, the TextEditor class is directly dependent on the SpellChecker class. This makes the system hard to maintain and not flexible.

With Dependency Injection:

public class TextEditor {
private IChecker checker;

public TextEditor(IChecker checker) {
this.checker = checker;
}
}

In this case, the TextEditor class is no longer directly dependent on the SpellChecker class. Instead, it interacts with the IChecker interface, which is an abstraction. The actual implementation of IChecker (it could be SpellChecker or GrammarChecker or any other class implementing IChecker) is provided at runtime. This makes the system more flexible, easier to test and maintain.

There are three types of Dependency Injection:

  1. Constructor Injection: The dependencies are provided through a class constructor.
  2. Setter Injection: The client exposes a setter method that the injector uses to inject the dependency.
  3. Interface Injection: The dependency provides an injector method that will inject the dependency into any client passed to it.

Dependency Injection is a key element in Spring Framework. In Spring you can use the @Autowired annotation to auto wire bean on setter methods, instance variable, and constructors.

Here are some reasons why we need the Dependency Inversion Principle:

  1. Decoupling Software Modules: DIP helps in decoupling software modules. When high-level modules depend on low-level modules, it increases the system’s coupling. By depending on abstractions, not on concrete classes (implementation), the coupling between software modules is reduced, making the system more modular.
  2. Ease of Module Exchange: If the software modules follow the DIP, we can easily replace the modules without changing the high-level module. This is very useful when we need to provide new functionality or replace old functionality with new one.
  3. Improved Code Maintainability: High-level modules are typically the ones that contain business logic. If these modules are dependent on low-level modules, any change in the low-level module might affect the high-level module and hence the business logic. By making high-level modules independent of low-level modules, we improve the maintainability of the code.
  4. Improved Code Testability: With high-level modules depending on abstractions, it’s easier to write unit tests. We can provide mock implementations of the abstractions which makes testing easier.
  5. Flexibility and Reusability: Dependency inversion principle leads to more flexible and reusable code. Since high-level and low-level objects depend on the same abstraction, we can reuse them as and when required.

In essence, the Dependency Inversion Principle helps us to manage dependencies between objects, making our code more flexible, easy to manage, test, and reuse. It’s a key principle in designing robust, scalable and maintainable software systems.

--

--

Namrata
Namrata

Written by Namrata

Engineering @Microsoft A software developer writing her daily bits . https://www.linkedin.com/in/namrataagarwal5/

No responses yet