The Right Approach to Exceptions

Nick Sabalausky a at a.a
Sun Feb 19 11:19:04 PST 2012


"Andrei Alexandrescu" <SeeWebsiteForEmail at erdani.org> wrote in message 
news:jhrave$2nas$1 at digitalmars.com...
> On 2/19/12 4:30 AM, Juan Manuel Cabo wrote:
>> Now, expanding on the hierarchy: I said that it makes no sense to
>> subclass UnrecoverableExceptions. Recoverable exceptions on the other
>> hand, need to be subclassed _with_the_catch_on_your_mind_. You are
>> passing info from the throw site to the catch site. The catch block is
>> the interpreter of the info, the observer. You are communicating
>> something to the catch block.
>>
>> So please, do not create a new types if there is no value in writing a
>> catch that only cathes that exception and that can recover from that
>> exception. Otherwise, use an existing type.
>
> I think this is a very sensible point. I wonder to what extent it clashes 
> with a simple idea that just occurred to me. It would be very easy to 
> define a hierarchy as follows:
>
> class ModuleException(string theModule) : 
> PackageException(packageOf(theModule))
> {
>     ...
> }
>
> Then any module could issue
>
> throw new ModuleException!(.stringof);
>
> That way the exception hierarchy would parallel the module hierarchy. (A 
> module is free to define more specific exception inheriting 
> ModuleException!(.stringof)).
>
> The catcher would catch things like ModuleException!"acme.text.io" and 
> such.
>
> In that approach, all exceptions thrown from Phobos would inherit 
> PackageException!"std" and all exceptions thrown from std.getopt would be 
> (or inherit) ModuleException!"std.getopt".
>
> This would save a lot on the boilerplate while still keeping open the 
> option of defining fine-grained hierarchies. Any thoughts, please chime.
>

That wouldn't be as useful. What the catcher is typically interested in is 
*what* happened, not *where* it happened.

For example, if I want to do something upon a network error, minimum 99 
times out of 100 I don't give a shit if it came from libNetworkFoo or 
libNetworkBar, and I don't *want* to care. What I care is whether or not 
there was a "network" error and possibly what *conceptual* type of network 
error.

Furthurmore, what if I change some implementation detail to use a different 
module? Then I have to go changing all my catch blocks even though it's 
conceptually the same fucking error handled the same way.

However, I wouldn't object to the idea of an "originatingModule" member 
being added to Exception that's automatically filled by the runtime (perhaps 
lazily). Although really, I think what would be more useful that that would 
be "Does xxx module/package exist in the portion of the callstack that's 
been unwound?"

As far as "when to add or not add an exception class", it's perfectly 
reasonable to err on the side of too many: If there's an unnecessary class, 
you can just ignore it. Problem solved. If there's a missing exception 
class, you're shit out of luck. Case closed.

I can't shake the feeling that we're desperately trying to reinvent the 
wheel here. The round wheel is solid technology with a proven track record, 
we don't need to waste time evaluating all these square and oval wheels just 
for the fuck of it.




More information about the Digitalmars-d mailing list