
Jochem Berndsen wrote:
András Mocsáry wrote:
*My concern* is about predictable failure of sw written in Haskell. To illustrate it let's see a Haskell pattern matching example:
And in Haskell pattern matching:
switch 1 = "Unchecked"
switch 2 = "Checked"
switch 3 = "Unknown"
Let's say, these are clearly defined states of some objects. Then let's say something unexpected happens: x gets something else than 0 1 2. Now we have a problem, which is most generally fixed in these ways:
switch 1 = "Unchecked"
switch 2 = "Checked"
switch 3 = "Unknown"
switch x = "Nothing"
These general ways really avoid this particular crash, but does something real bad to the code in my opinion.
Agreed. The real cause of the problem is that the programmer didn't prove that x is in {1,2,3} when calling switch.
I agree with most of what you say, just some clarification: Well I'd say it depends on the function's specification. If it is specified with 'precondition: parameter n must be one of 1,2,3', then yes. If it says it works for all integers, then it is the function's fault. Such things must be documented.
Below are some cases x can go wrong: *1. The bad data we got as 'x', could have came from an another part of our very program, which is the REAL CAUSE of the crash, but we successfully hide it.* * Which makes it harder to fix later, and thus eventually means the death of the software product. Eventually someone has to rewrite it. Which is economically bad for the company, since rewriting implies increased costs.
Yes.
2. The bad data we got as 'x', could also could have come form a real word object, we have underestimated, or which changed in the meantime.
You should not assume that your input is correct in fault-tolerant programs.
3. This 'x' could have been corrupted over a network, or by 'mingling' or by other faulty software or something.
Unlikely. There is nothing you can do about this, though.
I'd say this is exactly as point 2. Data you get over the network or from other programs or from the file system should *never* be trusted. Data integrity must be checked and bad data rejected.
Point 1: If we allow ourself such general bugfixes, we eventually kill the ability of the project to 'evolve'.
Point 2: Programmers eventually take up such 'arguably bad' habits, thus making harder to find such bugs.
Thus it would be wiser to tell my people to never write Default cases, and such general pattern matching cases.
It depends, really. See above. Without a spec for the function in question this cannot be decided.
It is a better idea to use the type system to prevent this kind of bugs. In this particular case, it's better to try to have a datatype like data X = One | Two | Three
Yes. But there may be a place where you have to *generate* such data, e.g. if you receive a byte from the network or user input or file, you need to convert this to your type; and this is the point where bad data must be cought. As I said above, I think we basically agree, just wanted to stress the role of the (hopefully documented) specification that should always explicitly state any preconditions. It is then clear which side (caller or callee) is to blame. Cheers Ben