In this five-part series, I’m covering each design principle laid out in SOLID. In this final post, I am covering the dependency inversion principle.
The “D” in SOLID is a pretty well understood principle. It is supported by a variety of platforms, including Angular. The code below shows how it is implemented using Angular.
The “D” is useful because we are intentionally decoupling all things in our system. We are decoupling the services from each other. We are intentionally only coupling to the contracts, not the data contracts.
The “D” in SOLID really comes back to “Information Hiding” from David Parnas’s paper, “On the Criteria To Be Used in Decomposing Systems into Modules” (1972):
“A well-defined segmentation of the project effort ensures system modularity. Each task forms a separate, distinct program module. At implementation time each module and its inputs and outputs are well-defined, there is no confusion in the intended interface with other system modules. At checkout time the integrity of the module is tested independently; there are few scheduling problems in synchronizing the completion of several tasks before checkout can begin. Finally, the system is maintained in modular fashion; system errors and deficiencies can be traced to specific system modules, thus limiting the scope of detailed error searching.”
Dependency inversion helps ensure that we are always programming to an interface / contract.
Now there are two flavors of dependency inversion. There is constructor injection and service locator (also known as factory). Most of us at Don’t Panic Labs prefer factory to constructor injection because we believe it does a better job of hiding information, which is good.
Now even though we prefer factory it doesn’t mean we dislike constructor injection. Either is way better than not doing dependency inversion at all.
Below is a simple example of how we get a dependency from within our systems. In this example, we are using an accessor factory to retrieve an accessor. We like to create three factories: one for managers, one for engines and one for accessors.
Using a factory also allows us to make our actual services internal, which means consuming them without using a factory difficult.
Dependency inversion, use it. You’ll thank me later.