The Right Approach to Exceptions

deadalnix deadalnix at gmail.com
Mon Feb 20 09:17:18 PST 2012


Le 18/02/2012 19:52, Andrei Alexandrescu a écrit :
> There's a discussion that started in a pull request:
>
> https://github.com/alexrp/phobos/commit/4b87dcf39efeb4ddafe8fe99a0ef9a529c0dcaca
>
>
> Let's come up with a good doctrine for exception defining and handling
> in Phobos. From experience I humbly submit that catching by type is most
> of the time useless.
>
>
> Andrei

By reading the discussion, and by travelling alone by car the whole day, 
I had plenty of time to think about all that. Here are some conclusion 
and a proposal.

1/ Andrei's proposal about transient is great. This is a useful property 
to know about Exceptions and so we should integrate it. This property 
must be pure and const, see why at point 4.

2/ Modules in phobos are organised according to what the do, not how 
they fail. So the Exception hierarchy using modules and package is not a 
good approach. We should use Exception in phobos that user or third 
party lib writter can use, to avoid Exception type proliferation.

3/ An Exception deserve its own type if it can additionnal carry data 
about the problem faced, or is supposed to be handled a very different 
way (ie, FileNotFoundException is likely to be handled differently that 
SecurityException on a function like remove). Most of the time, theses 2 
caracteristics goes with each other.

4/ Sometime, Exception doesn't deserve its own type, but you may want to 
not match all of them. For example, if we have an OracleException with 
an errorcode as defined by oracle documentation, we may want to handle 
some of them differently.

For such a thing, proposal has been made in this thread. Let me expose 
mine. This is not revolutionary and is largely inspired by what was 
posted in this thread. The point is to specify it more clearly.

Let's start with the syntax :

try {
     // Stuff . . .
} catch(Exception e) if(e.transient == false) {
     // Handling . . .
}

If what is in the if is evaluated to false, then the catch block isn't 
selected and the Exception continue its propagation just like no catch 
block were present.

This syntax has proven to be convenient in template instanciation, and 
we should reuse it as much as possible (even if in our case, it is 
evaluated at runtime and not compiletime).

To ensure that it make sense, we need that what is in the if is pure and 
the Exception const. The execution of the test in the if must have no 
side effect.

If what is in the if block throw, then it happen the same than if 
something in the catch block throw : the new Exception is propagated, 
and the old one is linked to that new one.

Alternatively, we can decide that what is in the if must be nothrow too, 
but we still have to consider Errors, so it doesn't solve the problem 
and add useless constraints.

I used the transient property here, but basically any test that is pure 
should be usable. If the Exception is a more specific type, then we can 
use it's property and method, as long as it is pure.

Amaury


More information about the Digitalmars-d mailing list