Throwable class design

H. S. Teoh hsteoh at quickfur.ath.cx
Wed Jan 30 09:43:53 PST 2013


On Wed, Jan 30, 2013 at 12:43:49AM -0800, Jonathan M Davis wrote:
> On Wednesday, January 30, 2013 08:32:47 rumbu wrote:
> > On Wednesday, 30 January 2013 at 07:01:56 UTC, H. S. Teoh wrote:
> > > Not true. I use this idiom a lot: a lower level function throws an
> > > error message (e.g., integer format error), and a catch-block
> > > halfway up the call-chain modifies .msg to include contextual
> > > information (e.g., filename, line number) and rethrows the
> > > exception, so that at the top level the error message contains
> > > both context information and the low-level error message.
> > > 
> > > 
> > > T
> > 
> > I thought exceptions are meant to be catched, not rethrown.
> > 
> > If you are the developper of an end user solution, you'll catch
> > the exception and you will display a message some way with the
> > details that you need, or, better, you will silently drop the
> > exception taking the necessary actions to resolve the cause.
> > Throwing exceptions in the user's face is not so friendly.

The point is that an error has occurred, and normal processing cannot
continue, so an exception is thrown.

The catching here is not to throw an exception "at the user's face"; it
is to insert additional information about the problem at an intermediate
level up the call-chain. Further up the call chain, the application
would still catch the exception and display the message.

The rationale for modifying the exception message is that (1) the
low-level code that threw the original exception does not have enough
context to be able to provide a helpful message (e.g., it doesn't
directly know which filename/line number it's processing, it's just a
low-level dumb conversion routine), and (2) a little further up the call
chain are functions that *do* have enough context to insert helpful
information, so they catch the exception, add on the context
information, and rethrow the exception to continue propagating the error
condition. This way, you will get to see both the exact problem that
caused the processing to fail (the original .msg) and also where in the
input (filename/line number) that triggered this problem.


> > If you are a library developper, you'll catch the exception and
> > you will rethrow *another* exception wrapping the original
> > exception in the next field through the constructor. Target
> > developpers of your library have no interest in your detailed
> > message, but in the *type* of the exception thrown. Their program
> > flow cannot interpret messages.

The message is intended for the end-user, not the library code.


> Exceptions get rethrown all the time. Heck, that's what happens with
> finally, scope(failure), and scope(exit). It's what you do when you
> need to react to the fact that the exception was thrown (maybe even to
> the specific exception) but aren't going to handle it in that section
> of code.
> 
> Now, mutating the exception before rethrowing is another thing. I'd
> tend to think that that was bad practice, but I suppose that it could
> be useful upon occasion. In general though, if I wanted to add
> information, I'd wrap the caught exception in a new exception and
> throw that.
[...]

In my case, I guess I didn't really see the need to invent another
wrapper exception type just to be able to insert filename/line number
information. As far as the application code is concerned, a parsing
error is a parsing error; it shouldn't need to know if said parsing
error is a wrapper class containing the real exception object. All it
cares to know is, a problem occurred, and the .msg field contains a
description of the problem that can be displayed to the user.


T

-- 
Windows: the ultimate triumph of marketing over technology. -- Adrian von Bidder


More information about the Digitalmars-d mailing list