The Dependency Inversion Principle
Would You Solder a Lamp Directly
into the Electrical Wiring in a Wall?
The Dependency Inversion Principle encourages Loose Coupling and High Cohesion designs.
Loose Coupling removes hard dependencies through the use of Abstractions that can support change easily over time.
High Cohesion is defined in software development as:
Software Entities that have a Single Purpose
… And Executes its Purpose Effectively
High Cohesion is a result of Design Principle compliance:
Open / Closed Principle (OCP)
Dependency Inversion Principle supports High Cohesion as a primary tool for SRP, OCP and ISP compliance
The Dependency Inversion Principle States:
Higher Level Modules Should Not Depend on Lower Lever Modules
… Lower Lever Modules Should Depend on Higher Level Module Abstractions
…… Both Should Depend on the Abstraction Details
In traditional programming each dependency type is created at the level in which it is to be consumed. Its scope is defined by the Class or Struct in which it is instantiated.
On the Surface Local Instantiation Seems Logical
Create a Dependency Type
… Where it is Required
…… Consume it When it is Required
Problem arises when the requirements of the Type
changes over the Life Cycle of the Type
The above Design Paradigm Tightly Couples the Creation of a Dependency to the usage of that Dependency
When you “Invert” that Design Paradigm you move the responsibility for the creation of a dependency type to the Highest Level Module that will be consuming the dependency type.
By “Designing to Abstractions” rather than “Designing to Concretes” you create an “Inverted Dependency Paradigm”.
The Dependency Inversion Paradigm supports Loosely Coupled Architectures that can implement “Instantiation Factories”.
These Instantiation Factories are called Inversion Of Control (IOC) Containers
The Dependency Inversion Principle
Dependency Inversion is the process of “Decoupling” the consuming Software Entity from the Dependencies it requires.
When the dependencies required delivering a requested response is managed at the lowest module level it is tightly coupled to the higher modules.
This coupling prevents efficient management of the dependency Types over the Life Cycle of the assembly.
DI allows us to inject abstractions of the required concretes to create instantiations that can change over time with minimum change requirements to the lower level modules.
The justification for DIP is based on a lower Total Cost of Ownership and better management of Entity Types over time.
The Inversion of the Dependencies from the consuming modules to the requesting module gives us a centralized location for implementing Inversion of Control Containers for a Global Management Strategy for assembly Type Management.
There is no real “Violation” of this principle.
If the solution does not implement Dependency Inversion then the assembly cannot benefit from its use.
There are no real “Violation” symptoms of this principle, only indications that it is not being used.
If all Concretes Types are being “Newed Up” then the Dependency Inversion Principle is not in play.
Refactoring sample code will be provided in the Modern Developer’s Design Pattern Series with a “Deep Dive” into Dependency Injection (DI) and Inversion of Control (IOC) Containers Design Patterns.
The Benefits of Compliance with the Dependency Inversion Principle:
Enables Easy Implementation of Inversion Of Control (IOC) Containers
Encourages the Development of Coding to Abstractions
Creates Loosely Coupled Architecture
Supports High Cohesion through Compliance of The Single Responsibility Principle
Supports IOC Run Time Type Swapping using Interception through Abstraction Design Practices
DIP Inverts the Responsibility
of Instantiation Management of Object Types
to the Type that is Consuming The Dependency
The Next Principle Design Series Post:
The Inversion Of Control Principle
… Manage All Your Toys
…… In One Place