Dependency inversion principle
RobertLechte (Talk | contribs) |
Tanmay Bhola (Talk | contribs) m |
||
(7 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
− | + | Often we would like to be able to reuse high level modules because they provide some general functionality which fits closely with some new problem we are trying to solve. The problem is that often these high level modules depend a great deal on the lower level modules they make use of. In this situation, what we need is an interface between the high and low level modules. Both the high and low level modules are then written to depend upon this interface, and so they do not depend upon one another. This allows us to interchange and reuse both the high and low level modules in a variety of situations. | |
+ | |||
+ | [[Bob Martin]] observed this effect and stated the following to summarize the Dependency Inversion Principle (DIP): | ||
:''"High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions."'' | :''"High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions."'' | ||
− | + | In OO design, the DIP is usually realized by a design similar to that depicted in the following diagram: | |
− | + | [[Image: Dependancy Inversion Principle.jpg]] | |
− | + | In this situation the high and low level modules are classes, and the interface between these classes is provided by the two abstract classes they inherit from. The ConcreteHighLevel class only depends upon the AbstractLowLevel class, and the ConcreteLowLevel class only depends upon the AbstractHighLevel class. So we can alter or add to the low level behavior by simply using a new ConcreteLowLevel class, and the ConcreteHighLevel class will be unaffected. From a different perspective, this means we can reuse the ConcreteHighLevel class so long as we provide a new ConcreteLowLevel class which conforms to the AbstractLowLevel interface and depends only on the AbstractHighLevel interface. | |
− | + | An additional advantage of following the DIP is that the hard to simulate low level functions do not need to be written before high level functions are tested. This allows for a top-down approach to design and development. | |
+ | |||
+ | The term "inversion" refers to how this principle differs from the design that would be typical of more traditional procedural methods. Procedural designs often resulted in high level modules depending on low level modules, and where abstractions depended on details. Thus, applying DIP to an OO design is effectively "inverting" the design that would usually have resulted from more traditional procedural methods. | ||
=== Typical Example === | === Typical Example === | ||
File "Streams": Both high and low level code is written to meet the "stream" interface. | File "Streams": Both high and low level code is written to meet the "stream" interface. | ||
+ | |||
+ | == See Also == | ||
+ | *[[Design by contract]] | ||
+ | *[[Program to the interface not the implementation]] | ||
+ | |||
+ | [[Category:Riel's heuristics]] | ||
+ | [[Category:Bob Martin's principles]] |
Latest revision as of 00:19, 19 October 2010
Often we would like to be able to reuse high level modules because they provide some general functionality which fits closely with some new problem we are trying to solve. The problem is that often these high level modules depend a great deal on the lower level modules they make use of. In this situation, what we need is an interface between the high and low level modules. Both the high and low level modules are then written to depend upon this interface, and so they do not depend upon one another. This allows us to interchange and reuse both the high and low level modules in a variety of situations.
Bob Martin observed this effect and stated the following to summarize the Dependency Inversion Principle (DIP):
- "High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions."
In OO design, the DIP is usually realized by a design similar to that depicted in the following diagram:
In this situation the high and low level modules are classes, and the interface between these classes is provided by the two abstract classes they inherit from. The ConcreteHighLevel class only depends upon the AbstractLowLevel class, and the ConcreteLowLevel class only depends upon the AbstractHighLevel class. So we can alter or add to the low level behavior by simply using a new ConcreteLowLevel class, and the ConcreteHighLevel class will be unaffected. From a different perspective, this means we can reuse the ConcreteHighLevel class so long as we provide a new ConcreteLowLevel class which conforms to the AbstractLowLevel interface and depends only on the AbstractHighLevel interface.
An additional advantage of following the DIP is that the hard to simulate low level functions do not need to be written before high level functions are tested. This allows for a top-down approach to design and development.
The term "inversion" refers to how this principle differs from the design that would be typical of more traditional procedural methods. Procedural designs often resulted in high level modules depending on low level modules, and where abstractions depended on details. Thus, applying DIP to an OO design is effectively "inverting" the design that would usually have resulted from more traditional procedural methods.
Typical Example
File "Streams": Both high and low level code is written to meet the "stream" interface.