www.digitalmars.com         C & C++   DMDScript  

D - The case against a 'throws' statement

reply "Walter" <walter digitalmars.com> writes:
I've been discussing this in email with Bruce Eckel, who managed to express
the ideas in writing much better than I have (I guess that's why Bruce is a
successful professional writer!). Here are his comments on it, reproduced
with his kind permission:

---------------------------------------------------------------------

It's like strong static type checking
vs late weak typing; the former sounds like a really good
idea, but in practice it turns out that as long as type
checking happens, you're OK, and late weak typing allows
faster experiments or something like that.

The way I (now) see exceptions is something like this:

1) The great value of exceptions is the unification of
error reporting: a standard mechanism by which to report
errors, rather than the popourri  of ignorable approaches
that we had in C (and thus, C++, which only adds exceptions
to the mix, and doesn't make it the exclusive approach).
The big advantage Java has over C++ is that exceptions are
the only way to report errors.

2) "Ignorable" in the previous paragraph is the other
issue. The theory is that if the compiler forces the
programmer to either handle the exception or pass it on in
an exception specification, then the programmer's attention
will always be brought back to the possibility of errors
and they will thus properly take care of them. I think the
problem is that this is an untested assumption we're making
as language designers that falls into the field of
psychology. My theory is that when someone is trying to do
something and you are constantly prodding them with
annoyances, they will use the quickest device available to
make those annoyances go away so they can get their thing
done, perhaps assuming they'll go back and take out the
device later. I discovered I had done this in the first
edition of Thinking in Java:

...
} catch (SomeKindOfException e) {}

And then more or less forgot it until the rewrite. How many
people thought this was a good example and followed it?
Martin Fowler began seeing the same kind of code, and
realized people were stubbing out exceptions and then they
were disappearing. The overhead of checked exceptions was
having the opposite effect of what was intended, something
that can happen when you experiment (and I now believe that
checked exceptions were an experiment based on what someone
thought was a good idea, and which I believed was a good
idea until recently).

When I started using Python, all the exceptions appeared,
none were accidentally "disappeared." If you *want* to
catch an exception, you can, but you aren't forced to write
reams of code all the time just to be passing the
exceptions around. They go up to where you want to catch
them, or they go all the way out if you forget (and thus
they remind you) but they don't vanish, which is the worst
of all possible cases. I now believe that checked
exceptions encourage people to make them vanish. Plus they
make much less readable code.

In the end, I think we must realize the experimental nature
of exceptions and look at them carefully before assuming
that everything about exceptions in Java are good. I
believe that having a single mechanism for handling errors
is excellent, and I believe that using a separate channel
(the exception handling mechanism) for moving the
exceptions around is good. But I do remember one of the
early arguments for exception handling in C++ was that it
would allow the programmer to separate the sections of code
where you just wanted to get work done from the sections
where you handled errors, and it seems to me that checked
exceptions do not do this; instead, they tend to intrude (a
lot) into your "normal working code" and thus are a step
backwards. My experience with Python exceptions supports
this, and unless I get turned around on this issue I intend
to put a lot more RuntimeExceptions into my Java code.
Sep 01 2001
next sibling parent reply Dan Hursh <hursh infonet.isl.net> writes:
	Well, I think I'll give my last argument on the topic and let it go.  I
do agree that exception specifications can be a problem when the
compiler is constantly throwing them in you face when you are not ready
to deal with error conditions yet.  On the other hand I'd still like a
mechanism to see if there any exceptions that go uncaught before I send
something out the door.  Let's face it: it is possible to check this at
compile time provided that a 'throws' is allowed.
	If you allow it, but not require it, then becomes like the rest of the
programming by contract facilities provided by D.  To get the behavior
that will allow you to forget it, you have to make the lack of a throws
clause the equivalent of saying you can throw any valid exception type. 
Given that, the compiler will only give you an exception specification
error if you put a throws clause on a function. But by putting the
throws clause on the function you are declaring that you want to deal
with any uncaught exceptions that you didn't say you throw.  In other
words, if it's harassing you, it's because you asked for it.  
	If you make it any more strict, then exception specifications will be
an annoyance.  Anything less, and it will be no more possible to know
you are shipping something that won't throw exceptions in the user's
face than you could be sure the C equivalent would behave in a remotely
robust fashion.  Where I work the users have become intimately familiar
with Java exceptions because the developers went the route of declaring
all mains as being able to throw any exception.  I've found end user
dislike java stack dumps even more than they hate "segment violation"s
and "bus error"s.  Exceptions tend not to mean anything to end users or
admins.  They are great however for developers.
	By having the ability to declare throws clauses, but not requiring
them, those who wish to ignore them at compile time and deal at run time
instead can do so.  Those who wish to control which exceptions if any
will make it to the user will have the tools to do so.
	It would be a courtesy to the developer who likes the handle exceptions
in code if library developers would provide reasonable throws clauses to
API functions.  This still would not require the users of the API to
catch the exceptions, but would advertise the possible exceptions that
can occur within the API and provide the necessary tools to those who
would like to know they've handle everything.  
	Without a throws clause, the only way you can be sure you've caught
everything is to have all the source available (not a bad thing, but not
always possible) and use a lint-like tool to tell you what you've
missed.  Even with the compromise I'm suggesting, it might still be nice
(though probably not necessary) to have a tool that can scan a
compilation unit for functions that don't have an explicit throws
clause.
	In closing, Bruce is right in that if you throw exceptions in the
developers face from square one, they will silently get lost by inducing
bad coding techniques.  However, if D is truly for "Programmers who
routinely use lint or similar code analysis tools to eliminate bugs
before the code is even compiled", "People who compile with maximum
warning levels turned on and who instruct the compiler to treat warnings
as errors" and "Programming managers who are forced to rely on C
programming style guidelines to avoid common C bugs" then I don't see
how D can deliver that with out some form of support for making sure the
no unexpected exceptions can sneak through.

Dan

Walter wrote:
 
 I've been discussing this in email with Bruce Eckel, who managed to express
 the ideas in writing much better than I have (I guess that's why Bruce is a
 successful professional writer!). Here are his comments on it, reproduced
 with his kind permission:
 
 ---------------------------------------------------------------------
 
 It's like strong static type checking
 vs late weak typing; the former sounds like a really good
 idea, but in practice it turns out that as long as type
 checking happens, you're OK, and late weak typing allows
 faster experiments or something like that.
 
 The way I (now) see exceptions is something like this:
 
 1) The great value of exceptions is the unification of
 error reporting: a standard mechanism by which to report
 errors, rather than the popourri  of ignorable approaches
 that we had in C (and thus, C++, which only adds exceptions
 to the mix, and doesn't make it the exclusive approach).
 The big advantage Java has over C++ is that exceptions are
 the only way to report errors.
 
 2) "Ignorable" in the previous paragraph is the other
 issue. The theory is that if the compiler forces the
 programmer to either handle the exception or pass it on in
 an exception specification, then the programmer's attention
 will always be brought back to the possibility of errors
 and they will thus properly take care of them. I think the
 problem is that this is an untested assumption we're making
 as language designers that falls into the field of
 psychology. My theory is that when someone is trying to do
 something and you are constantly prodding them with
 annoyances, they will use the quickest device available to
 make those annoyances go away so they can get their thing
 done, perhaps assuming they'll go back and take out the
 device later. I discovered I had done this in the first
 edition of Thinking in Java:
 
 ...
 } catch (SomeKindOfException e) {}
 
 And then more or less forgot it until the rewrite. How many
 people thought this was a good example and followed it?
 Martin Fowler began seeing the same kind of code, and
 realized people were stubbing out exceptions and then they
 were disappearing. The overhead of checked exceptions was
 having the opposite effect of what was intended, something
 that can happen when you experiment (and I now believe that
 checked exceptions were an experiment based on what someone
 thought was a good idea, and which I believed was a good
 idea until recently).
 
 When I started using Python, all the exceptions appeared,
 none were accidentally "disappeared." If you *want* to
 catch an exception, you can, but you aren't forced to write
 reams of code all the time just to be passing the
 exceptions around. They go up to where you want to catch
 them, or they go all the way out if you forget (and thus
 they remind you) but they don't vanish, which is the worst
 of all possible cases. I now believe that checked
 exceptions encourage people to make them vanish. Plus they
 make much less readable code.
 
 In the end, I think we must realize the experimental nature
 of exceptions and look at them carefully before assuming
 that everything about exceptions in Java are good. I
 believe that having a single mechanism for handling errors
 is excellent, and I believe that using a separate channel
 (the exception handling mechanism) for moving the
 exceptions around is good. But I do remember one of the
 early arguments for exception handling in C++ was that it
 would allow the programmer to separate the sections of code
 where you just wanted to get work done from the sections
 where you handled errors, and it seems to me that checked
 exceptions do not do this; instead, they tend to intrude (a
 lot) into your "normal working code" and thus are a step
 backwards. My experience with Python exceptions supports
 this, and unless I get turned around on this issue I intend
 to put a lot more RuntimeExceptions into my Java code.
Sep 02 2001
parent Dan Hursh <hursh infonet.isl.net> writes:
	Yes, I know I said that would be last post on this topic, but I want to
deal with one ambiguity I'm my argument.  Along with everything below, I
would also say that you would need to allow a function to declare a
throws clause that contains exceptions that are bases classes of one or
more of the exceptions he may actually throw, and a function must be
able to declare that it can throw exceptions that it in fact does not. 
Also, a catch statement must be able to catch derived types if there
isn't an exact match.
	This will allow for an API standard to declare that there are certain
exception that could be thrown and the programmers should be ready to
handle.  If a specific implementation of a standard wants to make more
granular error checking possible by subclassing the exceptions of the
standard API, it would still work for someone programming to the
standard and it would allow someone to leverage the more granular error
handling for a platform if they so choose.
	This will also allow an implementation to write code robust enough that
it will not need to throw one or more of the exceptions declared by the
standard without having an adverse affect on the programmers who code to
the standard.  Coding to a standard should never flag and error or
warning.  Writing a more robust implementation should not flag an error
either.
	I think that's everything.  I may add more amendments to this, but I
hope not.

Dan

Dan Hursh wrote:
 
         Well, I think I'll give my last argument on the topic and let it go.  I
 do agree that exception specifications can be a problem when the
 compiler is constantly throwing them in you face when you are not ready
 to deal with error conditions yet.  On the other hand I'd still like a
 mechanism to see if there any exceptions that go uncaught before I send
 something out the door.  Let's face it: it is possible to check this at
 compile time provided that a 'throws' is allowed.
         If you allow it, but not require it, then becomes like the rest of the
 programming by contract facilities provided by D.  To get the behavior
 that will allow you to forget it, you have to make the lack of a throws
 clause the equivalent of saying you can throw any valid exception type.
 Given that, the compiler will only give you an exception specification
 error if you put a throws clause on a function. But by putting the
 throws clause on the function you are declaring that you want to deal
 with any uncaught exceptions that you didn't say you throw.  In other
 words, if it's harassing you, it's because you asked for it.
         If you make it any more strict, then exception specifications will be
 an annoyance.  Anything less, and it will be no more possible to know
 you are shipping something that won't throw exceptions in the user's
 face than you could be sure the C equivalent would behave in a remotely
 robust fashion.  Where I work the users have become intimately familiar
 with Java exceptions because the developers went the route of declaring
 all mains as being able to throw any exception.  I've found end user
 dislike java stack dumps even more than they hate "segment violation"s
 and "bus error"s.  Exceptions tend not to mean anything to end users or
 admins.  They are great however for developers.
         By having the ability to declare throws clauses, but not requiring
 them, those who wish to ignore them at compile time and deal at run time
 instead can do so.  Those who wish to control which exceptions if any
 will make it to the user will have the tools to do so.
         It would be a courtesy to the developer who likes the handle exceptions
 in code if library developers would provide reasonable throws clauses to
 API functions.  This still would not require the users of the API to
 catch the exceptions, but would advertise the possible exceptions that
 can occur within the API and provide the necessary tools to those who
 would like to know they've handle everything.
         Without a throws clause, the only way you can be sure you've caught
 everything is to have all the source available (not a bad thing, but not
 always possible) and use a lint-like tool to tell you what you've
 missed.  Even with the compromise I'm suggesting, it might still be nice
 (though probably not necessary) to have a tool that can scan a
 compilation unit for functions that don't have an explicit throws
 clause.
         In closing, Bruce is right in that if you throw exceptions in the
 developers face from square one, they will silently get lost by inducing
 bad coding techniques.  However, if D is truly for "Programmers who
 routinely use lint or similar code analysis tools to eliminate bugs
 before the code is even compiled", "People who compile with maximum
 warning levels turned on and who instruct the compiler to treat warnings
 as errors" and "Programming managers who are forced to rely on C
 programming style guidelines to avoid common C bugs" then I don't see
 how D can deliver that with out some form of support for making sure the
 no unexpected exceptions can sneak through.
 
 Dan
 
 Walter wrote:
 I've been discussing this in email with Bruce Eckel, who managed to express
 the ideas in writing much better than I have (I guess that's why Bruce is a
 successful professional writer!). Here are his comments on it, reproduced
 with his kind permission:

 ---------------------------------------------------------------------

 It's like strong static type checking
 vs late weak typing; the former sounds like a really good
 idea, but in practice it turns out that as long as type
 checking happens, you're OK, and late weak typing allows
 faster experiments or something like that.

 The way I (now) see exceptions is something like this:

 1) The great value of exceptions is the unification of
 error reporting: a standard mechanism by which to report
 errors, rather than the popourri  of ignorable approaches
 that we had in C (and thus, C++, which only adds exceptions
 to the mix, and doesn't make it the exclusive approach).
 The big advantage Java has over C++ is that exceptions are
 the only way to report errors.

 2) "Ignorable" in the previous paragraph is the other
 issue. The theory is that if the compiler forces the
 programmer to either handle the exception or pass it on in
 an exception specification, then the programmer's attention
 will always be brought back to the possibility of errors
 and they will thus properly take care of them. I think the
 problem is that this is an untested assumption we're making
 as language designers that falls into the field of
 psychology. My theory is that when someone is trying to do
 something and you are constantly prodding them with
 annoyances, they will use the quickest device available to
 make those annoyances go away so they can get their thing
 done, perhaps assuming they'll go back and take out the
 device later. I discovered I had done this in the first
 edition of Thinking in Java:

 ...
 } catch (SomeKindOfException e) {}

 And then more or less forgot it until the rewrite. How many
 people thought this was a good example and followed it?
 Martin Fowler began seeing the same kind of code, and
 realized people were stubbing out exceptions and then they
 were disappearing. The overhead of checked exceptions was
 having the opposite effect of what was intended, something
 that can happen when you experiment (and I now believe that
 checked exceptions were an experiment based on what someone
 thought was a good idea, and which I believed was a good
 idea until recently).

 When I started using Python, all the exceptions appeared,
 none were accidentally "disappeared." If you *want* to
 catch an exception, you can, but you aren't forced to write
 reams of code all the time just to be passing the
 exceptions around. They go up to where you want to catch
 them, or they go all the way out if you forget (and thus
 they remind you) but they don't vanish, which is the worst
 of all possible cases. I now believe that checked
 exceptions encourage people to make them vanish. Plus they
 make much less readable code.

 In the end, I think we must realize the experimental nature
 of exceptions and look at them carefully before assuming
 that everything about exceptions in Java are good. I
 believe that having a single mechanism for handling errors
 is excellent, and I believe that using a separate channel
 (the exception handling mechanism) for moving the
 exceptions around is good. But I do remember one of the
 early arguments for exception handling in C++ was that it
 would allow the programmer to separate the sections of code
 where you just wanted to get work done from the sections
 where you handled errors, and it seems to me that checked
 exceptions do not do this; instead, they tend to intrude (a
 lot) into your "normal working code" and thus are a step
 backwards. My experience with Python exceptions supports
 this, and unless I get turned around on this issue I intend
 to put a lot more RuntimeExceptions into my Java code.
Sep 02 2001
prev sibling next sibling parent Axel Kittenberger <axel dtone.org> writes:
I don't agree that unchecked exceptions like in C++ are better than in 
checked once in java, yes the java ones tend to let you write ignorance 
code like 'catch Error {}' to ignore everything while you're experimenting. 
But the other side C++ allowing you just silently to bypass exceptions can 
also be even more nasty, if you want to write robust code you'll have to 
constantly check the API specifications in the fear you could miss an 
exception, and when newer API's come out you've to take extremely care that 
no new exceptions causes were added your code doesn't expect. 

It goes down to the old statement, you can write fortran in any language. 
the clean coding style while experimenting would be:

catch Exception {

}

Then at later stage before you're releasing a produce you just have to 
`grep' the whole source code for TODO and fix all occurences. 

It's actually a question of matter of principle, do we want an language 
suited for expermints or do we want one for huge stable projects.

Take in example a language optimized for expermenting and teaching, people 
want to get results quickly, without having to write empty templates. Think 
of the C 'hello world' program, how many lines of it are just workaround 
you first have to tell you're pupils ignore all that it's framework like , 
so a teacher want's a language with results when already writing just one 
line, same goes for the expreminter. However a programmer targeted to 
stable software actually wants a strong frame, he knows already all the 
rudimentary surrondings, and wants them. A single line dropped somewhere 
suddendly doing something for itself is a horror for him. 

People with different diserers will come and have different and converse 
expectations in a language, it's matter of the language to target which 
aspects it wants to cover and which a secondary. Strong or weak exceptions 
are just such a case.

- Axel
Sep 02 2001
prev sibling next sibling parent "kaffiene" <kaffiene xtra.co.nz> writes:
This is a choice between D being a language to create large, stable, correct
codebases or one for quick hacks.
Ultimately that choice is not mine to make, but if D is for hacking, then
I'm sticking with C++.

I can live with operator overloading, I can bare generics, but ignoring
exception specificiation - which is a fantastic tool for creating correct
code -  is just stupid, especially when it doesn't stop you hacking if you
want to.

Peter.
Sep 02 2001
prev sibling next sibling parent reply "kaffiene" <kaffiene xtra.co.nz> writes:
[snip!]

 The theory is that if the compiler forces the
 programmer to either handle the exception or pass it on in
 an exception specification, then the programmer's attention
 will always be brought back to the possibility of errors
 and they will thus properly take care of them. I think the
 problem is that this is an untested assumption we're making
 as language designers that falls into the field of
 psychology.
It is not an untested assumption. It might have been many years ago Java when was introduced (about seven years ago?) but there has been enough testing of the idea since. My practical experience, the experience of people I have worked with and that of others on this newsgroup attests that this idea does work. Peter.
Sep 02 2001
parent reply "John Carney" <john.carney pacific.net.au> writes:
"kaffiene" <kaffiene xtra.co.nz> wrote in message
news:9mt8rs$2u2h$2 digitaldaemon.com...
 [snip!]

 The theory is that if the compiler forces the
 programmer to either handle the exception or pass it on in
 an exception specification, then the programmer's attention
 will always be brought back to the possibility of errors
 and they will thus properly take care of them. I think the
 problem is that this is an untested assumption we're making
 as language designers that falls into the field of
 psychology.
It is not an untested assumption. It might have been many years ago Java when was introduced (about seven years ago?) but there has been enough testing of the idea since. My practical experience, the experience of people I have worked with and that of others on this newsgroup attests
that
 this idea does work.
My own experience agrees with this. I agree that there is a tendency displayed by lazy programmers to use "throws Exception, Error" to avoid actually thinking about what they are doing. For hacks this is perfectly acceptable and not a tremendous burden to anyone. But when it comes to real, live, actual, customers-screaming-down-the-phone production code it quickly becomes clear to even the sloppiest programmer that all they're doing is *deferring* exception handling, not avoiding it. When I was working with Java, a colleague of mine at the time - a mathematician in programmer's clothing and the second laziest programmer I have ever worked with - was very firmly in the the "throws Exception" camp. Over time he moved towards my way of thinking (handle early) because he found that his style of coding (handle late) requires much hairier handling code further up the call stack if you want your software to be presentable to a paying customer... Or even to a non-paying customer ;-) It the risk of sounding evangelical, I urge anyone who resists the idea of strict exception specification to actually try it. You'll find that your code /feels/ much more robust. This alleviates much stress from the working programmer and is well worth the small amount of extra effort. All of that being said, I would accept Russ' compiler switch compromise - albeit grudgingly. Though I would like to have some way of knowing whether 3rd party D binaries are "compliant". I don't want to ship code that could explode in a customer's face. Or rather, if it is going to explode, I'd like it to be sure that it's *my* fault - that is, in code that I have some control over. Regards, John "ashamed to be an Australian at the moment" Carney.
Sep 02 2001
parent reply "Kent Sandvik" <sandvik excitehome.net> writes:
Long time ago I wrote code that tried to go around error handlings by
'recovery' and all kinds of code to somehow halt along after problems.
Usually such code ended up becoming far too complex, resulting in even more
unknown states. The best is to let the application bomb as quickly as
possible, and force the programmer to fix the problem on the spot. Hence
delegating the error handling to another level and even ignoring is in my
current view not a practical solution. In embedded systems programming it's
far better to have the program crash and then you are indeed forced to fix
the problem before shipping it. --Kent
Sep 06 2001
parent "Walter" <walter digitalmars.com> writes:
Kent Sandvik wrote in message <9n8n4u$ai5$1 digitaldaemon.com>...
Long time ago I wrote code that tried to go around error handlings by
'recovery' and all kinds of code to somehow halt along after problems.
Usually such code ended up becoming far too complex, resulting in even more
unknown states. The best is to let the application bomb as quickly as
possible, and force the programmer to fix the problem on the spot. Hence
delegating the error handling to another level and even ignoring is in my
current view not a practical solution. In embedded systems programming it's
far better to have the program crash and then you are indeed forced to fix
the problem before shipping it. --Kent
I've had a long standing disagreement with some people who think that programs should attempt to recover from their own bugs. My feeling is that if a fault is detected, fail immediatedly. Trying to recover from them is like duct taping over rust.
Sep 06 2001
prev sibling parent reply Russ Lewis <russ deming-os.org> writes:
It's an intriguing and disturbing argument.  I think I would say that if the
language spec leads to (lots of) the kind of hacks Bruce describes, then I
would be against exception specification.  But is there another way?

Looked at Dan's suggestion of not requiring throws clauses.  The problem with
that is if you call a library function that does declare its exceptions, there
is absolutely no way to declare one in your code (as you cannot guarantee you
have caught all they throw).  That would, of course, encourage writers of
library APIs to declare their exceptions...but you get one idiot, and all of a
sudden a lot of user code can't use declarations anymore.

The alternative is to use C++ -style catch(...) clauses, which, IMHO, are often
worse than not catchnig things at all.

My thought is that maybe throws checking should be a compiler switch.  Let the
default setting of the compiler be to check exceptions and to interpret a lack
of a throws clause as an explicit "throws nothing" clause.  But allow for a
compiler switch that causes lack of a throws clause to mean "could throw
anything".

Then programmers could use loose throwing for their quick hacks, and tight
checking for their important code.
Sep 02 2001
next sibling parent Russ Lewis <russ deming-os.org> writes:
Russ Lewis wrote:

 My thought is that maybe throws checking should be a compiler switch.  Let the
 default setting of the compiler be to check exceptions and to interpret a lack
 of a throws clause as an explicit "throws nothing" clause.  But allow for a
 compiler switch that causes lack of a throws clause to mean "could throw
 anything".
Maybe with the "hack switch" on, it would still check things, but they would only be posted as warnings...
Sep 02 2001
prev sibling parent reply Dan Hursh <hursh infonet.isl.net> writes:
Russ Lewis wrote:
 Looked at Dan's suggestion of not requiring throws clauses.  The problem with
 that is if you call a library function that does declare its exceptions, there
 is absolutely no way to declare one in your code (as you cannot guarantee you
 have caught all they throw).  That would, of course, encourage writers of
 library APIs to declare their exceptions...but you get one idiot, and all of a
 sudden a lot of user code can't use declarations anymore.
You can get idiots in any language. If you find a language feature that could fix that, I would truly be impressed. I'll assume you meant to say "...if you call a library function that DOESN'T declare its exceptions..", or else you are misrepresenting my argument. First, this hypothetical API designer is an idiot and the API should be considered flawed. Some programs can afford to be quick and dirty. No public API should. Even if a lack of a throws clause implied no exception thrown, you will still get idiots who will declare they throw the exception base class. The compiler cannot fix that. You could still catch the exception in my example given that D was supposed to have a single base class that all exceptions had to be derived from. (Or am I mistaken?) Where ever you would put "catch(...)" in C++ you would put "catch(exception e)" or whatever the base class is in D. I still say you should hound the API developer, or use a different API by someone a little less idiotic. Dan
Sep 02 2001
next sibling parent reply Axel Kittenberger <axel dtone.org> writes:
Even if a lack of a throws clause implied no exception thrown,
 you will still get idiots who will declare they throw the exception base
 class.  The compiler cannot fix that.
No it can, writing 'throws' in the decleration is not alone making the compiler happy. You must actually throw it somewhere, or call a function in your body that throws this exception, or else you've at least a warning if not an error. So if you declare the exceptoin base class in the throws clause you must also throw it somewhere.
 I still say you should hound the API developer, or use a different API by 
 someone a little less idiotic.
I used to have C++ projects that suddendly crashed by the costumer because some code part threw an exception that was not catched. Whats more important quick hacks or stable projects?
Sep 02 2001
next sibling parent reply "Walter" <walter digitalmars.com> writes:
Axel Kittenberger wrote in message <9mv24r$r8k$1 digitaldaemon.com>...
I used to have C++ projects that suddendly crashed by the costumer because
some code part threw an exception that was not catched. Whats more
important quick hacks or stable projects?
It's common for C and C++ code to crash because the code failed to test for the error return from a function. Even longtime professional programmers make this error. By having errors signalled by throwing an exception, they cannot be ignored by default. If there is no code to catch the exception, the startup code installs an exception handler to print out the error message for the exception (all exceptions are defined to have an explanatory error message associated with them). For batch programs, this in itself will be adequate for most uses. For non-batch programs, at least you get a reasonable error message and graceful exit when the program fails, instead of the C approach of a random crash.
Sep 02 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
 It's common for C and C++ code to crash because the code failed to test
 for the error return from a function. Even longtime professional
 programmers make this error. 
Okay now how many people do check on the return value for fclose() :o)
 By having errors signalled by throwing an
 exception, they cannot be ignored by default. If there is no code to catch
 the exception, the startup code installs an exception handler to print out
 the error message for the exception (all exceptions are defined to have an
 explanatory error message associated with them).
Well I used MSVC in the past, an the application just halted with an exit code. Not message, nothing. But mabye I just did something wrong. And actually this is the runtime vs. compiletime approval. Why should a error have to be discovered at runtime if it could be tracked at compiletime already? Like uncatched excpetions. And honestly through all economic non high-security software projects we must admit that there are really some code parts that go out untested, like some cases to reaction of certain malfunctions. No 'normal' software project can effort to go through a profiler supported branch decision test analyses high security software goes through. Just take a worst case exception, "NuclearCoreMeltdownException", okay one code piece forgot to catch it and to start emergency shutdown sequence. The compiler doesn't complain because some guys want to do quick hacks without having to write syntatic catch-sugar. Now the application terminates with a nice NuclearCoreMeltdownException raised in code module XYZ line 245 is uncatched, application terminated with exit code -1. But now who starts the emergency sequence? I know this example is very hyperbolical, since software used in this fields is tested through other means as we're used to. But I think you can image what I think about, take in example fclose(), no body with local filesystems thinks about closing a file could fail, but with network filesystems it can, and a really good program should at least inform the user that his file is not saved, and possibly lost. Okay fclose is a bad example as 99% of people ignore it's return value, myself included :( But I think you can imagine what I ment with comiletime vs. runtime security. - Axel
Sep 03 2001
parent reply Dan Hursh <hursh infonet.isl.net> writes:
Axel Kittenberger wrote:
 
 It's common for C and C++ code to crash because the code failed to test
 for the error return from a function. Even longtime professional
 programmers make this error.
Okay now how many people do check on the return value for fclose() :o)
I believe I've mention in one of the other "exceptions" threads that I was anal. This is what I mean. I will admit, I don't check it every time, I do check it often, even in perl. Go ahead. Laugh!
 By having errors signalled by throwing an
 exception, they cannot be ignored by default. If there is no code to catch
 the exception, the startup code installs an exception handler to print out
 the error message for the exception (all exceptions are defined to have an
 explanatory error message associated with them).
Well I used MSVC in the past, an the application just halted with an exit code. Not message, nothing. But mabye I just did something wrong.
Probably not. I've had the same thing in UNIX. I think my C++ implementation just called abort on uncaught exceptions. Java dumps huge stack traces that fall somewhere between rude and terrifying to the unwashed masses. It sounds like D is going to require behavior of the runtime that is likely to be a little less anti-social.
 And actually this is the runtime vs. compiletime approval. Why should a
 error have to be discovered at runtime if it could be tracked at
 compiletime already? Like uncatched excpetions. 
The issue is that uncaught exceptions are not necessarily an error. It sounds like D will allow the exception to be the means to pass on an error message and die which is reasonable behavior in a large number of cases. (If only you could give it the exit status too. hint hint)
 And honestly through all
 economic non high-security software projects we must admit that there are
 really some code parts that go out untested, like some cases to reaction of
 certain malfunctions. No 'normal' software project can effort to go through
 a profiler supported branch decision test analyses high security software
 goes through. Just take a worst case exception,
 "NuclearCoreMeltdownException", okay one code piece forgot to catch it and
 to start emergency shutdown sequence. The compiler doesn't complain because
 some guys want to do quick hacks without having to write syntatic
 catch-sugar. Now the application terminates with a nice
 NuclearCoreMeltdownException raised in code module XYZ line 245 is
 uncatched, application terminated with exit code -1. But now who starts the
 emergency sequence?
OK. So this isn't one of those cases where returning a message and exit status would be sufficient.
 I know this example is very hyperbolical, since software used in this
 fields is tested through other means as we're used to.
True, but I like the idea of a nuclear meltdown being handled automatically by an exception. It just sounds so routine.
 But I think you can
 image what I think about, take in example fclose(), no body with
 local filesystems thinks about closing a file could fail, but with network
 filesystems it can, and a really good program should at least inform the
 user that his file is not saved, and possibly lost. Okay fclose is a bad
 example as 99% of people ignore it's return value, myself included :(
 
 But I think you can imagine what I ment with comiletime vs. runtime
 security.
Yes, there should be a way to find out at compiler time if there are any uncaught exceptions. There are project that would definitely use that. But there a lot of genuinely useful programming tasks for with overly strict exception rules would be a burden that bares no benefits. Not everyone is building a Sherman tank. (Or a Nuke Plant for that matter.) There must be room for tradeoffs. Dan PS: I still like the idea of a nuclear meltdown being handled by a mere exception. I can't imagine what it would be like to write the code that monitor the situation and just determine "hmm... The core is melting. I guess I'll throw an exception. My work is done." :-)
Sep 03 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
 Okay now how many people do check on the return value for fclose()
 I believe I've mention in one of the other "exceptions" threads that I
 was anal.  This is what I mean.  I will admit, I don't check it every
 Go ahead. Laugh!
Absolutly not, Most times I either forget about it, or are to lazy, or don't know what it should do else. Well small stack traces are nice to have either way. For costumer support, if somebody calls you with the messge "your application just segfaulted", no matter what else he babbles, having a stack trace gives you a very defined idea where to problem arised. Especially on GUI application it's a nasty event if the application just vanishes from the user, at least a message box and some explanation what happened should appear. Okay windows learned this and now even KDE has nice crash handles, and if you've a debug build of KDE it does print out a nice stack trace, you can copy/paste for bug reports. But okay I think it's task of the application to handle segfault signals, and to investigate it's own status on this signal.
 Not everyone is building a Sherman tank.  (Or a Nuke Plant for that
 matter.)  There must be room for tradeoffs.
Yes I said it's overstated. On PC's it are more trivial things like FileIoException - write access not allowed. Something you can miss when coding an application, not thinking about your application could be runned in places where you don't have write access to your direction. Or the target system is malfunctioning because the current user doesn't even have access to /tmp, or somebody deleted the /tmp or whatever.
 PS:  I still like the idea of a nuclear meltdown being handled by a mere
 exception.  I can't imagine what it would be like to write the code that
 monitor the situation and just determine "hmm... The core is melting.  I
 guess I'll throw an exception.  My work is done."  :-)
Okay, okay it was a bad example, as normally there is even an own circuit respsonsible just for this. But staying in practical/physical world you've quite often conditions an producure says: man, under this situation I can never continue my task, and it -must- be handled proparly by a single instance. Just imagine every possible code loop would have to handle itself criticial errors, diffrerent programmers result in different solutions. So the answer to how does this system react on this or this situation? would have to be answered, well that depends on which state the software currently is. Hmmm okay from my phantasy I've imagine a new hopefully better example. Take the airplane autopilot, in case of an engine starting to catch fire, the autopilot will no longer care to reach the target city or to fly in for maximum comfortability for the passanger. It raises an 'EngineCatchedFireException' :o) and code pops back until a main loop, which catches it, and handles the exception by giving control to a complete other code part, since flying with just one wing is very different than with two :o) (but from what I heared it's still possible). Again if the application exits with a callback stack.... okay enough phantasy :o) - Axel
Sep 03 2001
parent Dan Hursh <hursh infonet.isl.net> writes:
Axel Kittenberger wrote:
 PS:  I still like the idea of a nuclear meltdown being handled by a mere
 exception.  I can't imagine what it would be like to write the code that
 monitor the situation and just determine "hmm... The core is melting.  I
 guess I'll throw an exception.  My work is done."  :-)
Okay, okay it was a bad example, as normally there is even an own circuit respsonsible just for this. But staying in practical/physical world you've quite often conditions an producure says: man, under this situation I can never continue my task, and it -must- be handled proparly by a single instance. Just imagine every possible code loop would have to handle itself criticial errors, diffrerent programmers result in different solutions. So the answer to how does this system react on this or this situation? would have to be answered, well that depends on which state the software currently is. Hmmm okay from my phantasy I've imagine a new hopefully better example. Take the airplane autopilot, in case of an engine starting to catch fire, the autopilot will no longer care to reach the target city or to fly in for maximum comfortability for the passanger. It raises an 'EngineCatchedFireException' :o) and code pops back until a main loop, which catches it, and handles the exception by giving control to a complete other code part, since flying with just one wing is very different than with two :o) (but from what I heared it's still possible). Again if the application exits with a callback stack.... okay enough phantasy :o)
Sorry. For some reason the whole scenario about the nuke plant came to me as a twisted Monty Python skit. It was a valid example of a critical application, exaggerated but that just helps to punctuate the idea. I just got this weird idea about it into my head and it gave me a good chuckle. I'm just warped. Dan
Sep 04 2001
prev sibling parent reply Dan Hursh <hursh infonet.isl.net> writes:
Axel Kittenberger wrote:
 
 Even if a lack of a throws clause implied no exception thrown,
 you will still get idiots who will declare they throw the exception base
 class.  The compiler cannot fix that.
No it can, writing 'throws' in the decleration is not alone making the compiler happy. You must actually throw it somewhere, or call a function in your body that throws this exception, or else you've at least a warning if not an error. So if you declare the exceptoin base class in the throws clause you must also throw it somewhere.
This is were we differ then. I do believe a function should be able to claim it throws an exception that it in fact does not. This is why I replied to my first message on this thread. The basic reason is that a standard API may allow for a given type of exception, when not all implementation of that standard will throw that exception. Either the API user has to use version statements in his throws clause (if that is even possible) or he will not be able to code to the standard and still use the more robust implementations of that standard. Requiring a function to actually throw every exception in it throws clause will be the source of many problems even for the most anal of developers. An unused exception is not like an unused variable in a function. Requiring a function to throw every exception in it throws clause is more like requiring a function with a return type of int to return every value from int.min() to int.max() at some point in its code.
 I still say you should hound the API developer, or use a different API by
 someone a little less idiotic.
I used to have C++ projects that suddendly crashed by the costumer because some code part threw an exception that was not catched. Whats more important quick hacks or stable projects?
My experience tells me both. My proposal would in fact satisfy the requirements of both. It would require allowing exceptions in the throws clause that aren't in fact thrown, it would require that a function be allowed to throw an exception if it is not in the throws clause as long as it is derived from one of the types in the throws clause. This already assumes that there is a shared base class for all exceptions. The spec calls it Error. class e1 : Error {} // Error is the exception base class class e2 : e1 {} class e3 : e1 {} // I can throw nothing void f() throws(); // I could throw anything including, but not limited to e1, e2 & e3 void g() throws(Error); // I could throw anything including, but not limited to e1, e2 & e3 void h(); // I could throw any subclass of e1 including, but not limited to e2 & e3 // I cannot throw Error or anything else not derived from e1 void i() throws(e1); // I could throw any subclass of e2 including, but not limited to e3 // I cannot throw e1 or Error or anything else not derived from e2 void j() throws(e2); // I could throw any subclass of e2 or e3 // I cannot throw e1 or Error or anything else not derived from e2 or e3 void k() throws(e2, e3); try{ f(); g(); h(); i(); j(); k(); }catch(Error){ // ALL exceptions WILL be caught here, // without exception :-) } All of the exceptions thrown by these functions could be caught by a 'catch(Error)' because all exceptions MUST be derived from Error or one of its descendants. Nothing can slip through. It is bullet proof and air tight. No exceptions. The lazy can be lazy. The non lazy can be non lazy, even when using code written by a lazy developer. The non lazy would probably have an easier time if he used code exclusively from other non lazy programmers. Even then he has to deal with the idiots and he has the tools he needs to do so. Dan
Sep 02 2001
next sibling parent reply Axel Kittenberger <axel dtone.org> writes:
 This is were we differ then.  I do believe a function should be able to
 claim it throws an exception that it in fact does not.  This is why I
 replied to my first message on this thread.  The basic reason is that a
 standard API may allow for a given type of exception, when not all
 implementation of that standard will throw that exception.  Either the
 API user has to use version statements in his throws clause (if that is
 even possible) or he will not be able to code to the standard and still
 use the more robust implementations of that standard.
 Requiring a function to actually throw every exception in it throws
 clause will be the source of many problems even for the most anal of
 developers.  An unused exception is not like an unused variable in a
 function.  Requiring a function to throw every exception in it throws
 clause is more like requiring a function with a return type of int to
 return every value from int.min() to int.max() at some point in its
 code.
True, I thought futher over that, in the matter of polymorphism requiring to throw all throws declared things is a horror.
 My experience tells me both.  My proposal would in fact satisfy the
 requirements of both.  It would require allowing exceptions in the
 throws clause that aren't in fact thrown, it would require that a
 function be allowed to throw an exception if it is not in the throws
 clause as long as it is derived from one of the types in the throws
 clause.  
I don't think this will benefit in the matter of readability. Why should one want to throw a child of the throws clause? Catching through inheritence by parents, okay. But throwing childs? This already assumes that there is a shared base class for all
 The lazy can be lazy.  The non lazy can be non lazy, even when using
 code written by a lazy developer.  
Thats another main objective we might differ. Does the language encorage projects written by a single author, or for multiple authors. This statment goes against projects where more than one code is envolved, and this is exactly the place most modern language approach at. Look who uses C++ succesfull in practice, most of these who do it but an additial coding rules upen C++ and force themself to a defined subset of the language, project teams where every member is allowed to use all features of C++ like he finds them are usually not so successfull, because C++ is bloated of features. Now I darkly remember what was the mission statment of D? " Programming managers who are forced to rely on C programming style guidelines to avoid common C bugs." So this goes against the lazy and non lazy approach :o) - Axel
Sep 03 2001
parent reply Dan Hursh <hursh infonet.isl.net> writes:
Axel Kittenberger wrote:
 My experience tells me both.  My proposal would in fact satisfy the
 requirements of both.  It would require allowing exceptions in the
 throws clause that aren't in fact thrown, it would require that a
 function be allowed to throw an exception if it is not in the throws
 clause as long as it is derived from one of the types in the throws
 clause.
I don't think this will benefit in the matter of readability. Why should one want to throw a child of the throws clause? Catching through inheritence by parents, okay. But throwing childs? This already assumes that there is a shared base class for all
This is a concession to the fact that some venders will implement things in a way that will allow they to return more granular error information than standard designers had anticipated or felt they could expect from all vendors. If a standard API stated that a given method X() could throw NetworkException in the case of network problems, a given vendor could subclass that exception to provide different forms of network exceptions to differentiate between cases that their platform can correct and those that can't be helped. This could allow people who are willing to tie themselves to the platform increased granularity of error detection and possibly allow them to react better to certain exceptional situations. Developers who code to the standard would not be affected by this increased granularity. Developers who do use the extra exceptions would have to find out about them somewhere other than the throws clause, which is sub optimal for them. I guess there would be other ways around this one too, but it feels most natural to me. I was just assuming that the exceptions in the throws clause might make their way into a function signature somehow, and I would not want someone who writes to a standard to get bitten because some one else was an over achiever in error detection.
 The lazy can be lazy.  The non lazy can be non lazy, even when using
 code written by a lazy developer.
Thats another main objective we might differ. Does the language encorage projects written by a single author, or for multiple authors. This statment goes against projects where more than one code is envolved, and this is exactly the place most modern language approach at. Look who uses C++ succesfull in practice, most of these who do it but an additial coding rules upen C++ and force themself to a defined subset of the language, project teams where every member is allowed to use all features of C++ like he finds them are usually not so successfull, because C++ is bloated of features. Now I darkly remember what was the mission statment of D? " Programming managers who are forced to rely on C programming style guidelines to avoid common C bugs." So this goes against the lazy and non lazy approach :o)
This is the biggest difference I guess. It is good to plan things so good practices can be handled and enforced by the language. Large projects will benefit from it. On the other hand, most of my experience has shown me that the quick fix tools and simple utilities are just as important as huge billion line programs. I would also guess that a number of scientists writing simulations would not be as interested in these strict features. They would want to be aware of errors, but they would be just as happy to let the simulation die, so they can correct the error. It's the difference between shipping a product and doing in house, batch style work. Not every task requires rock solid stability and it is not practical to impose such constrains on everyone. It is necessary that to provide the tools that will allow people to easily get stability if they want it, but there needs to be room for the tradeoffs that have to happen in the real world. We could say that D is only for "Programming managers who are forced to rely on C programming style guidelines to avoid common C bugs" but I suspect that such a stance would make D just another language that is only used by a few large companies use for a short period of time. I guess the thing I like about have the exception handling that I've been whining about is that you can take a function by a lazy developer, add a throws clause, and the compiler will tell you (through error messages) what exceptions you need to handle or pass on. So it is easy to start working on a chuck of code without paying much attention to error handling, and when you are ready to clamp down, it would be pretty easy. Dan
Sep 03 2001
parent reply Axel Kittenberger <axel dtone.org> writes:
 This is the biggest difference I guess.  It is good to plan things so
 good practices can be handled and enforced by the language.  Large
 projects will benefit from it.  On the other hand, most of my experience
 has shown me that the quick fix tools and simple utilities are just as
 important as huge billion line programs.  I would also guess that a
 number of scientists writing simulations would not be as interested in
 these strict features. 
That's the point, and thats a principle decision languages have to do. From what I read from the walters specs I had the impression he targeted his language to be thought for use by million line programs not as a ideal quick hack tool. For quick hacks a lot of scrip languages are already pretty ideal, or? - Axel
Sep 03 2001
parent reply Dan Hursh <hursh infonet.isl.net> writes:
Axel Kittenberger wrote:
 
 This is the biggest difference I guess.  It is good to plan things so
 good practices can be handled and enforced by the language.  Large
 projects will benefit from it.  On the other hand, most of my experience
 has shown me that the quick fix tools and simple utilities are just as
 important as huge billion line programs.  I would also guess that a
 number of scientists writing simulations would not be as interested in
 these strict features.
That's the point, and thats a principle decision languages have to do. From what I read from the walters specs I had the impression he targeted his language to be thought for use by million line programs not as a ideal quick hack tool. For quick hacks a lot of scrip languages are already pretty ideal, or? - Axel
True. I was just going off some of his comments I've seen on this group. I'm guessing he's after as much middle ground in this area as possible without making a complete sacrifice in error handling. Even with the compromise, D would be worlds better than C. I'm still of the opinion that it would be no worse than java functionally speaking. In any case, I've gone on longer about this than I ever intended to. Dan
Sep 03 2001
parent Axel Kittenberger <axel dtone.org> writes:
 I've gone on longer about this than I ever intended to.
Sorry if I was importunate/stolid :/ - Axel
Sep 03 2001
prev sibling parent "Walter" <walter digitalmars.com> writes:
I think your suggestion and reasoning is pretty good. -Walter

Dan Hursh wrote in message <3B9326BB.44475274 infonet.isl.net>...
Axel Kittenberger wrote:
 Even if a lack of a throws clause implied no exception thrown,
 you will still get idiots who will declare they throw the exception
base
 class.  The compiler cannot fix that.
No it can, writing 'throws' in the decleration is not alone making the compiler happy. You must actually throw it somewhere, or call a function
in
 your body that throws this exception, or else you've at least a warning
if
 not an error. So if you declare the exceptoin base class in the throws
 clause you must also throw it somewhere.
This is were we differ then. I do believe a function should be able to claim it throws an exception that it in fact does not. This is why I replied to my first message on this thread. The basic reason is that a standard API may allow for a given type of exception, when not all implementation of that standard will throw that exception. Either the API user has to use version statements in his throws clause (if that is even possible) or he will not be able to code to the standard and still use the more robust implementations of that standard. Requiring a function to actually throw every exception in it throws clause will be the source of many problems even for the most anal of developers. An unused exception is not like an unused variable in a function. Requiring a function to throw every exception in it throws clause is more like requiring a function with a return type of int to return every value from int.min() to int.max() at some point in its code.
 I still say you should hound the API developer, or use a different API
by
 someone a little less idiotic.
I used to have C++ projects that suddendly crashed by the costumer
because
 some code part threw an exception that was not catched. Whats more
 important quick hacks or stable projects?
My experience tells me both. My proposal would in fact satisfy the requirements of both. It would require allowing exceptions in the throws clause that aren't in fact thrown, it would require that a function be allowed to throw an exception if it is not in the throws clause as long as it is derived from one of the types in the throws clause. This already assumes that there is a shared base class for all exceptions. The spec calls it Error. class e1 : Error {} // Error is the exception base class class e2 : e1 {} class e3 : e1 {} // I can throw nothing void f() throws(); // I could throw anything including, but not limited to e1, e2 & e3 void g() throws(Error); // I could throw anything including, but not limited to e1, e2 & e3 void h(); // I could throw any subclass of e1 including, but not limited to e2 & e3 // I cannot throw Error or anything else not derived from e1 void i() throws(e1); // I could throw any subclass of e2 including, but not limited to e3 // I cannot throw e1 or Error or anything else not derived from e2 void j() throws(e2); // I could throw any subclass of e2 or e3 // I cannot throw e1 or Error or anything else not derived from e2 or e3 void k() throws(e2, e3); try{ f(); g(); h(); i(); j(); k(); }catch(Error){ // ALL exceptions WILL be caught here, // without exception :-) } All of the exceptions thrown by these functions could be caught by a 'catch(Error)' because all exceptions MUST be derived from Error or one of its descendants. Nothing can slip through. It is bullet proof and air tight. No exceptions. The lazy can be lazy. The non lazy can be non lazy, even when using code written by a lazy developer. The non lazy would probably have an easier time if he used code exclusively from other non lazy programmers. Even then he has to deal with the idiots and he has the tools he needs to do so. Dan
Sep 03 2001
prev sibling parent Russ Lewis <russ deming-os.org> writes:
Dan Hursh wrote:

 You can get idiots in any language.
"If you invent an idiot-proof computer...they will invent a better idiot!"
 If you find a language feature
 that could fix that, I would truly be impressed.  I'll assume you meant
 to say "...if you call a library function that DOESN'T declare its
 exceptions..", or else you are misrepresenting my argument.  First, this
 hypothetical API designer is an idiot and the API should be considered
 flawed.  Some programs can afford to be quick and dirty.  No public API
 should.
Absolutely. I didn't mean to imply that having non-strict throws clauses would *cause* bad library APIs. What I was intending to say was that programmers are fundamentally lazy, and that the use of the language will tend to gravitate towards the quickest & dirtiest way. If the default setting of the language is to have strict exceptions, I would guess that more programs (and a higher percentage of library APIs) will use it so as to "not have to bother with the compiler switches." Ofc, you will always have idiots and anal people on both ends in any language. Having this be the default puts additional pressure on designers of library APIs to write "good" APIs. If they want their API to be interoperable with my program, and the default of my compiler is to require strict exceptions, they are more likely to declare those strict exceptions "just to make it work."
Sep 04 2001