SOLID in Action: the Dependency Inversion Principle

Depend upon Abstractions. Do not depend upon concretions.

Gerald Nguyen
Gerald Nguyen
4 min read ·
Previous | Next
Also on Medium
On this page
Photo by ocd studio on Unsplash

Photo by ocd studio on Unsplash

The Dependency Inversion Principle (DIP)

Naive application of traditional software development methods (e.g. SADT or Structured Analysis and Design Technique), in the past, often resulted in a type of relationship where high-level modules depended on lower implementation details. This form of relationship often leads to rigidity, fragility, and immobility. These are the symptoms of bad design according to Robert C. Martin.

A naive application of top-down approaches can lead to bad design. Source: R.C.M paper

A naive application of top-down approaches can lead to bad design. Source: R.C.M paper

The Dependency Inversion Principle (DIP) means to invert such dependency relationships. Rather than having the relationship flow in one direction and tie upper layers onto implementation details of lower layers, the implementation of the lower layers now inversely points upward to abstraction layers that sit between the upper and lower layers. The benefit of this DIP is the preservation of the benefits of conventional analysis and design techniques plus the flexibility and reusability of abstraction-based object-oriented designs.

Source: R.C.M paper

Source: R.C.M paper

The above diagram can be summarized as:

High-level modules should not depend upon low-level modules. Both should depend upon abstractions

Abstractions should not depend upon details. Details should depend upon abstraction

Examples

As long as you are considering a dependency where the depended-on component or service can have 2 or more implementations or can be further expanded through inheritance, the DIP can be put to good benefit.

In my Becoming a SOLID developer article, I share 2 examples:

EmailService and its associations

EmailService and its associations

Car and its associations

Car and its associations

And Misuses

Martin Fowler called out the overuse of interfaces for single-implementation service in his Interface Implementation Pair article

The practice of taking every class and pairing it with an interface. So as a result you see pairs of things — maybe ICustomer and Customer or Customer and CustomerImpl…Using interfaces when you aren’t going to have multiple implementations is extra effort to keep everything in sync (although good IDEs help). Furthermore, it hides the cases where you actually do provide multiple implementations.

Another common misuse in object-oriented programming languages is equating abstraction with interface construct. While interface is a popular way to express abstraction, it is by no means the only way, especially in dynamically typed languages or languages without interface support such as JavaScript or Python. We should rather consider an abstraction from a less concrete perspective. Take the abstraction expressed by the Car class above, for example, it does not have to be an interface to represent an abstraction.

In relation to the Inversion of Control

IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern — https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-introduction

Inversion of Control (IoC) may share the term “inversion” but DIP and IoC are different. The distinction between the 2 concepts is in the purposes of their application. While DIP guides the modeling of relationships between components, the IoC provides ways to assemble the application while respecting the DIP relationship.

Conclusion

We have examined the meaning of the Dependency Inversion Principle and some examples of proper applications as well as misuse. We have also clarified its purposes by comparing it with the IoC principle.

If you like this article, please follow me for more quality content.

Other articles in this series:

Thank you.