1. 程式人生 > >Effective Program Structuring with the Dependency Inversion Principle

Effective Program Structuring with the Dependency Inversion Principle

The Dependency Inversion Principle

At its heart, the DIP is about structure. The manner in which you structure your program entities, and the way in which they interact with one another, has a direct impact on your ability to conform to the rest of the SOLID principles (the benefits of which we have discussed previously.) If your dependencies are mismanaged, then the likelihood of your code being flexible, maintainable, and reusable is drastically diminished.

In his paper on the DIP, Robert C. Martin enumerates the primary characteristics of poorly-designed software as follows: it is rigid, meaning that it is hard to change due to the cascading effects of changes in one place into another; it is fragile, meaning that changes result in unexpected breakage; and, it is immobile

, in that you cannot reuse entities due to their entanglement with one another. [1] Martin attributes these problems primarily to poor structural design. As entities become more tightly coupled to one another, their rigidity, fragility, and immobility increase. In other words, dependency management is the key to writing software that is more flexible and therefore easier to maintain and reuse.

If the problem with bad software is related to dependency structure, then what is the solution? It is here that Martin flips the classic dependency structure on its head and argues for dependency inversion. In traditional entity layering, higher level entities depend on lower level entities, which in turn depend on even lower level entities. This is a typical top-down structure wherein entities that perform work at the policy level will delegate behavior down an increasingly detail-focused chain of dependencies. The problem with this model is that changes at the lower level can force changes at the higher level, which in turn makes reuse of higher level entities very difficult. Compare this to an “inverted” dependency structure wherein both high-level and low-level entities depend on shared abstractions. Here, different layers within a software program form a contract with one another to use a shared abstraction when they interact. In doing so, the layers free themselves to implement details however they may choose without concern for affecting one another.

Put concisely, the DIP says that high- and low-level modules should depend on mutual abstractions, and furthermore, that details should depend on abstractions rather than vice versa. By implementing a dependency structure that follows this principle, you can free your modules from one another in a way that opens them up for reuse. So long as an entity conforms to the prescribed contract of its abstraction dependencies, it can be used anywhere.