Exactly. But the upstream caller of your function might need it.
And that’s the beauty of it. If I don’t know how to handle a particular error in one context, I can just leave it and let it propagate upwards.
For example downloadFile()->parseHttpResponseStrean()->readSocket()
If readSocket throws a timeoutError I don’t need every http library to explicitly deal with it. What can they even do about it, apart from retrying? The application level code calling the downloadFile function is still free to catch the error and gracefully show an error to the user or use a default file from disk if they please.
auto fileOrError = downloadFile();
if (fileOrError is error) {...} if err != nil {
…
}
Just take a look at any golang project, it has more error handling than business logic. If you are writing flight avionics sw this might be a good thing, but for my cat pic sharing MVP I’m happy to just print “unhandled internal error” when the DB stops responding due to unusual hug of death overload. There is nothing else that can be done to recover this error anyway.On top of this it still isn’t bullet proof. There are infinite number of errors that can happen almost anywhere, especially when IO is involved; Disconnects, Time-outs, StackOverflow, ArrayOutOfBounds, DivideByZero, Overflow, NoSuchKeyInDictionary. And so on and so on.
Going back to go, Many low quality libraries still use panic, which gives you two ways to handle errors, one which is considered exotic so you don’t normally put recover() in place, then get bitten at worst moment.
Another example being Java where checked exceptions force beginners to handle errors, where most people don’t know what to do about it, so they just log.error() and return a dummy value, giving no way for upstream to detect such error and causing the program to blow up later instead. That said, checked exceptions is probably the best middle ground between verbosity and safety. It’s just greatly misunderstood.
Very few languages are as finely tuned to the needs of libraries and users of libraries as C++. Exceptions are an essential part of that compact. Failing to abide by it makes your library a bad citizen.
Which is part of the problem. If you're not catching the exception, you don't need exceptions. You just need a way to log stuff, such as a trace, and exit the program. New languages such as Rust and Go encourage this explicitly - that is, use the ordained error path in the return value for expected errors, and only panic for catastrophic errors (or use panic in hotpath where return overhead has unacceptable performance impact and errors are super rare).
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p070...
> Programs bugs are not recoverable run-time errors and so should not be reported as exceptions or error codes. — We must express preconditions, but using a tool other than exceptions... migrate std:: away from throwing exceptions for precondition violations.