principles:dependency_inversion_principle
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
principles:dependency_inversion_principle [2021-05-19 11:18] – old revision restored (2021-03-25 15:10) 2a04:ac00:4:d29:5054:ff:fe00:d387 | principles:dependency_inversion_principle [2021-09-02 12:23] – old revision restored (2021-05-11 21:48) 65.21.179.175 | ||
---|---|---|---|
Line 6: | Line 6: | ||
===== Context ===== | ===== Context ===== | ||
/* fill in contexts here: */ | /* fill in contexts here: */ | ||
- | * [[contexts: | + | * [[contexts: |
- | * [[contexts: | + | |
===== Principle Statement ===== | ===== Principle Statement ===== | ||
- | |||
- | Depend on abstractions.((Robert C. Martin: // | ||
===== Description ===== | ===== Description ===== | ||
- | A simplified description of DIP is that a variable declaration should always have the (static) type of an abstract class or '' | ||
- | |||
- | The more elaborate definition by Robert C. Martin reads as follows: | ||
- | |||
- | > a. High-level modules should not depend on low-level modules. Both should depend on abstractions. | ||
- | > b. Abstractions should not depend on details. Details should depend on abstractions.(({{page> | ||
- | |||
- | Following this rule leads to " | ||
- | |||
- | {{ : | ||
- | |||
- | When applying DIP, both modules depend on the abstraction (note that in UML diagrams all arrows point into the direction of the dependency): | ||
- | |||
- | {{ : | ||
- | |||
- | '' | ||
===== Rationale ===== | ===== Rationale ===== | ||
- | When DIP is not applied, only the low-level modules can be reused independently. The higher-level modules depend on the others, so trying to reuse them makes it necessary to either also reuse the lower-level modules or to change the higher-level module. The former is often not wanted because reuse is often done in another context where the lower-level modules do not fit. And the latter is error-prone and requires additional work as it requires changes to already working modules. | ||
===== Strategies ===== | ===== Strategies ===== | ||
- | |||
- | * Apply the [[patterns: | ||
- | * Use events, the observer pattern, etc. to remove dependencies | ||
- | * Apply other forms of [[glossary: | ||
- | * Have an '' | ||
- | * Declare only '' | ||
- | * Do not derive classes from concrete ones (i.\,e.\ non-abstract classes) | ||
- | * Do not override already implemented methods in subclasses | ||
- | |||
- | ===== Caveats ===== | ||
- | |||
- | It is normally not helpful to apply DIP to [[patterns: | ||
- | |||
- | Furthermore note that applying [[patterns: | ||
- | |||
- | See section [[#contrary principles]]. | ||
===== Origin ===== | ===== Origin ===== | ||
- | |||
- | {{page> | ||
===== Evidence ===== | ===== Evidence ===== | ||
/* Comment out what is not applicable and explain the rest: */ | /* Comment out what is not applicable and explain the rest: */ | ||
- | + | /* | |
- | /* * [[wiki: | + | * [[wiki: |
- | /* * [[wiki: | + | * [[wiki: |
- | + | | |
- | [[wiki: | + | * [[wiki: |
- | + | */ | |
- | /* * [[wiki: | + | |
===== Relations to Other Principles ===== | ===== Relations to Other Principles ===== | ||
==== Generalizations ==== | ==== Generalizations ==== | ||
- | |||
- | * [[Low Coupling]] (LC): LC aims at reducing the dependencies to other modules. One way to do so is to only depend on abstractions. DIP is about this aspect. | ||
==== Specializations ==== | ==== Specializations ==== | ||
==== Contrary Principles ==== | ==== Contrary Principles ==== | ||
- | |||
- | * [[More Is More Complex]] (MIMC): DIP demands introducing abstractions, | ||
==== Complementary Principles ==== | ==== Complementary Principles ==== | ||
- | * [[Model Principle]] | + | * [[principles: |
+ | * [[principles: | ||
+ | * [[principles: | ||
+ | * [[principles:Encapsulate the Concept that Varies]] | ||
==== Principle Collections ==== | ==== Principle Collections ==== | ||
Line 94: | Line 53: | ||
{{page> | {{page> | ||
- | ===== Examples | + | ===== Example |
- | ==== Example 1: Furnace ==== | ||
- | An example for a high-level module is a regulator module of a furnace. The classical approach would result in the regulator depending on a thermometer and a heater. in such a case it would not be possible to reuse the regulator module for regulating the fluid level of a reservoir or the speed of a car. A DIP-compliant solution would result in the regulator just depending on a sensor module and an actuator module and thermometer and header implementing these '' | ||
- | |||
- | This example is taken from (({{page> | ||
- | |||
- | ==== Example 2: Client Repository ==== | ||
- | |||
- | Let's say the high-level module (your business logic), wants to be able to add or remove users to the database. Instead of it talking to the database directly, it defines an interface called ClientRepository which contains the methods the business logic needs. Then a MySQLClientRepository concretion, implements that interface and uses a database library to submit the queries. Since the interface is decided by the business logic, the high-level policy is protected from changes in the database library. More over, since the interface was defined by the business logic, it does not reveal anything about the underlying implementation, | ||
===== Description Status ===== | ===== Description Status ===== | ||
/* Choose one of the following and comment out the rest: */ | /* Choose one of the following and comment out the rest: */ | ||
- | /*[[wiki: | + | [[wiki: |
/ | / | ||
- | [[wiki: | + | /*[[wiki: |
===== Further Reading ===== | ===== Further Reading ===== | ||
- | * {{page> | ||
- | * {{page> | ||
- | * {{page> | ||
- | * [[wiki> | ||
- | * [[wp> | ||
- | |||
- | ===== Discussion ===== | ||
- | Discuss this wiki article and the principle on the corresponding [[talk: |
principles/dependency_inversion_principle.txt · Last modified: 2021-10-18 21:23 by christian