Jump to page: 1 2 3
Thread overview
Exceptions
Jan 26, 2006
nick
Jan 26, 2006
Sean Kelly
Jan 26, 2006
nick
Jan 26, 2006
xs0
Jan 26, 2006
Mike Parker
Jan 26, 2006
xs0
Jan 26, 2006
S. Chancellor
Jan 26, 2006
S. Chancellor
Jan 26, 2006
John Demme
Jan 26, 2006
nick
Jan 26, 2006
kris
Jan 26, 2006
nick
Jan 26, 2006
Kris
Jan 26, 2006
nick.atamas
Jan 26, 2006
Sean Kelly
Jan 26, 2006
nick.atamas
Jan 26, 2006
Sean Kelly
Jan 27, 2006
nick
Jan 27, 2006
Kris
Jan 27, 2006
nick
Jan 27, 2006
nick
Jan 27, 2006
David Medlock
Jan 27, 2006
nick
Jan 29, 2006
nick
Jan 29, 2006
Bruno Medeiros
Jan 29, 2006
Walter Bright
January 26, 2006
Keeping it brief:

Shouldn't exception catching be mandatory as in Java?

If not, then shouldn't functions/methods still have a throws keyword so coders know what to catch?

Sorry if this has already been discussed.

January 26, 2006
nick wrote:
> Keeping it brief:
> 
> Shouldn't exception catching be mandatory as in Java?

Why?  Exceptions should be allowed to pass as far up the call stack as the programmer wishes them to.

> If not, then shouldn't functions/methods still have a throws keyword so coders know what to catch?

Coming from a C++ background, I have a personal bias against throw specs, and I think some of the same reasons can be applied to D.  Throw specs are really only useful if every function provides one, and D's near seamless integration with C library code makes this impossible. For example, say I do something crazy like this:

void fn() {
    throw new Exception("Surprise!");
}

extern (C) void callFunction( void(*)() );

callFunction( &fn );

The C function cannot have a throw spec and yet I've just created a situation where an exception will be thrown from it.  And contrived situations aside, hardware errors can also cause exceptions to be thrown, which can obviously occur in functions with no throw spec. Also, from an implementation perspective, I think a throw spec might have to be mangled into the function name, and this isn't possible for functions with C linkage.

In C++, about the only use for throw specs is to provide the strong exception guarantee (that the function will not throw under any circumstances), and even this finds little use outside of dtor calls. And since throwing an exception out of a dtor does not risk a call to terminate (because the exception will override the one that is already in flight), there is no need for such a guarantee in D.


Sean
January 26, 2006
On 2006-01-26 00:06:24 -0800, Sean Kelly <sean@f4.ca> said:

> nick wrote:
>> Keeping it brief:
>> 
>> Shouldn't exception catching be mandatory as in Java?
> 
> Why?  Exceptions should be allowed to pass as far up the call stack as the programmer wishes them to.
Agreed. There is no contradiction:

void A() throws Exception {throw Exception("hi");}
void B(){A();} // This doesn't work
void B() throws Excpetion {A();} // This works

So the exception can pass up the call stack, but now the programmer is explicitly aware of what is going on.

> 
>> If not, then shouldn't functions/methods still have a throws keyword so coders know what to catch?
> 
> Coming from a C++ background, I have a personal bias against throw specs, and I think some of the same reasons can be applied to D.  Throw specs are really only useful if every function provides one, and D's near seamless integration with C library code makes this impossible.
> [...SNIP...]
Having a throw spec lets the programmer know at compile time exactly what errors could occur. That way, one doesn't have to look through docs to find a list of exceptions that could be thrown.

Having written a fair share of Java code, I find enforced exception specs fantastically useful.

Of course, there would be 2 types of excpetions: (1)normal and (2)runtime.
1)Normal exceptions must either be caught or explicitly propagated as in the example above.
2)Runtime exceptions are exactly l ike C++ exceptions.

I don't think that D users should be deprived of such a valuable high-level tool as handled exceptions.

January 26, 2006
nick wrote:

> Having written a fair share of Java code, I find enforced exception specs fantastically useful.
> 
> Of course, there would be 2 types of excpetions: (1)normal and (2)runtime.
> 1)Normal exceptions must either be caught or explicitly propagated as in the example above.
> 2)Runtime exceptions are exactly l ike C++ exceptions.
> 
> I don't think that D users should be deprived of such a valuable high-level tool as handled exceptions.

Well, having written a fair share of Java code myself, I tend to disagree.

First, the normal/runtime distinction is somewhat arbitrary, even in the Java libraries itself. For example,

> Integer.parseInt(input_from_user)

will fail often, yet throws a "runtime" exception, and you must specifically remember to wrap it in try/catch. On the other hand,

> some_string.getBytes("UTF-8")

will never fail (Java standard mandates support for UTF-8), yet declares a non-runtime exception, so must always be wrapped in try/catch, resulting in unnecessarily ugly code.

Second, with code of any significant complexity, you soon need to either declare like 19 specific exceptions, or just wrap them into "throws Exception", which is what most people seem to do (at least where I work), at which point the declaration is totally useless, as you can basically get an Exception from any code anyway..

Third, declared exceptions really fail to work with interfaces well. For example, suppose you have something that can work either with RAM (and can fail with OutOfMemoryError), with a file (IOException) or with a database (SQLException). A common interface will either have "throws Throwable" (totally zero information again), "throws Exception" (almost zero information, and you'll probably forget about OutOfMemory), or nothing, forcing you to wrap those IO/SQLExceptions into RuntimeExceptions, and you'll need to read the docs anyway :)



xs0
January 26, 2006
xs0 wrote:


> specifically remember to wrap it in try/catch. On the other hand,
> 
>  > some_string.getBytes("UTF-8")
> 
> will never fail (Java standard mandates support for UTF-8), yet declares a non-runtime exception, so must always be wrapped in try/catch, resulting in unnecessarily ugly code.

"UTF-8" is just one of many possible arguments to this method, so throwing a checked Exception makes sense. Throwing a runtime exception just because one potential argument will never throw wouldn't be a good thing.

> 
> Second, with code of any significant complexity, you soon need to either declare like 19 specific exceptions, or just wrap them into "throws Exception", which is what most people seem to do (at least where I work), at which point the declaration is totally useless, as you can basically get an Exception from any code anyway..

Definitely poor practice. This is most noticeable with APIs like JDBC, where every method throws an SQLException. If you don't like typing try...catch blocks around every exception every time you use it, the solution is to wrap it up in a utility class that handles the exceptions for you.

> 
> Third, declared exceptions really fail to work with interfaces well. For example, suppose you have something that can work either with RAM (and can fail with OutOfMemoryError), with a file (IOException) or with a database (SQLException). A common interface will either have "throws Throwable" (totally zero information again), "throws Exception" (almost zero information, and you'll probably forget about OutOfMemory), or nothing, forcing you to wrap those IO/SQLExceptions into RuntimeExceptions, and you'll need to read the docs anyway :)

This is a weak argument. Nothing is stopping you from throwing custom exceptions and attaching the cause to them. Good exception handling code, rather than relying solely on printStackTrace(), will log the entire exception chain to a file.

Although I don't agree with your reasoning, I do agree that adding a throws statement to D would be a bad idea. I have often wished that all exceptions in Java were of the runtime variety. As for the original poster's reliance on the compiler to inform him of which exceptions need to be caught, I disagree. I rather do not like it when I compile something and see an error saying that I failed to handle an exception. I always read the documentation for every method I use if it's new to me. IDEs like Eclipse can let you know as you type, but I really do not wish to become dependent upon an IDE (as too many Java programmers are these days).

The only downside I can see to not forcing a throws statement is that when someone fails to provide proper documentation, you can't know if a method throws anything or not if you do not have access to the source. But I don't see that as reason enough to add the feature to D. More useful would be a statement that forces people to write documentation. If Walter could come up with that one...
January 26, 2006
I am a Java convert.  When I first started using D I found the lack of
requiring try/catches to be disturbing.  However, I now prefer the implicit
manner that D uses.  Why?  With either method, if you're going to be
programming safely, you're going to be putting in appropriate try/catch
blocks that handle exceptions correctly.  With Java, OTOH, I've seen a lot
of stuff like this:
try {
        FileReader fr = ...;
} catch (Exception e)
{
        //Just get the damn thing to compile... Not sure what to do if this fails
}

Which leads to code that may silently fail.  It's bitten me a few times in Java.  Of course your response is that the responsible programmer will add the proper throws clauses to his method signatures to allow the exception to propogate up, but the responsible programmer will put a try/catch in the place where it really matters regardless of whether or not he is required to.

Knowing which exceptions could get thrown is an issue of documentation.

~John Demme

nick wrote:

> Keeping it brief:
> 
> Shouldn't exception catching be mandatory as in Java?
> 
> If not, then shouldn't functions/methods still have a throws keyword so coders know what to catch?
> 
> Sorry if this has already been discussed.

January 26, 2006
Mike Parker wrote:
> xs0 wrote:
> 
> 
>> specifically remember to wrap it in try/catch. On the other hand,
>>
>>  > some_string.getBytes("UTF-8")
>>
>> will never fail (Java standard mandates support for UTF-8), yet declares a non-runtime exception, so must always be wrapped in try/catch, resulting in unnecessarily ugly code.
> 
> "UTF-8" is just one of many possible arguments to this method, so throwing a checked Exception makes sense. Throwing a runtime exception just because one potential argument will never throw wouldn't be a good thing.

I know UTF-8 is just one of many possibilities, but I'm forced to handle a never-occurring exception. Furthermore, with the data-flow checking Java does, I have to do it like this:

> byte[] out=null;
> try {
>    out=string.getBytes("UTF-8");
> } catch (UnsupportedEncodingException neverHappens) {}

Notice how it's more than twice as long as

> byte[] out=string.getBytes("UTF-8");

yet does exactly nothing more.


>> Second, with code of any significant complexity, you soon need to either declare like 19 specific exceptions, or just wrap them into "throws Exception", which is what most people seem to do (at least where I work), at which point the declaration is totally useless, as you can basically get an Exception from any code anyway..
> 
> Definitely poor practice. This is most noticeable with APIs like JDBC, where every method throws an SQLException. If you don't like typing try...catch blocks around every exception every time you use it, the solution is to wrap it up in a utility class that handles the exceptions for you.

That's just as useless. I know nothing more from the fact that it's a SQLException instead of an Exception, except that I caught it when doing a JDBC call (which I probably knew anyway). If the methods were allowed to throw an IOException as well, I would know I should probably try to reconnect and do my query again, but that's not something that can happen, so I either have to always reconnect, never reconnect or ask the user, all of which are worse.


>> Third, declared exceptions really fail to work with interfaces well. For example, suppose you have something that can work either with RAM (and can fail with OutOfMemoryError), with a file (IOException) or with a database (SQLException). A common interface will either have "throws Throwable" (totally zero information again), "throws Exception" (almost zero information, and you'll probably forget about OutOfMemory), or nothing, forcing you to wrap those IO/SQLExceptions into RuntimeExceptions, and you'll need to read the docs anyway :)
> 
> This is a weak argument. Nothing is stopping you from throwing custom exceptions and attaching the cause to them. Good exception handling code, rather than relying solely on printStackTrace(), will log the entire exception chain to a file.

That's not exception handling, it's merely exception logging. The point I was trying to make is that by fixing the exceptions that can be thrown, you force the implementors of interfaces to wrap all others into either a runtime exception or a declared non-runtime exception (if it even exists), and in both cases information about the real cause is lost, diminishing the program's ability to respond appropriately.


> The only downside I can see to not forcing a throws statement is that when someone fails to provide proper documentation, you can't know if a method throws anything or not if you do not have access to the source. But I don't see that as reason enough to add the feature to D. More useful would be a statement that forces people to write documentation. If Walter could come up with that one...

Agreed :)


xs0
January 26, 2006
On 2006-01-26 00:06:24 -0800, Sean Kelly <sean@f4.ca> said:

> void fn() {
>      throw new Exception("Surprise!");
> }

ROFLMAO....  I think I've been programming too lone, for some reason I find that hilarious.

-S.

January 26, 2006
On 2006-01-26 00:32:26 -0800, nick <nick.atamas@gmail.com> said:

> On 2006-01-26 00:06:24 -0800, Sean Kelly <sean@f4.ca> said:
> 
>> nick wrote:
>>> Keeping it brief:
>>> 
>>> Shouldn't exception catching be mandatory as in Java?
>> 
>> Why?  Exceptions should be allowed to pass as far up the call stack as the programmer wishes them to.
> Agreed. There is no contradiction:
> 
> void A() throws Exception {throw Exception("hi");}
> void B(){A();} // This doesn't work
> void B() throws Excpetion {A();} // This works
> 
> So the exception can pass up the call stack, but now the programmer is explicitly aware of what is going on.
> <snip>blahblahblah<snip>

Is there some problem with looking at the function definition?  If it's opaque, this is what DDoc is for.  Throws definitions are annoying.

-S.

January 26, 2006
> Knowing which exceptions could get thrown is an issue of documentation.

I agree. The question is, how do we enforce the partice of documenting which exceptions are thrown AND make it easily accessible to the programmer. Easily accessible meaning that he/she doesn't have to leave the IDE. Furthermore, how do we create an exception safety net.

How about, if "checked" exceptions can go potentially uncaught, there is a compiler warning. I think that's reasonable.

Thoughts?

« First   ‹ Prev
1 2 3