principles:invariant_avoidance_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:invariant_avoidance_principle [2013-02-18 17:24] – external edit 127.0.0.1 | principles:invariant_avoidance_principle [2021-09-02 12:37] – old revision restored (2021-05-11 21:58) 65.21.179.175 | ||
---|---|---|---|
Line 10: | Line 10: | ||
===== Principle Statement ===== | ===== Principle Statement ===== | ||
+ | |||
+ | Avoid Invariants and Preconditions. | ||
===== Description ===== | ===== Description ===== | ||
+ | |||
+ | Methods typically have preconditions. Something that has to be true prior to invoking the method so it can work properly. Typical cases are parameters that may not be '' | ||
+ | |||
+ | Furthermore there are (class) invariants, i.e. conditions that have to be true in all observable states during the whole lifetime of an object. Typical invariants are attributes that may not be '' | ||
+ | |||
+ | While preconditions and invariants are absolutely necessary, introducing further ones comes at a certain cost. | ||
+ | |||
+ | Not that this principle does not apply to loop invariants, control-flow invariants, etc. as there is normally no chance to avoid them. But there can be fewer or more class invariants depending on the solution. | ||
===== Rationale ===== | ===== Rationale ===== | ||
+ | |||
+ | A typical kind of defect is the violation of an invariant or a precondition. The more preconditions and invariants there are, the more possibilities there are to introduce defects. And according to [[Murphy' | ||
===== Strategies ===== | ===== Strategies ===== | ||
+ | |||
+ | * If the language supports that, use references which cannot be '' | ||
+ | * In C++ use references instead of pointers (see [[#example 3: C++ references]]) | ||
+ | * In Java use primitive types instead of their object wrappers ('' | ||
+ | * Use [[patterns: | ||
+ | * Avoid duplication of information. If the same information is stored in different places (maybe in different formats), the values may get out of sync (see also [[Don' | ||
===== Caveats ===== | ===== Caveats ===== | ||
- | See section [[#contrary principles]]. | + | Keep in mind that preconditions and invariants are absolutely necessary for every software. So this principle is constantly violated. Introducing preconditions and invariants is often also done deliberately in order to simplify the code (see [[Keep It Simple Stupid|KISS]]). So the purpose of this principle is mainly to point out that there are drawbacks. By no means invariants are problematic themselves or should be entirely avoided. They just also have disadvantages. |
+ | |||
+ | See also section [[#contrary principles]]. | ||
===== Origin ===== | ===== Origin ===== | ||
+ | |||
+ | This principle is newly introduced here. | ||
===== 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: | ||
Line 62: | Line 86: | ||
- | ===== Example ===== | + | ===== Examples ===== |
+ | |||
+ | ==== Example | ||
+ | |||
+ | <code java> | ||
+ | public void prettyPrintItem(List< | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This method has the following preconditions: | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Compare the following solution: | ||
+ | |||
+ | <code java> | ||
+ | public void prettyPrintItem(Item item) | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This is better as it just has one precondition: | ||
+ | |||
+ | |||
+ | ==== Example 2: String Preconditions ==== | ||
+ | |||
+ | <code java> | ||
+ | public void downloadFile(String url) | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This method has the following preconditions: | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Compare the following method: | ||
+ | |||
+ | <code java> | ||
+ | public void downloadFile(URL url) | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This is better since there is only one precondition: | ||
+ | |||
+ | ==== Example 3: C++ References ==== | ||
+ | |||
+ | Sompare the following two methods: | ||
+ | |||
+ | <code c++> | ||
+ | void prettyPrint(SomeClass * obj) | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <code c++> | ||
+ | void prettyPrint(SomeClass& | ||
+ | { | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In the second version '' | ||
+ | |||
+ | |||
+ | ==== Example 4: DRY ==== | ||
+ | |||
+ | A class for [[wp> | ||
+ | |||
+ | So it is better to store just one representation (e.g. the real and imaginary values) and if the other representation is needed (in this case the polar form), it can be computed. This can also be done transparently in the getter method. | ||
+ | |||
+ | |||
+ | ==== Example 5: Caching | ||
+ | |||
+ | All forms of caching and redundancy are typical violations of IAP. They are done in order to increase performance. But there is always the disadvantage that all copies have to be kept in sync as there is the invariant that the data may not be inconsistent throughout the copies. There are forms of caching where temporary inconsistencies are tolerated. This is slightly better in terms of IAP but nevertheless there are these consistency constraints and there is the danger of violating them, so to some degree the disadvantage is always there. | ||
===== 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: |
/ | / | ||
principles/invariant_avoidance_principle.txt · Last modified: 2021-10-18 21:53 by christian