Exceptions are meant to communicate to your caller that you couldn't fulfill your job. [That's the most-ignored fact about exceptions.]
That's good advice. As soon as you find out that you can't complete successfully, it's best to immediately inform your caller about that fact (after cleaning up any inconsistent state that you'd otherwise left behind, it that applies to your application).
Continuing in your program is typically useless, can even be dangerous because of missing or wrong data.
So, e.g. when opening a file, don't immediately catch the exception, log it and continue. The following code will try to read from that file and of course fail as well.
Generally, you write program statements because your logic needs them. So, if one of your steps fails, the whole method won't give the desired results. So, let exceptions that you receive simply bubble up the stack, and actively throw appropriate exceptions whenever you detect failure conditions.
Although a good general guideline, "Avoid Catching" is over-simplified.
Better: think three times if you really want to catch exceptions here in this place. I've seen lots and lots of code cluttered with try/catch constructs that are unnecessary and most of the time even quality traps or plain programming mistakes.
Catch exceptions only in places where you can successfully continue, even after some of your program so far has failed. That translates to the question: Do I have a fallback or recovery strategy available that can turn the failure I just experienced into a success? Maybe by a retry/reconnect or by having an alternative algorithm or whatever.
In catching exceptions, you have to be honest to yourself:
- You know that something in your current code block failed.
- You also know how the failing code labeled the type of failure (by means of creating its exception object), or how some layer in-between re-labeled the original failure reason (by wrapping the original exception object). [You see, this isn't the most reliable source of information.]
- Take into account that a given exception type might come from any enclosed piece of code, from any level deep down the stack. So don't assume you know what happened from just looking at the exception object.
- Having only these informations, can you turn your current method into success?
An honest answer to this reasoning will be "No" in most cases. And then don't catch the exception.
Valid "Yes" situations are e.g. having a retry/reconnect strategy at hand, or an alternative algorithm, or just reasoning about optional code, something like a cleanup that's nice to have, but not necessary for making your current method succeed.
You should finally catch exceptions at some top-level (user-interface action level, service API top layer, etc.). There:
- log the error,
- tell the user or your client that their request failed,
- and wait for the next request, that probably (hopefully?) won't run into the same problem.
What the author calls a supervisor translates to a well-designed catch block in more traditional languages: a place where you know how to deal with a failure in such a way that you can meaningfully continue.