The Right Approach to Exceptions

H. S. Teoh hsteoh at quickfur.ath.cx
Tue Feb 21 21:47:19 PST 2012


On Tue, Feb 21, 2012 at 07:43:32PM -0500, Jonathan M Davis wrote:
> On Tuesday, February 21, 2012 14:15:03 Andrei Alexandrescu wrote:
> > I thought I was pushing the generics angle, and OO people explained
> > it to me that that was wrong.

I've changed my mind. Now I'm trying to see if the generics angle has
some possibilities. Maybe, maybe not, but we'll never know without
experimenting with it. I think your is_transient idea can be expanded
upon.

The way exceptions are currently implemented, they only carry
information, not behaviour, as Jonathan said rightly.  The try/catch
mechanism essentially reduces to "I've hit a problem I don't know how to
solve, here's a description of it". There's no behaviour in there. The
throwing code has already given up.  It's up to the catcher to interpret
the description of the problem and figure out how to recover. To recover
well, the catcher must know the intimate details of the problem well. So
you have the situation of a specific catcher catching a specific
Exception subclass. This is not an ideal situation, because now
high-level code needs to know the specifics of low-level errors.

With your is_transient idea, though, this begins to change. Now we're no
longer just describing the problem.  When is_transient=1, it means the
thrower is suggesting that perhaps retrying would help. Of course, it's
up to the catcher whether or not to follow through with this suggestion,
but it's one step up from "here's a description of the problem, figure
out the solution yourself". But now the catcher doesn't necessarily have
to know the specifics of the low-level problem. It knows at least one
strategy that might fix the problem, regardless of what the problem is:
retry the operation. This is good, because the low-level code, which
knows the problem best, can offer a useful suggestion (retry). The
high-level code can just take the suggestion or not; it no longer needs
to know low-level details.

But why stop there? Since the low-level code knows all the dirty details
about the problem, it's in the best position to offer meaningful
recovery suggestions. It just has to communicate these possible recovery
strategies to the high-level code, and let the high-level code decide
what to do. The high-level code doesn't need to know how to implement
these strategies -- it's not in the best position to know that anyway.
It just knows, here's a list of recovery strategies, I can go ahead with
one of them, or just call it quits and unwind the stack. The low-level
code is what implements each strategy.

Of course, in order for the high-level code to meaningfully choose
between alternative strategies, the strategies themselves must be
generic concepts; otherwise we're still tying high-level code to
low-level details. So we need to identify generic categories of
exceptions for which this kind of generic recovery is meaningful --
which is what I've done in another post.

I won't repeat the details here, but I just want to say that I think
this angle merits some investigation. It allows us to factor out
exceptions which can be resolved by commonly used recovery strategies so
that we don't have to keep writing tons and tons of exception-specific
recovery code everywhere. Some specific code is still needed, no doubt,
there's always special cases that need specific handling.  But if enough
exceptions can be adequately dealt with generically, then we don't need
to write specific code for them. We can simply reuse generic recovery
solutions.


T

-- 
Real Programmers use "cat > a.out".


More information about the Digitalmars-d mailing list