Dependency Inversion Principle

Definition
High-level modules should not depend on low-level modules, but both should depend on abstractions
Dependency Inversion Principle

How does it work?

The principle has two aspects:

  • High-level modules should not import anything from low-level modules. Both should depend on abstractions (e.g., interfaces).
  • Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.

When should you use it?

  • Testing and Mocking: DIP facilitates unit testing and the use of mock objects. By depending on abstractions and injecting dependencies, it becomes easier to substitute real implementations with mock or test-specific implementations during unit testing.
  • Parallel Development: In collaborative development environments where different teams or developers work on different components of the system independently, DIP can provide a clear separation of concerns, enabling parallel development without tight coupling.

Problems

  • Abstraction Overhead: Introducing abstractions (interfaces or abstract classes) to implement DIP can lead to additional code and complexity, especially in smaller projects where the benefits may not outweigh the costs.
  • Over-Engineering: Over-application of DIP, especially in simpler projects, can result in unnecessary abstraction layers, leading to over-engineering and increased development time and effort.
  • Increased Number of Interfaces: As the number of abstractions increases, the codebase may end up with a large number of interfaces, potentially making it harder to manage and navigate.

Links