The Right Approach to Exceptions

Jonathan M Davis jmdavisProg at gmx.com
Mon Feb 20 10:52:15 PST 2012


On Monday, February 20, 2012 12:28:27 Andrei Alexandrescu wrote:
> On 2/20/12 12:20 PM, Jonathan M Davis wrote:
> > On Monday, February 20, 2012 18:05:38 foobar wrote:
> >> Separation of concerns - exceptions are meant to notify the
> >> *developer* of errors. User facing error messages is a separate
> >> concern that exceptions should not be responsible for. it's not
> >> just outsourcing the translation strings, it's the developer's
> >> job to determine what if at all should be done with the exception.
> > 
> > Agreed. Users shouldn't be seeing exception messages. They are intended
> > for
> > the developer. Users don't know or care about them. You don't display
> > error
> > codes to users when something goes wrong do you?
> 
> You don't want to duplicate all over the place formatting code do you?

Most of the time that won't happen simply because you need different formatting 
code for different types of errors and contexts. And if it does, you can just 
write a function which takes the exception and prints out the message that you 
want with the formatting that you want.

Also, for contexts where you're going to give a message to the user, toString 
doesn't cut it, because it's doing stuff like putting the stack trace in the 
message. So, do you intend to effectively have _two_ error messages with every 
exception - one for the developer and one for the user?

So, in the cases where you need to save on formatting code, I don't think that 
it's hard to do so without adding anything to Exception, and it's stuff which 
frequently needs to be application-specific anyway, in which case, Exception 
couldn't possibly provide the right message anyway.

> > And adding an
> > internationalization mechanism would actually make things _worse_, because
> > it complicates exceptions for something that they don't generally need,
> > and it makes debugging harder, because you can't see the message as
> > easily in the debugger.
> > 
> > The fields and functions that exceptions have should be geared towards
> > facilitating the program processing and recovering from the exception, not
> > printing out error messages. And a big part of that is giving them fields
> > which can be processed programmatically, not ways to print
> > internationalized strings.
> 
> Yes. Programmatic processing in a class hierarchy means you want to push
> policy up and implementation down. If you don't do this, you need to
> duplicate client code to work with each derived class, instead of having
> client code deal with good primitives.

So, instead of

catch(SpecificException1 e)
{
 //use fields specific to this exception to do whatever you need to do
}
catch(SpecificException2 e)
{
 //use fields specific to this exception to do whatever you need to do
}
catch(GenericException e)
{
 //handle the generic exception as best you can given the lack of
 //a specific one
}

you end up with something effectively along the lines of

catch(GenericException e)
{
 if(/* e is SpecificException1 */)
 {
 //use fields specific to this exception to do whatever you need to do
 }
 else if(/* e is SpecificException2 */)
 {
 //use fields specific to this exception to do whatever you need to do
 }
 else
 {
 //handle the generic exception as best you can given the lack of
 //a specific one
 }
}

How is that better? It's throwing away catch's ability to put the program 
execution in the correct handling code. I don't see how your suggestion is an 
improvement over using an actual class hierarchy. You can't generally make the 
handling uniform unless the catch block is simply going to do something like 
log the message rather than handle it. And if you're doing that, you can just 
catch the more generic exception.

It seems like you want to effectively do something like add a method to 
Exception along the lines of handleException which exception handling code 
calls so that it's nice and generic. But it's the exception handling code 
which needs to do specific stuff and thus frequently _can't_ be generic.

Also, how would the whole variant hash work with purity? You can access global 
variables in pure functions. So, I wouldn't expect it to work in a pure 
function. Class hierarchies do. I would think that that would kill the whole 
idea right there, even if it were better than using a class hierarchy (which I 
don't think that it is).

- Jonathan M Davis


More information about the Digitalmars-d mailing list