Chapter 11 is on the Dependency-Inversion Principle:
This principle is closely related to two other principles that I have talked about previously:
- Open-Closed Principle – Modules should be open for extension, but closed for modification.
- Low Coupling GRASP Pattern – An element with low (or weak) coupling is not dependent on too many other elements.
All three of these principles have to do with making your applications loosely coupled by not depending on concrete classes when appropriate, but abstractions. These abstractions are usually done with abstract classes, polymorphic methods, and interfaces. This book has tended to focus on abstract classes, but you can find other books that prefer interfaces, etc. There are pros and cons to each, and that subject is beyond the scope of this post :).
This principle is unique with respect to the others in that it points out the direction of dependency on the abstraction. Rather than having the policy and business level classes dependent on the lower-level plumbing / utility type detail classes, it recommends that you invert the dependency and make the lower-level detail classes dependent on the higher level policy making classes that are most important in your application.
Robert said it best in this brief, well-written chunk of text from his book:
“Consider the implications of high level modules that depend upon low level modules. It is the high level modules that contain the important policy decisions and business models of an application. It is these models that contain the identity of the application. Yet, when these modules depend upon the lower level modules, then changes to the lower level modules can have direct effects upon them; and can force them to change.
This predicament is absurd! It is the high level modules that ought to be forcing the low level modules to change. It is the high level modules that should take precedence over the lower level modules. High level modules simply should not depend upon low level modules in any way.
Moreover, it is high level modules that we want to be able to reuse. We are already quite good at reusing low level modules in the form of subroutine libraries. When high level modules depend upon low level modules, it becomes very difficult to reuse those high level modules in different contexts. However, when the high level modules are independent of the low level modules, then the high level modules can be reused quite simply.[Martin, p.127-128]”
You can see this visually in the following figures:
This is a very, very common practice. Everything in the Enterprise Library Application Block uses this principle to make it pluggable so that you can add new caching strategies, data repositories, configuration policies, etc. It is also used in anything that uses the Provider Model, because this is the basis of the Provider Model – provide an abstraction in the .NET framework that your application can utilize and have components that provide the detail be dependent on that abstraction used in your application.
You can see my posts on DotNetNuke and Community Server for a little bit of information on the Provider Model – the pre .NET 2.0 version anyway, which I have used several times in applications:
- Community Server Source Code – Abstract Classes, Reflection and Data Providers
- DotNetNuke Architecture – Digging Into the DNN Source Code
You can read Robert’s words about the Dependency-Inversion Principle in this PDF. A couple chapters from now I will start digging into a lot of the Design Patterns that support these principles.
[Sipping on: Jasmine Pearls Green Tea]