D - throws?
- Russ Lewis (5/5) Aug 17 2001 Is there a reason not to implement a throws declaration?
- Chris Friesen (11/18) Aug 17 2001 If I write a function that calls another function (etc, etc...), do I ha...
- Russ Lewis (5/17) Aug 17 2001 Yes. Basically, the theory is that you should either handle the excepti...
- Russ Lewis (14/32) Aug 17 2001 Another thought....
- John Carney (14/27) Aug 17 2001 to
- Christophe de Dinechin (28/36) Aug 18 2001 There are two philosophies of error recovery: error recovery as cleanup,...
- Dan Hursh (15/61) Aug 23 2001 What happens if you have to write bullet proof code. (Think a
- Christophe de Dinechin (14/19) Aug 17 2001 Throw declarations in C++ have a subtle problem: the throw declaration
- Russ Lewis (7/19) Aug 18 2001 Actually, I would argue the reverse. In C++, where you don't have throw...
- kaffiene (13/18) Aug 18 2001 I think that a throws declaration is a fantastic idea. The thing is tha...
Is there a reason not to implement a throws declaration? IMHO, this is good because it enforces design decisions and interfaces. It forces the implementer of the function to either handle the exceptions he can generate, or publish to all his callers what he might do.
Aug 17 2001
Russ Lewis wrote:Is there a reason not to implement a throws declaration? IMHO, this is good because it enforces design decisions and interfaces. It forces the implementer of the function to either handle the exceptions he can generate, or publish to all his callers what he might do.If I write a function that calls another function (etc, etc...), do I have to include all of their throw list in my throws declaration? If yes, then it becomes messy. If not, then what is the point of it since I can't tell just by looking at a function what it can potentially throw? Chris -- Chris Friesen | MailStop: 043/33/F10 Nortel Networks | work: (613) 765-0557 3500 Carling Avenue | fax: (613) 765-2986 Nepean, ON K2H 8E9 Canada | email: cfriesen nortelnetworks.com
Aug 17 2001
Chris Friesen wrote:Russ Lewis wrote:Yes. Basically, the theory is that you should either handle the exception (catch it) or alert those who call you that you might throw it. Yes, it gets messy (declaration wise). But I think that without it, things get messy implementation wise, which, IMHO, is far worse.Is there a reason not to implement a throws declaration? IMHO, this is good because it enforces design decisions and interfaces. It forces the implementer of the function to either handle the exceptions he can generate, or publish to all his callers what he might do.If I write a function that calls another function (etc, etc...), do I have to include all of their throw list in my throws declaration? If yes, then it becomes messy. If not, then what is the point of it since I can't tell just by looking at a function what it can potentially throw?
Aug 17 2001
Russ Lewis wrote:Chris Friesen wrote:Another thought.... New exceptions tend to filter up through the call tree. That is, if you choose, late in the game, to throw a totally new type of exception, that exception has serious impacts on the other code. If they consider you a minor function and want to catch all of your errors, then when you add a new exception your are breaking their program. Thus, a small change in your library might suddenly cause total program crashes for what they consider to be minor errors. By forcing declaration, you are specifying the impact that the change will have on all of your users. Anyone who builds a new version of code using yours will get syntax errors because of your declaration change. They must then think about the best way to change it - they either allow the exception to continue to be thrown further up the tree, or they catch it. Either way, they are *forced* to at least consider your error conditions, which I consider a Very Good Thing.Russ Lewis wrote:Yes. Basically, the theory is that you should either handle the exception (catch it) or alert those who call you that you might throw it. Yes, it gets messy (declaration wise). But I think that without it, things get messy implementation wise, which, IMHO, is far worse.Is there a reason not to implement a throws declaration? IMHO, this is good because it enforces design decisions and interfaces. It forces the implementer of the function to either handle the exceptions he can generate, or publish to all his callers what he might do.If I write a function that calls another function (etc, etc...), do I have to include all of their throw list in my throws declaration? If yes, then it becomes messy. If not, then what is the point of it since I can't tell just by looking at a function what it can potentially throw?
Aug 17 2001
"Chris Friesen" <cfriesen nortelnetworks.com> wrote in message news:3B7D59CE.448CFD79 nortelnetworks.com...Russ Lewis wrote:toIs there a reason not to implement a throws declaration? IMHO, this is good because it enforces design decisions and interfaces. It forces the implementer of the function to either handle the exceptions he can generate, or publish to all his callers what he might do.If I write a function that calls another function (etc, etc...), do I haveinclude all of their throw list in my throws declaration? If yes, then it becomes messy. If not, then what is the point of it since I can't telljust bylooking at a function what it can potentially throw? ChrisI totally agree with the original poster on this one. Yes, it does mean that functions must declare the exceptions thrown by functions they call. I disagree that this becomes 'messy'. 'Messy' is when lazy programmers let uncaught exceptions propagate up the call stack resulting in upper-level functions having to deal gracefully with exceptions that would have been better handled closer to the source. When I use a library function I want to know about *all* of the exceptions that it will throw. Rigid exception specification guarantees this. Cheers, John Carney.
Aug 17 2001
John Carney wrote:I totally agree with the original poster on this one. Yes, it does mean that functions must declare the exceptions thrown by functions they call. I disagree that this becomes 'messy'. 'Messy' is when lazy programmers let uncaught exceptions propagate up the call stack resulting in upper-level functions having to deal gracefully with exceptions that would have been better handled closer to the source. When I use a library function I want to know about *all* of the exceptions that it will throw. Rigid exception specification guarantees this.There are two philosophies of error recovery: error recovery as cleanup, and error recovery as repair. Eiffel implements the first one, C++ inconsistently implements the second one. Error recovery as cleanup means that a catch handler does not try to "keep" the exception, but simply to locally cleanup in case of error (close files, release locks, etc). In Eiffel (and LX), by default, exceptions keep propagating, as opposed to C++ where they by default are finished by a catch block. In this philosophy, a component never decides what to do with an error, but leaves it to the component user to decide. Error recovery as repair assumes that the closer to the source you catch an error, the easier it is to fix, and thus tries to prevent an error from propagating. In my opinion, it generally lends to less robust software, because errors tend to be ignored in running software. C++ is inconsistent (as I wrote in another post) in that it implements repair-style in the catch block (an exception doesn't propagate unless you explicitly rethrow), but it offers cleanup-style interfaces (the throw spec says what you throw, not what you catch). Interestingly, there is no way to really bring a throw spec and a catch totally in sync. A catch says "I won't throw that", but there is no (simple) way to say "I will throw all but that" (the complex way being "catch that and rethrow, catch dot-dot-dot and ignore", which is ugly. In short, my recommendation would be to go for an "error recovery as cleanup" model, in which case throw specs are inherently bad (you don't know what kind of errors may occur, you let the caller decide). In the case of "real" code with callbacks, virtual functions, etc, it tends to map to real-life situations better, in my experience. Christophe
Aug 18 2001
What happens if you have to write bullet proof code. (Think a pacemaker.) I need to know ever error a function could throw at me so I can make sure to deal with it gracefully. In you're suggestion you are pretty much saying "I could throw anything at you, include exception classes that are out of you're scope." Writing and maintain throws() clauses is truly a royal pain, but it does allow for a good amount certainty that you are handling every known error condition a function can throw at you, provided that the compiler will actually enforce the clauses. (Does C++ require the compiler to gripe?) Granted it makes template code much more difficult to write if you are forced to specify a throws clause. Now what we need to design is a sure way to tell the programmer all of the unknown errors that are in the program. ;-) Dan Christophe de Dinechin wrote:John Carney wrote:I totally agree with the original poster on this one. Yes, it does mean that functions must declare the exceptions thrown by functions they call. I disagree that this becomes 'messy'. 'Messy' is when lazy programmers let uncaught exceptions propagate up the call stack resulting in upper-level functions having to deal gracefully with exceptions that would have been better handled closer to the source. When I use a library function I want to know about *all* of the exceptions that it will throw. Rigid exception specification guarantees this.There are two philosophies of error recovery: error recovery as cleanup, and error recovery as repair. Eiffel implements the first one, C++ inconsistently implements the second one. Error recovery as cleanup means that a catch handler does not try to "keep" the exception, but simply to locally cleanup in case of error (close files, release locks, etc). In Eiffel (and LX), by default, exceptions keep propagating, as opposed to C++ where they by default are finished by a catch block. In this philosophy, a component never decides what to do with an error, but leaves it to the component user to decide. Error recovery as repair assumes that the closer to the source you catch an error, the easier it is to fix, and thus tries to prevent an error from propagating. In my opinion, it generally lends to less robust software, because errors tend to be ignored in running software. C++ is inconsistent (as I wrote in another post) in that it implements repair-style in the catch block (an exception doesn't propagate unless you explicitly rethrow), but it offers cleanup-style interfaces (the throw spec says what you throw, not what you catch). Interestingly, there is no way to really bring a throw spec and a catch totally in sync. A catch says "I won't throw that", but there is no (simple) way to say "I will throw all but that" (the complex way being "catch that and rethrow, catch dot-dot-dot and ignore", which is ugly. In short, my recommendation would be to go for an "error recovery as cleanup" model, in which case throw specs are inherently bad (you don't know what kind of errors may occur, you let the caller decide). In the case of "real" code with callbacks, virtual functions, etc, it tends to map to real-life situations better, in my experience. Christophe
Aug 23 2001
Throw declarations in C++ have a subtle problem: the throw declaration declares the _opposite_ of what the implementation can easily guarantee. For instance: int foo() throw (A) { try { bar() } catch(B&) { glop() } } what the implementation guarantees is, roughly, that you won't throw B, but there is no throw spec that will let you "say" that. Christophe Russ Lewis wrote:Is there a reason not to implement a throws declaration? IMHO, this is good because it enforces design decisions and interfaces. It forces the implementer of the function to either handle the exceptions he can generate, or publish to all his callers what he might do.
Aug 17 2001
Christophe de Dinechin wrote:Throw declarations in C++ have a subtle problem: the throw declaration declares the _opposite_ of what the implementation can easily guarantee. For instance: int foo() throw (A) { try { bar() } catch(B&) { glop() } } what the implementation guarantees is, roughly, that you won't throw B, but there is no throw spec that will let you "say" that.Actually, I would argue the reverse. In C++, where you don't have throws declarations, that is what it means. But if you *must* declare all possible thrown exceptions for *every* function, then you know (by its declaration) what bar() might throw. You are not saying that foo() throws all exceptions except B...you are saying that foo() throws any exceptions that bar() might throw...except that it catches B.
Aug 18 2001
I think that a throws declaration is a fantastic idea. The thing is that it forces programmers to explicitly handle or explicitly delegate the responsibility of dealing with any given exception that can occur in it. This is a really good thing. C++ ends up with the lame try..catch block in the middle of main to catch everything - which means that any usefull handling (and possibly error recovery) is not done. The throws declaration tends to make people consider exceptions closer to the source - where they can do something usefull about it. This is *A VERY GOOD THING* :-) Peter. "Russ Lewis" <russ deming-os.org> wrote in message news:3B7D3698.1A47A8A8 deming-os.org...Is there a reason not to implement a throws declaration? IMHO, this is good because it enforces design decisions and interfaces. It forces the implementer of the function to either handle the exceptions he can generate, or publish to all his callers what he might do.
Aug 18 2001