The Right Approach to Exceptions

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Feb 20 09:57:07 PST 2012


On 2/20/12 11:44 AM, foobar wrote:
> This extra processing is orthogonal to the exception. the same exception
> can be logged to a file, processed (per above example) and generate
> graphical notification to the user, etc. The exception contains the
> information pertaining only to what went wrong. the rest is not part of
> this discussion.

Exactly. I don't see how a disagreement follows from here. So isn't it 
reasonable to design the exception such that it can offer information 
pertaining to what went wrong, in a uniform manner?

> The exact same exception in the example would also be thrown on a
> mistyped URL in an application that tries to scrape some info from a
> website for further processing. The error is still the same - the url is
> incorrect but different use cases handle it differently. In the former
> example I might call to a i18n lib (someone already mentioned gettext)
> while in the latter I'll call a logging library with the the mistyped
> url (for statistics' sake).
> in the first I use the url to find a closest match, in the second I want
> to log said requested url. Both handled by *other* mechanisms.
> in both cases the exception needs a url field and in both cases I have
> no need for the Variant[string] map.

The Variant[string] map saves a lot of duplication whenever you want to 
format a human-readable string (which is a common activity with 
exceptions). It transforms this (I'm too lazy to write code anew by 
hand, so I'll paste Jonathan's):

try
     getopt(args, ...)
catch(MissingArgumentException mae)
{
     stderr.writefln("%s is missing an argument", mae.flag);
     return -1;
}
catch(InvalidArgumentException iae)
{
     stderr.writelfln("%s is not a valid argument for %s. You must give 
it a
%s.", mae.arg, mae.flag, mae.expectedType);
     return -1;
}
catch(UnknownFlagException ufe)
{
     stderr.writefln("%s is not a known flag.", ufe.ufe);
     return -1;
}
catch(GetOptException goe)
{
     stderr.writefln("There was an error with %s",  goe.flag);
     return -1;
}
//A delegate that you passed to getopt threw an exception.
catch(YourException ye)
{
     //...
}
catch(Exception e)
{
     stderr.writeln("An unexpected error occured.");
     return -1;
}

into this:

try
     getopt(args, ...)
catch(Exception e)
{
     stderr.writeln(stringTemplate(typeid(e).toString(), e.info));
     return -1;
}

The stringTemplate function loads the formatting template from a table 
indexed on typeid(e).toString() and formats it with the info. It's 
simple factorization.


Andrei


More information about the Digitalmars-d mailing list