Jump to page: 1 2 3
Thread overview
The case against a 'throws' statement
Sep 02, 2001
Walter
Sep 02, 2001
Dan Hursh
Sep 02, 2001
Dan Hursh
Sep 02, 2001
Axel Kittenberger
Sep 02, 2001
kaffiene
Sep 02, 2001
kaffiene
Sep 03, 2001
John Carney
Sep 06, 2001
Kent Sandvik
Sep 07, 2001
Walter
Sep 02, 2001
Russ Lewis
Sep 02, 2001
Russ Lewis
Sep 02, 2001
Dan Hursh
Sep 03, 2001
Axel Kittenberger
Sep 03, 2001
Walter
Sep 03, 2001
Axel Kittenberger
Sep 04, 2001
Dan Hursh
Sep 04, 2001
Axel Kittenberger
Sep 05, 2001
Dan Hursh
Sep 03, 2001
Dan Hursh
Sep 03, 2001
Axel Kittenberger
Sep 04, 2001
Dan Hursh
Sep 04, 2001
Axel Kittenberger
Sep 04, 2001
Dan Hursh
Sep 04, 2001
Axel Kittenberger
Sep 03, 2001
Walter
Sep 04, 2001
Russ Lewis
September 02, 2001
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.



September 02, 2001
	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.
September 02, 2001
	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.
September 02, 2001
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 {
  # TODO
}

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

September 02, 2001
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.



September 02, 2001
[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.


September 02, 2001
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.

September 02, 2001
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...

September 02, 2001
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
September 03, 2001
"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.



« First   ‹ Prev
1 2 3