When your main argument for not using exceptions for every kind of error handling is performance instead of architecture, then maybe it is a sign that exceptions should simply be constructed to be more performant instead of giving people advice that isn't and can't ever be consistent.<p>As the writer of a library (or just other utility functions), you simply cannot know whether something is an exceptional situation or not, because that is a property of the program and the environment, not the function. Being unable to parse a string to a number, or to create a socket, or to even allocate memory can all be exceptional or not exceptional depending on the context, and often you simply do not know the context this code will run in, or the code will actually run in multiple directly contradictory contexts.
An exceptional condition is arguably anything that means some call in your program can't do its job.<p>Passing error conditions up the call stack to the control layer that displays and/or logs a relevant message is a pain.<p>Exceptions make it less painful.<p><i>Catch</i> blocks should be used sparingly, sure. If you're using them close to where the error is thrown then maybe you should consider an error code-oriented approach. But catch blocks in controller code (or better yet, meta-controller code)? Sure.
"Exceptional" has no reasonable objective definition, especially not at the library level. When you try to open a file by name and it doesn't exist, is that exceptional? It depends on context. Whether something is "predictable and intentional" can even change with product evolution. It's a recipe for bikeshedding. This is a crazy criterion to try to make coding decisions by.<p>Different applications need different trade-offs, and not every API will be suitable for all users. Standard libraries will make decisions according to what kind of applications the language targets. Libraries making other trade-offs can be written to cater to people with other needs.<p>I get that some people are repeatedly encountering situations where they feel like exceptions are used in ways that reduce readability and performance, and they feel like this is a rule that could improve the situation by reducing the use of exceptions across the board, but please, apply your usual criteria of clarity, readability, and performance! If you believe that exceptions are the clearest way of expressing a certain bit of logic in your language and codebase, and that they are acceptably performant, don't get distracted from that by bottomless, ultimately insubstantial arguments about what it means to be "exceptional."<p>Edit: Just wanted to add that I really enjoy the more expressive type systems that make it ergonomic to use return values in a lot of situations where exceptions are otherwise the most readable choice.
Maybe the issue is that "exception" is a really confusing name. Go has the keyword "panic" for errors that stop the current flow and unfold the stack, that makes it clear that you shouldn't use them for anything else than exceptional situations, and they can be "recovered" if they have to be handled explicitely.<p><a href="https://blog.golang.org/defer-panic-and-recover" rel="nofollow">https://blog.golang.org/defer-panic-and-recover</a>
Relatedly, I'm a strong proponent of debugging with "break on all exceptions" enabled. It's very easy to miss bugs if you're not aware of exceptions being thrown but for this to be practical the code must only throw exceptions exceptionally or it's a nightmare to debug.
Fact 1: There are always bugs or unforeseen events in software.<p>Fact 2: When there is an unforeseen event, the developer did not consider what to do.<p>Fact 3: Developers often deal with other people's buggy code.<p>It's clear that exceptions aren't the perfect solution to anything, but given these 3 facts, exceptions are around to stay.
I wonder why callbacks aren't a more popular way for languages to handle exceptions. What if each type of exception registered a weak link to a function with a name like `IOExceptionHandler` which prints a noisy error if it isn't overridden with other behavior?<p>I guess it would be harder to use a single exception callback if you had a lot of similar "try/catch" blocks in different areas of your code, and you'd still probably need to collect some sort of stack trace, but it might work out alright if you go with this article's advice and recommend that people keep exceptions out of their program's normal control flow.<p>I dunno, maybe it's a dumb idea and I've just been spending too much time with microcontrollers lately. They use interrupt callbacks for all kinds of hardware triggers and software events, and I kind of like how you can compartmentalize error handling into a few predictable event handlers.<p>That Java stack trace image at the end of the article also brings back some memories...but I'm feeling much better these days.
For Ruby there's this book, by the exceptional Avdi Grimm
<a href="https://pragprog.com/book/ager/exceptional-ruby" rel="nofollow">https://pragprog.com/book/ager/exceptional-ruby</a> it's a fantastic resource on the subject.
> So exceptions should be exceptional, unusual or rare, much like a asteroid strike!!<p>That's a super huge misread of the text recommendation.<p>I watched a live presentation directly from Jeffrey Richter at the bay area .net user group, oh god about 15 years ago when he described how he came up with this text. In fact it was a call to use exceptions a lot more than we used to, and to avoid error codes. So no, exceptions are not supposed to be rare like that.<p>His main point was to throw if the method name was not achievable, except in specific situations where that breaks user expectations too much, like getting null from missing map entries.
Anecdotally one of my stumbling blocks with clojure was how to deal with errors. The language style heavily pushes to just coding the happy path and using nil punning, instead of exceptions, but sometimes you need to signal errors, so some libraries use keywords for error codes - but now that we have spec the community seems to be shifting opinion to “exceptions are ok-ish if a result of not conforming”. Both error codes and nils make spec definitions ugly, thus all the “maybe not” opinion by Rick... it seems someehat overwhelming, to be honest.
I’ve taken Go’s approach to error handling in new typescript projects. I want to force my team into thinking about IO errors. I want failures to be part of the domain since stack traces only kinda work in Node. We will only throw exceptions if someone didn’t program for bulls properly. Everything else is a Failure instance passed up the call chain. Annoying, but our testing and code-thoughtfulness have gone up.