6 ms·
Where the Howler here?
by Banana699 4y ago
Where the Howler here?
- goto11 4y agoThere is certainly some faulty reasoning in: > I don’t like exceptions because they are, effectively, an invisible goto This is supposes to invoke dread because everyone knows goto's are evil right? But if any jump to a different place in the code is a goto, then if/else/while are also goto's, and so are functions and returns.
- ncmncm 4y agoIt is the "invisible" bit that bothers Joel. But of course nothing is invisible: there is a perfectly visible function call operator "()" right there, that he should assume an exception may bubble out of, and act accordingly.
- goto11 4y agoI guess you could call exception an "invisible return", since it is not obvious that "foo()" may exit the current function. But "invisible return" sounds rather less nefarious than "invisible goto". I like Rusts "foo()?" syntax which explicitly indicates that the function call may exit with an error.
- Banana699 4y agoI'm not sure you're giving that argument all what it deserves. Control structures and function calls are a very statically-well-behaved control flow: unlike gotos, when you see a jump you know exactly where its destination is (runtime polymorphism for functions\methods is... an exception, and that's why some people don't like it.), unlike a goto where that might be a dynamic address. The Return is the only modern goto with a dynamic destination, but even then the destination is not completely arbitary (stack discipline), and actually the destination is irrelevant if the function is a well-named non-leaky abstraction, the function simply returns to its "caller", wherever it may be. Furthermore, traditional control flow is Structured, it "owns" its jump labels. Nobody can jump to an else clause of a conditional except that conditional, nobody can jump to a loop start except the code immediately before it or the loop end (breaks and continues are, again, limited exceptions to this, and that's why some people don't like them), only the Returns of a function can jump back to the callsite of that function. As utterly trivial and basic as that sounds, it's a marvel. Gotos are nothing like this, they jump to public labels, anybody can jump to the label, it's a communism of control flow. Exceptions break all of that. You don't statically know what's the destination of a Throw is, and unlike a Return, the destination is not irrelevant, the program is disrupted, you really need to know where that Throw is going to end up. Throws don't own their catches as well, any Throw can jump to the same Catch. In a very real sense, Exceptions are more dangerous gotos than ifs and whiles.
- ncmncm 4y agoYou manifestly don't care what the destination of an exception is. Aggressively so. The only choice to make is: here, or not here. If here is at a high enough level to do something intelligent about it, catch it. If not, it is not your problem: there is nothing to be done, so you do that. Generally, a good program will have very few places where exceptions are caught, and the code there is easily exercised and well tested. The destructors that run on the way there are also well exercised because they run with or without exceptions. Beware code that only ever runs in exceptional cases. It grows bugs when what was correct becomes wrong as the code changes around it.
- goto11 4y agoExceptions are like returns, they go back up the call stack. You cant statically determine where a return will end up either, since it depends on where the function was called. > unlike a Return, the destination is not irrelevant, the program is disrupted, you really need to know where that Throw is going to end up. I don't follow your reasoning here. A function should not know where it returns to and a throw should not know where the exceptions will be caught. That is the point of those constructs. If you know exactly at the point of throwing how you want the exception to be handled, then you wouldn't need to throw an exception in the first place.
- Banana699 4y agoYes exactly, exceptions are much much nastier returns. Returns only go up exactly 1 frame, and the call/return pairs are balanced no matter what. Exceptions can unwind the entire stack, and the throw/catch pairs aren't balanced automatically. Returns of a single function own their call sites, nobody jumps to their call site except them, but a single catch accept every single throw from arbitrarily deep into the stack. Exceptions are an entire call/return system hidden beneath the vanilla call/return system, with less thought in the design and more foot guns. >I don't follow your reasoning here Okay forget it, it was a somewhat subjective point, my main point is as above, exceptions are extremely spicy returns, they interact dangerously with the regular call/return system and scoping. That's essentially all of what objections to exceptions boil down to, and it's a legitimate reason to hate and avoid them.
- ArrayBoundCheck 4y agoBut exceptions do invoke dread in me. Sometimes a goto (or 11) will skip an array bounds check. - This comment is mostly a joke, look at our names. But I did see this happen at least once
- ncmncm 4y agoNot to give it away, but another example is when Joel says that, to know whether dosomething() might throw an exception, you have to read all down through its call tree, you know you are off in the weeds. Obviously it might throw. Even if it doesn't today, it might tomorrow. So you don't need to guess or explore whether cleanup(), there, is wrong. You already know it's wrong. Cleanup code goes in destructors. Period. Destructors always run. Other people posting here have noted that using our language's type system intelligently is how we make trouble fail to compile. Counting on our and our colleagues' finely-tuned sense of rightness to keep out bad code is a recipe for having Bad Code. It suffices to explain Microsoft.