3 ms·
Exception handling may indeed end up with less code, but often it is because the developers forgot to handle most error situations properly. And that's my bigge
by pkolaczk 5y ago
Exception handling may indeed end up with less code, but often it is because the developers forgot to handle most error situations properly. And that's my biggest gripe with exceptions, particularly the unchecked ones, which can just pop up from 100 layers below. I've just seen it too many times when developers just throw exceptions and let them bubble up to a place where there is so little context that the final error message presented to the user is near useless.
On the other hand return values (using something like a try/either monad) have the property of forcing the developer to think about the unhappy path in every layer. Maybe a bit more code, but the quality of diagnostics - priceless.
IMHO exceptions/panics should be reserved for bugs only (eg assertions), and return values for all the other error handling caused by user input or environment.
- jcelerier 5y ago> I've just seen it too many times when developers just throw exceptions and let them bubble up but it's the whole point ! that's exactly why exceptions are good ! > to a place where there is so little context that the final error message presented to the user is near useless. there are only two valid cases: there's an error that you know you are able to recover from, you did recover, and the users does not see a message and never knows that an error happened, OR the user sees the message "The program has encountered an error. A backup of your data has been saved in c:/foo/. The program will now exit.". Anything else makes software terrible to use. If you have logging and recovery to do, use your logging architecture and core dumps, don't misuse exceptions for that. > On the other hand return values (using something like a try/either monad) have the property of forcing the developer to think about the unhappy path in every layer. Maybe a bit more code, but the quality of diagnostics - priceless. Except what happens in practice is that people just put panics everywhere because most of the time there is no meaningful action one can take at the layer where the implementation happens. Actual examples in servo: https://pastebin.com/0DAFU9vS https://pastebin.com/0DAFU9vS I also invite you to run the following command: $ cd ~/.cargo $ rg panic! | wc -l I get 2987 as a result. Choosing to program like this instead of using exceptions which at least can be recovered by the person who will use your lib, is literally hateful towards users. I've not seen Go code to be meaningfully different either. > IMHO exceptions/panics should be reserved for bugs only (eg assertions), and return values for all the other error handling caused by user input or environment. Sure, this is the community consensus in C++. It's the Python people who use exceptions to get out of for loops :) But the most important rule is that - invalid state must not be representable in the program. There must be no way to get an "invalid" object (unless the object being invalid is part of its possible domain, but this is exceedingly rare when one isn't interfacing with a 1985 C API)
- pkolaczk 5y ago> but it's the whole point ! that's exactly why exceptions are good ! Good for what? For crashing the program with a stacktrace? Probably. But for regular error handling - that's a terrible thing. They break normal control flow by adding a parallel / alternative control flow. Now with them you have to think on what happens if any of the code you call suddenly throws an exception and the number of potential control flow paths increases drastically. They are not referentially transparent and it is nearly impossible to do functional programming with them (they introduce side effects everywhere). You can also end up in a really bad situation when a destructor throws (typically crash). > I get 2987 as a result. Choosing to program like this instead of using exceptions which at least can be recovered by the person who will use your lib, is literally hateful towards users. But panics are Rust equivalent of exceptions. That's the whole point of them. They are used for exceptional cases, which are impossible to recover from (which means the only way to deal with is to dump core and terminate) and most of the time preventable (you can always avoid dividing by zero or going out of array bounds). It looks like we agree they should not be used for regular errors, like e.g. file not found. I'd not like my word processor to terminate with a core dump when it couldn't load the file from the disk. In this case return values are way better error handling mechanism. > invalid state must not be representable in the program Returning an option/try/either strikes that goal just as well as exceptions.
- fpoling 5y agoYou can recover from panic! in Rust on the thread level.
- pkolaczk 5y agoYeah, I know I can recover, that's why I said they are equivalent of C++ exceptions (which can be caught as well). But this is not a recommended idiomatic way of handling expected errors, e.g. input errors, improper configuration, I/O errors etc.