Dependency inversion principle

From CSSEMediaWiki
(Difference between revisions)
Jump to: navigation, search
m
 
(5 intermediate revisions by 4 users not shown)
Line 1: Line 1:
As stated by [[Bob Martin]]:
+
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."''
  
The Dependency inversion principle states that high level modules should not depend on low level modules; both (high and low level) modules should depend on abstractions.
+
In OO design, the DIP is usually realized by a design similar to that depicted in the following diagram:
  
It is common in software development to write some low level modules that provide some useful functionality. These modules are then used by the high level modules. This means that the high level modules depend on the low level modules. The Dependency inversion principle states that both high and low level modules should depend on the same, general abstractions, thus inverting the dependency direction.
+
[[Image: Dependancy Inversion Principle.jpg]]
  
An advantage of this is that 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 for design and development.
+
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.
  
[[Image: Dependancy Inversion Principle.jpg]]
+
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 ===
Line 17: Line 21:
 
*[[Design by contract]]
 
*[[Design by contract]]
 
*[[Program to the interface not the implementation]]
 
*[[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:

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

File "Streams": Both high and low level code is written to meet the "stream" interface.

See Also

Personal tools