The Right Approach to Exceptions

Regan Heath regan at netmail.co.nz
Mon Feb 20 08:10:11 PST 2012


On Sat, 18 Feb 2012 19:58:14 -0000, H. S. Teoh <hsteoh at quickfur.ath.cx>  
wrote:

> On Sat, Feb 18, 2012 at 08:18:53PM +0100, Nathan M. Swan wrote:
>> On Saturday, 18 February 2012 at 18:52:05 UTC, Andrei Alexandrescu
>> wrote:
>> >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.
> [...]
>> Here's a compromise I would suggest: we have the different exception
>> types for different exceptional behaviors, but still they all
>> descend from a common exception type that has a field with the
>> module name; this way, the client can choose which way they want to
>> go.
>
> I think deadalnix's approach is better. Exceptions should not be
> categorized by module. What if the module depends on submodules? Then
> catching only that module's exceptions will miss exceptions thrown from
> submodules. No, exceptions need to be based on *semantics* rather than
> modules, like CommandLineException, not GetOptException.

The way I currently prefer to use exceptions in C++ is to have 1 exception  
type per module.  That module will catch and wrap *all* exceptions thrown  
by modules it calls. i.e.

[somemodule.cpp]
...
try
{
...
}
catch(OtherModuleException &ex)
{
   throw SomeModuleException("lalala", ex);
}

In this way I know, when calling a method in SomeModule, the only  
exception I need to catch is SomeModuleException.

So, code which uses multiple modules might look like..

try
{
SomeModule a = new..
OtherModule b = new ..
...
a->method();
...
b->method();
}
catch(SomeModuleException ex)
{
...
}
catch(OtherModuleException ex)
{
...
}

where typically one of those modules is something like a tcpip socket  
module, or a database module and the other may be something much more  
specific/different (which internally could use sockets etc).

In the case of more complex modules, where I want to allow different error  
cases to be caught separately I might define multiple exceptions, named on  
error semantics, but all prefixed with the module i.e.  
SomeModule<semantic_error>Exception - but again, the module  
methods/functions will always catch and wrap all exceptions from all  
modules it itself calls so you have a small finite list of exceptions you  
need to worry about.

Basically, I've taken exception handling and flattened it somewhat to make  
it easier to keep track of what exceptions can be thrown when/where and  
what I need to worry about handling.  It is still possible to dig into an  
exception and get the inner/cause exception, and theoretically I could  
alter my behaviour based on that, but I've never needed to yet.

All my exceptions come from a common base, except for certain "errors"  
which are only caught at top level locations i.e. process main, thread  
main, or the top of a conceptual "task" or task engine.  These are derived  
 from a separate base type - much like we have Error and Exception in D -  
in fact, I probably got the idea from this NG :p

>> It would be nice if there was a mixin template that creates an
>> exception class that acts like this; making similar exception
>> classes is annoying.

+1 I use a macro in C++ for this.

Regan

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/


More information about the Digitalmars-d mailing list