Fog Creek Software
Discussion Board




An alternative to exceptions and error codes?

There's been a lot of debate recently about the relative merits of using return codes and exceptions.

What I'm wondering is this: is there a third way? I can't seem to think of any. Has anyone ever seen anything use another error reporting method?

Mike Swieton
Thursday, October 16, 2003

One of the major uses of exceptions is data validation. You could use a language that supports Design By Contract, and get rid of the vast majority of them.

Brad Wilson (dotnetguy.techieswithcats.com)
Thursday, October 16, 2003

We could use 3D, instead of 2D code.

Normally, the flow of execution goes downward.

In case of an error, the flow of execution goes perpendicular on the code, along the Z axis.

Jed
Thursday, October 16, 2003

Many Unix functions signal errors by setting the global int variable "errno".  This is even easier to ignore than a return value. This can be good or bad, dependng on if you want to write quick and dirty code or robust code.

A variant of this idea is to have a function that returns the error state. An example of this is the function GetLastError() in Windows.

John Brophy
Thursday, October 16, 2003

Command pattern.

Flamebait Sr.
Thursday, October 16, 2003

In Smalltalk, we sometimes pass a block of code (to serve as an error handler) as a parameter to a method.

    translation := dictionary at: word ifAbsentPut: [FillInTheBlank request: 'Please type in the translation of ', word]

That's a call to a method named "at:ifAbsentPut:". It'll look up the word in the dictionary, but if it doesn't find an entry for that word, it'll ask the user to input the translation manually (and then add it to the dictionary).

Adam Spitz
Thursday, October 16, 2003

GetLastError. *Yuk*

The third way is for me the most unintuitive.  It has also the same design problem of return codes. It does not require the programmer that uses the particular function to deal with the error.

Design By Contract concept can be used with languages without support in it. Although it requires a little more discipline. Like you can program with OO concepts in pure C.  e.g. you encapsulate by your own programming and design because the compiler does not help you in C!

Janne V
Thursday, October 16, 2003

Yes, there is a third way as found in Forth: conditional multiple return values: a routine can return a Boole on the stack indicating success or failure. However, if-and-only-if successfull, the stack will also contain a result, making the number of output parameters dependent on the Boole result. This way one cannot ignore the error flag, but it is also possible to get at the result in case of a failure. Very neat. Works well.

"One of the major uses of exceptions is data validation. You could use a language that supports Design By Contract, and get rid of the vast majority of them"

This is not what DbC was designed for and it is bad practice. Exceptions are to be used for exceptional cases not for common cases such as input errors.

Contracts define the interfaces, and breaking a contract is a *violation* of programming logic. Your programs should not break on a user entering invalid data.

I guess that any language feature can be abused...

There is another practical reason not to use DbC for data validation: input errors are usually known very locally, so a simple test can suffice. Even in a complicated case it is possible to postpone validation and use a single routine to validate multiple inpunt fields (including their referential validity. If this routine marks the data as invalid one can simply loop back to the entry form.

The important advantage of such a routine is that it can be used for 'non-destructive' validation on many different contexts. Because that is what it is: just a validation routine, an abstraction in itself. Contrary to preconditions of a procedure, there is no further action behind it.

Karel Thönissen
Thursday, October 16, 2003

I use ASSERT to enforce design by contract in C++.  If a program has a flaw (say exceeds some buffer size limitation) you are pretty much screwed if you don't catch this during debugging.

On windows you could handle the flaw with a last resort SEH that does something to effect of poping up a message box that says..

"Sorry you are screwed.  Have a nice day."

Rhapsody from listen.com does this.

christopher baus (tahoe, nv)
Thursday, October 16, 2003

Oops: "This way one cannot ignore the error flag, but it is also possible to get at the result in case of a failure.

This way one cannot ignore the error flag, but it is also /im/possible to get at the result in case of a failure.

Karel Thönissen
Thursday, October 16, 2003

I think there is a third way, but I haven't tried it yet.  Have an error log object.  Rather than throwing, write to the error log.  Calling objects can then check the error log to see if any errors have been thrown.  You could even have the error log allow objects to optionally provide a call back to be called when the error log is written to.

It would be like an error code that you check later, or farther down the call stack if you want.  And, you could extend it to save a whole bunch of other useful context information.

Keith Wright
Thursday, October 16, 2003

It's not always appropriate or worth the trouble, but I like the idea of an error callback (sort of like what Adam suggested for Smalltalk).  It makes it easy to reuse a processing sequence in different applications (for example, interactive vs. non-interactive) where the appropriate response to an error can be totally different (for example, prompting the user in an interactive application for information needed to complete processing).

I also like the idea of being able to switch between different schemes -- for example, VB's On Error.  Want to not worry about error handling and let it bubble up to the caller?  That's the default.  Want to handle errors sequencially by checking an error value?  Use On Error Resume Next and the Err object.  Want to ignore errors?  Use On Error Resume Next and don't check Err.  Want to keep error handling logic separate from the rest of the logic?  Use On Error GoTo.  I'm not suggesting that VB should be the model for all language design, just that the ability to switch paradigms can be useful when different tasks call for different approaches. 

SomeBody
Thursday, October 16, 2003

Flamebait:

I don't understand how the command pattern solves the issue.

A command object is supposed to basically have a run method or similar that performs an action. So if it fails, you'll what, return a value? Throw an exception? Set a member of the command object itself? How is this different?

Mike Swieton
Thursday, October 16, 2003

christopher_baus: "I use ASSERT to enforce design by contract in C++. "

How do you handle subcontracting?  One of the main reasons I can't use DbC effectively in the languages I use for work is that it's really hard to build the constraints imposed by sub-contracting using only assert(), so I'm interested if there is some solution that hasn't occurred to me.  Thanks!

contractor bob
Thursday, October 16, 2003

"I don't understand how the command pattern solves the issue."

Maybe you pass in a command object and if an exception occurs, you call it's execute() method.  Similar to the callback approach mentioned above.

one interpretation
Thursday, October 16, 2003

http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html

Miki
Friday, October 17, 2003

ON ERROR PROCHandleError();

Ye olde basic way.

Mr Jack
Friday, October 17, 2003

contractor bob: "How do you handle subcontracting?  One of the main reasons I can't use DbC effectively in the languages I use for work is that it's really hard to build the constraints imposed by sub-contracting using only assert(), so I'm interested if there is some solution that hasn't occurred to me.  Thanks!"

If you are using C or C++, I would recommend the Digital Mars ( http://www.digitalmars.com/ ) compiler. It adds DbC support to those languages ( http://www.digitalmars.com/ctg/designbycontract.html).

If you are using Java, there's nothing I would actually _recommend_, but a quick Google should provide you with a few options.

One of the important parts of DbC (which is not met by assert() or most add-on tools) is that the contract is included in the docs along with the description and method signature. The contract contains the semantics of the call, which must be known by the caller.

Greg Pfeil
Tuesday, March 09, 2004

*  Recent Topics

*  Fog Creek Home