8 ms·
"This should never happen" is a design pattern of defensive programming. This is the same pattern for assert. The usual use is to catch errors caused by misus
by dzdt 11y ago
"This should never happen" is a design pattern of defensive programming. This is the same pattern for assert.
The usual use is to catch errors caused by misuse of a method. There is some invariant that the method assumes but is not enforced by the type signature of the interface. So if something goes wrong in outside code, or someone tries to use the method incorrectly, the invariant is not satisfied. When you catch such a problem, the current code context is FUBAR. The question is how aggressively to bail out : spew errors to a log and proceed with some GIGO calculation? Throw an exception? Exit the program?
- zaphar 11y agoAnd this pattern is exactly why I prefer compile time type safety in my languages. This pattern is still sometimes necessary but there is a whole class of error this pattern gets used for that you can many times eliminate.
- gue5t 11y agoWhat's interesting is that (as described in the present top comment on this article, about "CALL BRIAN"), if the abstraction of "type safety" is leaky (as it is, e.g. in the presence of memory or hardware errors), this kind of paranoia can actually have real-world benefits even though you can prove the impossibility of the code running using static analysis. Sometimes the important artifact is the executable in the larger context of the deployed system, rather than the code you generate it from.
- nightski 11y agoThere is nothing preventing modeling the contextual environment within static analysis. Static analysis/type systems help the programmer draw the line between the known and the unknown. Some conditions are just not practical or efficient to check for. However for the context you use it within you can make certain guarantees about the code. This is still incredibly useful even though it doesn't guarantee an error can never take place. You say it "is" leaky in the presence of memory corruption. However that is not necessarily true. One could model software memory verification within a type system. Meaning, you could guarantee at compile time that each time a variable is read it is verified via checksum against its last written value. This would not be particularly efficient, but the point stands that type systems can be used (and should be used) to model hardware failures. This is no different than network link failures, etc...
- TillE 11y agoAnd how do you verify that your checksum-verifying code hasn't been corrupted with cosmic rays? The real world is messy. We can mitigate that, but we can never have mathematical purity.
- nightski 11y agoThat is exactly the point, to mitigate it. Just because you can't mitigate everything doesn't mean it is less valuable. It is still extremely valuable to mitigate the things you do (or choose to) have control over.
- chopin 11y agoIn typed languages this is pretty often circumvented by choosing the wrong type. Java (even the language library) is literally littered with API's which take a String where the parameter does not have the semantics of a string (a bunch of characters with no meaning). The worst offenders take a String, support only a very limited subset and offer no explanation which are valid ones.
- ctdonath 11y agoIt's a sub-pattern of "ain't got time for dat". Developer knows that condition should never happen, but is not inclined to prove it (as represented by coding type checking or other handling) yet realizes it shouldn't be ignored outright (if only to document the unproven condition in code, or to shut the compiler up about incompleteness warnings).
- pron 11y ago> is not inclined to prove it (as represented by coding type checking or other handling) This is known as a reachability problem that in the general case cannot be proven. So, "not inclined" may actually mean "can't (in any reasonable amount of time)".
- dasil003 11y agoI came to say much the same thing, but even take it a step further and point out that proofs are subject to human error as well. More powerful programming constructs are a great tool, but at some point it's turtles all the way down. The Knuth quote comes to mind: "Beware of bugs in the above code; I have only proved it correct, not tried it."
- semi-extrinsic 11y agoIt's not "in any reasonable amount of time". Proving in the general case whether a variable is unused in code or not is equivalent to solving the halting problem. This follows from Rice's theorem: https://en.wikipedia.org/wiki/Rice%27s_theorem#Proof_by_reduction_to_the_halting_problem https://en.wikipedia.org/wiki/Rice%27s_theorem#Proof_by_redu...
- pron 11y agoYes, but it's more nuanced than that. Even if you can prove that a computation always terminates you can't necessarily prove that it yields the wanted result in any reasonable amount of time. This is the bounded halting problem, and it applies even to languages that only allow terminating computations. In those languages, the halting problem is nominally gone, but the bounded halting problem is just as bad as for Turing-complete languages. Just how bad is it? It is a time complexity class that includes all time complexity classes, i.e. it is harder (in general) than any problem that is computable and known to complete within f(n) steps, where n is the size of the input and f is any computable function.
- Someone1234 11y agoI agree that it does demonstrate defensive programming. But can I also just add that the error message remains unhelpful and outright "bad." You should absolutely have checks for "impossible" situations, but when those checks fail you need some way of determining which check failed (and cannot always assume you'll have stack backtrace, in particular if an end-user is telling you the error message). For example you could do this: "Impossible Error in GetName(): {Exception}"
- wellpast 11y agoRight. An identical query: https://github.com/search?utf8=%E2%9C%93&q=IllegalStateException&type=Code&ref=searchresults https://github.com/search?utf8=%E2%9C%93&q=IllegalStateExcep...