Skip to main content

Dependency Inversion Principle (DIP)

D of the SOLID principle is Dependency Inversion Principle also known as DIP.

This is one of those very powerful principle to build highly-decoupled well structured software.

What is Dependency Inversion Principle?

The dependency inversion principle is a specific form of decoupling software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details. (wikipedia)
Depend on abstractions, not on concretions.

Robert C. Martin’s definition of the Dependency Inversion Principle consists of two parts:
  1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
  2. Abstractions should not depend on details. Details should depend on abstractions.

The idea here is that high-level module should not depend on low-level modules. Both should only depend on the abstraction. With that you can see that is changes the direction of the dependency.

Basically, loose coupling is the Dependency Inversion Principle's goal, and there are at least two ways to achieve it.
  • Dependency Injection
  • Service Locator - considered an anti-pattern.

A bit of Dependency Injection

Dependency injection is a technique in which an object receives other objects that it depends on.

Dependency Injection or DI is a way of implementing DIP. You are injecting your dependencies through constructor, setters, properties.
Inversion of Control (IoC) frameworks like Spring uses this technique to manage dependencies. However it is just another tool we use.

Here we are going to write a file.

FileProcessor -> FileWriter
FileProcessor -> AbstractFileWriter <-- AwsFileWriter

Have a look at the arrow in this new design. You can see that with  this design we have inverted the direction. Now low-level dependency is directing towards high-level.

Complete example

One step further

If you like to have more flexible design, you can separate abstractions further by putting them in separate modules. However this needs to maintain separate package structure.
High-level  --> api <-- low-level