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