principles:murphy_s_law
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:murphy_s_law [2013-01-15 21:02] – evidence, relations, origin christian | principles:murphy_s_law [2021-09-02 17:57] – old revision restored (2021-05-11 22:11) 65.21.179.175 | ||
---|---|---|---|
Line 3: | Line 3: | ||
===== Variants and Alternative Names ===== | ===== Variants and Alternative Names ===== | ||
- | * Design for Errors((Alan M. Davis: //201 Principles | + | * Design for Errors(({{page> |
===== Context ===== | ===== Context ===== | ||
/* fill in contexts here: */ | /* fill in contexts here: */ | ||
* [[contexts: | * [[contexts: | ||
+ | * [[contexts: | ||
+ | * [[contexts: | ||
+ | * [[contexts: | ||
===== Principle Statement ===== | ===== Principle Statement ===== | ||
Line 23: | Line 25: | ||
It is not always possible to design a system in such a way. But as systems are built and used by humans, one should strive for such " | It is not always possible to design a system in such a way. But as systems are built and used by humans, one should strive for such " | ||
- | Note that Murphy' | + | There are different kinds of possible errors that can and according to ML eventually will occur in some way: Replicated data can get out of sync, invariants can be broken, preconditions can be violated, interfaces can be misunderstood, |
+ | |||
+ | Note that Murphy' | ||
Line 32: | Line 36: | ||
This means the fewer possibilities there are that a mistake is made, the fewer there will be. As mistakes are generally undesirable, | This means the fewer possibilities there are that a mistake is made, the fewer there will be. As mistakes are generally undesirable, | ||
+ | Note that ML does //not// claim that everything constantly fails unless there is no possibility to do so. It simply says that statistically in the long run a system will fail if it can. | ||
===== Strategies ===== | ===== Strategies ===== | ||
This is a very general principle so there is a large variety of possible strategies to adhere more to this principle largely depending on the given design problem: | This is a very general principle so there is a large variety of possible strategies to adhere more to this principle largely depending on the given design problem: | ||
- | * Make use of static typing, so the compiler will report faults. | + | * Make use of static typing, so the compiler will report faults |
- | * Make the design simple, so there will be fewer implementation defects. (see [[Keep It Simple Stupid]]) | + | * Make the design simple, so there will be fewer implementation defects (see [[Keep It Simple Stupid|KISS]]) |
- | * Use automatic testing to find defects. | + | * Use automatic testing to find defects |
- | * Avoid duplication and manual tasks. (see [[principles:Don't Repeat Yourself]]) | + | * Avoid duplication and manual tasks, so necessary changes are not forgotten |
- | * Use polymorphism instead of repeated switch statements. | + | * Use polymorphism instead of repeated switch statements |
+ | * Use the same mechanisms wherever reasonably possible (see [[Uniformity Principle|UP]]) | ||
+ | * Use consistent naming and models throughout the design (see [[Model Principle|MP]]) | ||
+ | * Avoid Preconditions and Invariants (see [[Invariant Avoidance Principle|IAP]]) | ||
+ | * Use assertions to detect problems early. | ||
* ... | * ... | ||
+ | |||
+ | |||
+ | ===== Caveats ===== | ||
+ | |||
+ | See section [[#contrary principles]]. | ||
Line 55: | Line 68: | ||
/* * [[wiki: | /* * [[wiki: | ||
- | * [[wiki: | + | * [[wiki: |
/* * [[wiki: | /* * [[wiki: | ||
+ | Furthermore every defect in any system is a manifestation of ML. If there is a fault then obviously something went wrong. The correlation between the number of possibilities for introducing defects and the actual defect count can be regarded trivially intuitive. | ||
===== Relations to Other Principles ===== | ===== Relations to Other Principles ===== | ||
Line 66: | Line 79: | ||
==== Specializations ==== | ==== Specializations ==== | ||
- | * [[principles:Don't Repeat Yourself]] (DRY): Duplication is a typical example for error possibilities. In case of a change, all instances of a duplicated piece of information have to be changed accordingly. So there is always the possibility to forget to change one of the duplicates. DRY is the application of ML to duplication. | + | * [[Don' |
- | * [[principles:Easy to Use and Hard to Misuse]] (EUHM): Because of ML an interface should be crafted so it is easy to use and hard to misuse. EUHM is the application of ML to interfaces. | + | * [[Easy to Use and Hard to Misuse]] (EUHM): Because of ML an interface should be crafted so it is easy to use and hard to misuse. EUHM is the application of ML to interfaces. |
- | * [[principles: | + | * [[Uniformity Principle]] (UP): A typical source |
+ | * [[Invariant Avoidance Principle]] (IAP): Invariants are statements that have to be true in order to keep a module in a consistent state. ML states that eventually an invariant will be broken resulting in a hard to detect defect. IAP states that invariants should therefore be avoided. So IAP is the application of ML to invariants. | ||
==== Contrary Principles ==== | ==== Contrary Principles ==== | ||
- | * [[principles:Keep It Simple Stupid]] (KISS): On the one hand a simpler design is less prone to implementation errors. | + | |
==== Complementary Principles ==== | ==== Complementary Principles ==== | ||
- | * [[principles:Fail Fast]] (FF): Sometimes it is impossible to actually prevent an error. In such a case it is advisable to fail fast to the mistake | + | |
Line 84: | Line 98: | ||
- | ===== Example | + | ===== Examples |
+ | ==== Example 1: Parameters ==== | ||
+ | Suppose there are two methods of a string class '' | ||
+ | |||
+ | The following method signatures are a bad choice: | ||
+ | <code java> | ||
+ | replaceFirst(String pattern, String replacement) | ||
+ | replaceAll(String replacement, | ||
+ | </ | ||
+ | Eventually someone will mix up the order of the parameters leading to a fault in the software which is not detectable by the compiler. | ||
+ | |||
+ | So it is better to make parameter lists consistent: | ||
+ | <code java> | ||
+ | replaceFirst(String pattern, String replacement) | ||
+ | replaceAll(String pattern, String replacement) | ||
+ | </ | ||
+ | This is less error prone. When for example a call to '' | ||
+ | |||
+ | But here still one could mix up the two string parameters. Although this is less likely, as having the substring to look for first is " | ||
+ | <code java> | ||
+ | replaceFirst(Pattern pattern, String replacement) | ||
+ | replaceAll(Pattern pattern, String replacement) | ||
+ | </ | ||
+ | Here both methods expect a '' | ||
+ | <code java> | ||
+ | "This are a test." | ||
+ | </ | ||
+ | ((Note that in the Java API it would rather be '' | ||
+ | instead of | ||
+ | <code java> | ||
+ | "This are a test." | ||
+ | </ | ||
+ | The [[Keep It Simple Stupid|KISS-Principle]] is about this disadvantage. | ||
+ | |||
+ | ==== Example 2: Casts and Generics ==== | ||
+ | |||
+ | Another example for the application of Murphy' | ||
+ | |||
+ | <code java> | ||
+ | List l = new ArrayList(); | ||
+ | l.add(5); | ||
+ | return (Integer)l.get(0) * 3; | ||
+ | </ | ||
+ | |||
+ | This works but it makes a cast necessary and every cast circumvents type checking by the compiler. This means it is theoretically possible that during maintenance someone will make a mistake and store a value other than Integer in the list: | ||
+ | <code java> | ||
+ | l.add(" | ||
+ | </ | ||
+ | Murphy' | ||
+ | <code java> | ||
+ | List< | ||
+ | l.add(5); | ||
+ | return l.get(0) * 3; | ||
+ | </ | ||
+ | Here this mistake is impossible as the compiler only allows storing integers. | ||
+ | |||
+ | Note that the typecast is rather a symptom than the actual problem here. The problem is, that the '' | ||
+ | |||
+ | ==== Example 3: Date, Mutability/ | ||
+ | |||
+ | In Java the classes [[http:// | ||
+ | |||
+ | <code java> | ||
+ | Date date1 = new Date(2013, 01, 12); | ||
+ | Date date2 = date1; | ||
+ | System.out.println(date1); | ||
+ | System.out.println(date2); | ||
+ | date1.setMonth(2); | ||
+ | System.out.println(date1); | ||
+ | System.out.println(date2); | ||
+ | </ | ||
+ | |||
+ | Furthermore as can be seen in the code above, the month value counterintuitively is zero-based, which results in 1 meaning February. This obviously is another source for mistakes. Also the order of the parameters can be mixed up easily. And lastly this does not refer to a date in 2013 but to one in 3913! The year value is meant to be " | ||
+ | |||
+ | Because of these and several other flaws in the design of the Java date API, most of the methods in '' | ||
===== 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: |
Line 99: | Line 187: | ||
* [[wp> | * [[wp> | ||
* [[wiki> | * [[wiki> | ||
- | * [[http:// | + | |
+ | ===== Discussion ===== | ||
+ | |||
+ | Discuss this wiki article and the principle on the corresponding |
principles/murphy_s_law.txt · Last modified: 2021-10-20 21:18 by christian