Fog Creek Software
Discussion Board




Exceptions good, just don't catch them!

I'd like to comment on Joel's two points about the failings of exceptions.

Joels first point is that exceptions are invisible in source code and "This means that even careful code inspection doesn't reveal potential bugs."  The comment I have to this is that when the exception is thrown, the bug has already happened. 

In most cases, the exception represents a serious error and you should terminate the app immediately (with an appropriate error message).  The exception will detail the exact error at the exact point it occurred (if well written).  Debugging becomes much easier.

Error codes, on the other hand, can be both ignored or masked.  My function might terminate with an error code but information about the original source and nature of the error is lost unless alot of work is done in every function.

Additionaly, most exceptions represent a terminal failure condition for your app, you shouldn't try and catch and handle them.  They should eventually be caught with a global handler that prints out useful debugging information and terminates your app.  In this case, you won't have any problems with multiple exit points or unfreed resources.  However, trapping exceptions is fairly safe as well.  All exception-based languages provide proper cleanup mechanisms that can easily cleanup everything nicely.  So, ultimaltely, you can do something like this:

try {
    FileSave();
} catch (err) {
    Msgbox(err.Message());
}

And everything chugs along smoothly.  Isn't that easier than passing around error codes?

Almost Anonymous
Tuesday, October 14, 2003

darn, you posted this while I typed in mine - just want to say:

yeah, right!!

Sam
Tuesday, October 14, 2003

And in Java you have to explicitly catch an exception, or adjust your method's declaration, so it is NOT invisible...

Hairy Monkey
Tuesday, October 14, 2003

Exceptions can represent serious (fatal almost?) failures.

They can also represent recoverable errors (e.g. network connections; it would be appropriate in many circumstances to have a retry system).

And they can also be part of your logic itself.  But that is another topic.

The more I write catch blocks in Java, the more I appreciate that most exceptions are recoverable.  And the best place to recover is close to where the exception was thrown.  Of course in java you get to choose how close 'close' is.

Maybe business software can just give up when it hits an io exception.  But shrink wrapped software can't.  It has to hide problems and errors and obscure codes from the user as much as possible.  Even if the network connection drops when uploading a page, for example, things have to go on (behind the scenes).  The user doesn't want to know about this kind of technicality.

Just my reason for keeping my catches close ala Joel and James Gosling.

i like i
Tuesday, October 14, 2003

I have code in one of my projects that looks pretty much like the file save pseudo-code I have listed above (except it's for File load).  Basically, if the disk is full or the file is locked or whatever (recoverable errors) the file load failed.  It prints an informative message to the user and continues.  If they free up some disk space or unlock the file they can try saving again.

I used to think that Java's use of forced exception declaration (or handling) was good.  But ultimately that just turns exceptions into error codes: You always have to handle them (or do a lot of declaring them) and so you have the same issues of ignoring and masking. 

Exceptions are not supposed to be micro-managed.

Almost Anonymous
Tuesday, October 14, 2003

Slightly off-topic, but here's Anders Hejlsberg's rationale for why .NET doesn't have "handle or throw" paradigm that Java does:

http://www.artima.com/intv/handcuffs.html

Tom
Tuesday, October 14, 2003

I pretty much agree with Hejlsberg on that one.

I also liked this quote:

"It is funny how people think that the important thing about exceptions is handling them. That is not the important thing about exceptions. In a well-written application there's a ratio of ten to one, in my opinion, of try finally to try catch. Or in C#, using statements, which are like try finally."

Which sums up my position better than I could say. 

Almost Anonymous
Tuesday, October 14, 2003

I started using this VB6 module called HuntErr that revolutionized the way I code.  Look it up if you code in VB6 and you want excellent error handling!

This module helps me pinpoint the cause of the error by re-raising the errors to the top of the callstack and saving info about each call along the way.  When it gets to the top I have a complete error report including line numbers and (if you want) call parameters/values.

At the top of the call stack (usually an event) I just pass the error to a "handler" object that logs/shows the error.  I also have a DLL that houses a class and some forms for dealing with errors which is quite nice because you can change how you handle errors in *all* of your programs with a single patch.

I actually LOVE errors now because with the reports that I get now I can fix things much quicker and it also made me code 10x better than before (trying to ignore errors, or writing "catch-all" code points).

Wayne
Tuesday, October 14, 2003

Oh yeah, I forgot to mention that HuntErr adds the idea of "Exceptions" to VB6 by masking the Err.Number that it raises. 

So you can raise exceptions like EXC_VALIDATION and your central handler can just display a message and not log it when it detects number like this.

Wayne
Tuesday, October 14, 2003

*  Recent Topics

*  Fog Creek Home