avatarGerald Nguyen

Summary

The provided web content discusses the Dependency Inversion Principle (DIP), one of the SOLID principles in software development, emphasizing the importance of depending on abstractions rather than concrete implementations to achieve flexible and maintainable code.

Abstract

The web content titled "SOLID in Action: the Dependency Inversion Principle" delves into the concept of DIP within the broader context of SOLID software development principles. It explains how traditional top-down development approaches could lead to rigid, fragile, and immobile codebases, which are symptomatic of poor design. The DIP is presented as a solution to invert the traditional dependency flow, ensuring that high-level modules and low-level modules both depend on abstractions rather than on each other. This principle promotes the creation of decoupled systems that are easier to maintain and extend. The article provides examples of DIP in practice, such as an OrderService depending on an EmailService interface rather than its specific implementation, and cautions against common misuses, such as the overuse of interfaces for single-implementation services. It also distinguishes DIP from Inversion of Control (IoC), clarifying that while DIP guides component relationships, IoC is a technique for assembling applications that respect DIP.

Opinions

  • The author suggests that naive application of traditional software development methods like SADT can result in poorly designed systems characterized by rigidity, fragility, and immobility.
  • The DIP is advocated as a means to preserve the benefits of conventional analysis and design techniques while also incorporating the flexibility and reusability offered by object-oriented design.
  • The article warns against the overuse of interfaces when there is only a single implementation, referencing Martin Fowler's critique of the Interface Implementation Pair practice.
  • The author emphasizes that abstraction is not solely achieved through interface constructs, especially in languages like JavaScript or Python that may not support interfaces.
  • The distinction between DIP and IoC is highlighted, with the author explaining that IoC is a method for managing dependencies in line with DIP but is not the same as the principle itself.

Software Development

SOLID in Action: the Dependency Inversion Principle

Depend upon Abstractions. Do not depend upon concretions.

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

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

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:

  • An OrderService depends on the interface provided by EmailService and not its IMAP or POP implementation.
EmailService and its associations
  • An UrbanTripPlanner depends on the abstraction provided by Car , not its Tesla or Toyota implementation
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.

Software Engineering
Object Oriented
Solid Principles
Programming
Dependency Inversion
Recommended from ReadMedium