Jump to page: 1 2 3
Thread overview
Throwable class design
Jan 30, 2013
rumbu
Jan 30, 2013
H. S. Teoh
Jan 30, 2013
Mehrdad
Jan 30, 2013
rumbu
Jan 30, 2013
Jonathan M Davis
Jan 30, 2013
rumbu
Jan 30, 2013
simendsjo
Jan 30, 2013
Jonathan M Davis
Jan 30, 2013
H. S. Teoh
Jan 30, 2013
rumbu
Jan 30, 2013
H. S. Teoh
Jan 30, 2013
Jonathan M Davis
Jan 30, 2013
simendsjo
Jan 31, 2013
Kagamin
Jan 30, 2013
H. S. Teoh
Feb 01, 2013
Sean Kelly
Feb 01, 2013
Andrej Mitrovic
Feb 01, 2013
H. S. Teoh
Feb 01, 2013
rumbu
Feb 01, 2013
Andrej Mitrovic
Feb 01, 2013
Andrej Mitrovic
Feb 01, 2013
Jonathan M Davis
January 30, 2013
I have one question regarding the Throwable, Error and Exception classes.

I cannot understand why members like msg, file, line, info or next are not hidden behind read-only properties or functions. What was the reason behind making these fields public? As far as I know, once an exception is thrown, there is no interest  in modifying contained members.
January 30, 2013
On Wed, Jan 30, 2013 at 07:49:37AM +0100, rumbu wrote:
> I have one question regarding the Throwable, Error and Exception classes.
> 
> I cannot understand why members like msg, file, line, info or next are not hidden behind read-only properties or functions. What was the reason behind making these fields public? As far as I know, once an exception is thrown, there is no interest  in modifying contained members.

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

-- 
The peace of mind---from knowing that viruses which exploit Microsoft system vulnerabilities cannot touch Linux---is priceless. -- Frustrated system administrator.
January 30, 2013
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.


Shouldn't you be throwing a new exception, with the old exception wrapped inside?
January 30, 2013
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.

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.
January 30, 2013
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.
> 
> 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.

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.

- Jonathan M Davis
January 30, 2013
On Wednesday, 30 January 2013 at 08:44:52 UTC, Jonathan M Davis wrote:
>
> 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.
>
> - Jonathan M Davis

Exceptions are not rethrown, finally block is executed *after* throwing/catching the exception. I don't know the details of the scope(*) implementations, but I doubt that they are rethrowing any exceptions. Exceptions are propagated, not rethrown with a mutated message or field.
January 30, 2013
On Wednesday, 30 January 2013 at 09:05:22 UTC, rumbu wrote:
> On Wednesday, 30 January 2013 at 08:44:52 UTC, Jonathan M Davis wrote:
>>
>> 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.
>>
>> - Jonathan M Davis
>
> Exceptions are not rethrown, finally block is executed *after* throwing/catching the exception. I don't know the details of the scope(*) implementations, but I doubt that they are rethrowing any exceptions. Exceptions are propagated, not rethrown with a mutated message or field.

Finally needs to rethrow the exception at the end of the scope. If an exception is thrown in the finally clause, it is chained at the end of the exception currently in flight.

I'm pretty sure scope(*) just lowers to try/catch/finally:
try {
  // something
  // scope(success)
} catch (Exception) {
  // scope(failure)
} finally {
  // scope(exit)
}
January 30, 2013
On Wednesday, January 30, 2013 10:05:21 rumbu wrote:
> On Wednesday, 30 January 2013 at 08:44:52 UTC, Jonathan M Davis
> 
> wrote:
> > 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.
> > 
> > - Jonathan M Davis
> 
> Exceptions are not rethrown, finally block is executed *after* throwing/catching the exception. I don't know the details of the scope(*) implementations, but I doubt that they are rethrowing any exceptions. Exceptions are propagated, not rethrown with a mutated message or field.

You seem to think that rethrowing has something to do with mutation. It doesn't. Finally, scope(failure), and scope(exit) all must catch exceptions, run the code within their blocks, and then rethrow the exception. No mutation of the exception is involved. If they didn't rethrow the exception, then it would stop there and never escape those blocks, and if it weren't caught by them, then those blocks wouldn't be executed at all.

Also I could easily do something like

try
 throw new Exception("hello");
catch(Exception e)
{
 writefln("It says: %s", e.msg);
 throw e;
}

I catch and use the exception and then rethrow it, but I don't mutate it. Yes, you can catch an exception, mutate it, and then rethrow it. But the fact that it's rethrown says nothing about whether it was mutated. It just means that the exception continues to propagate up again after it was caught.

- Jonathan M Davis
January 30, 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
January 30, 2013
Ok, maybe my thoughts are polluted by some C# programming practices, but I learnt that exceptions are never intended for the end user (one of the reasons is that the exception mesages are in most cases displayed in english language). In Windows world, throwing an exception displays a message with a nice two buttons: Close and Debug. This will make the accountant using my software very eager to click on Debug :)

My way to deal now with *unattended* exceptions is to log them for further investigation, but I will never display a raw exception message, considering the fact that my LOB applications are in most cases multilanguage.

« First   ‹ Prev
1 2 3