- A. High level modules should not depend upon low level modules. Both should depend upon abstractions.
- B. Abstractions should not depend upon details. Details should depend upon abstractions. (http://www.objectmentor.com/publications/dip.pdf)
We wish to avoid designs which are:
- Rigid (Hard to change due to dependencies. Especially since dependencies are transitive.)
- Fragile (Changes cause unexpected bugs.)
- Immobile (Difficult to reuse due to implicit dependence on current application code.)
“Structured” methods of the 1970’s tended towards a “top-down decomposition”, which encouraged high-level modules to depend on modules written at a lower level of abstraction. (More modern procedural approaches depend more on databases and less on functional decomposition at the large-scale level. Thus, they are often “flatter” now.) This principle stems from the realization that we must reverse the direction of these dependencies to avoid rigidity, fragility and immobility. [edited from Robert’s original to reflect modern procedural philosophy]
What does this mean to testability? When test subjects depend on abstractions, adhering to DIP, the option of interaction based testing(IBT) is available without refactoring. This increases testability. Clearly IBT has been a running theme in the last three posts in this series. Besides providing a design to allow the use of test doubles for validation purposes DIP can be important in breaking of dependencies. When working with a third part component for example you might couple to a concrete type instead of an abstraction. Coupling to the concrete type, also know as strong coupling, effects testability in that you must include that type from the third party component in your test execution. Sometimes this may not be of much consequence but in many other times this can mean being dependent on say, an email server for test execution. Coupling to an abstraction, also known as loose coupling, provides an opportunity to insert a test double.
What ever your reason compliance with DIP increases testability by providing dependency relationships that allow for insertion of test doubles.