CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo (.com)

Blog moved to www.jeffreypalermo.com

Why are error return codes evil? - level 100

Miller ran across some code today that used error codes for return values.  We exchanged some bad examples of misusing error codes (or just using them, period).

In languages without structured exception handling, we often used some sort of indicator to communicate when an error happened.  For instance, a DOS program (or batch file) has a return code retrievable using the ERRORLEVEL global variable.

With my platform of choice (.NET) supporting structured exception handling, using return codes for error reporting is quite far on the evil spectrum.  Consider this code:

   1:  public int DoSomething(){
   2:      //omitted implementation
   3:      return -1;
   4:  }

This method should be void.  It is using an integer to tell whether an error occurred or not.  If something went wrong, throw an exception:
   1:  public void DoSomething(){ 
   2:      throw new SomethingException();
   3:  }
 

Then there is no chance of the program continuing while being broken under the covers.  Some folks call this method "failing fast".  If the program encounters a serios error that it can't handle, fail fast because a program not operating according to plan can only cause harm.  That's why so many people hate "On Error Resume Next" in VB.  Errors are simply ignored.  Some folks rigged up error handling in VB by using:

   1:  On Error Goto ErrHandler
   2:      'some code
   3:   
   4:  ErrHandler:
   5:      'do some error reporting

The team had to be very disciplined to make this work.  One funny thing I came across was a statement like the following:

   1:  On Error Goto Hell
   2:      'some code
   3:   
   4:  Hell:
   5:      'do some error reporting

Bottom Line:  Throw exceptions if something goes wrong.  Don't set a "magic number" and expect to remember to check that later on.


Comments

shebert said:

In my Fox Pro days, it was:

ON ERROR DO ME

# September 30, 2005 6:07 PM

Fregas said:

I completely 100% agree. They did something similar to this kind of crap at True.com (which is VB.NET) ALL THE TIME. They were all VB6/FoxPro developers and would catch all exceptions. log it, then keep running. So if a method that returned a string had an error, it just returned an empty string and kept on trucking. If it was supposed to return an int, it returned 0 or -1 or something.

it was so painful to actually debug and fix any given error.
# September 30, 2005 6:10 PM

Jeremy D. Miller said:

Yeah, but I miss how "ON ERROR RESUME NEXT" was a magic elixir you sprinkled over your ASP code to make things work.
# September 30, 2005 6:12 PM

Joshua Flanagan said:

Oh man, that is one of my biggest pet peeves. Anytime someone asks me to debug a "really weird problem" with a VBS or ASP, I immediately tell them to comment out any occurrence of ON ERROR RESUME NEXT and get back to me if they still can't figure out what the root problem is. I don't think they ever come back.
# September 30, 2005 6:33 PM

BlackTigerX said:

is that simple.

but there is this thing with programmers and exceptions, I don't know what it is, a lot of the people I know don't like to use them, and when they use them they use them wrong
# September 30, 2005 7:17 PM

Brendan Tompkins said:

I'd also add the following mantra:

"Throw Low, Catch High"

Often you'll see code that both throws and catches errors. While this may be okay in some circumstances, catching errors in business or data layers is almost always not a good idea, IMO...
# September 30, 2005 8:23 PM

Brendan Tompkins said:

Steve- On Error DO ME is hysterical. Man, I love finding stuff like that in code!

B
# September 30, 2005 8:26 PM

VinceB said:

I've been through all of it since DOS box C and Batch development. The other side of your good point is to make exceptions exceptional.

To me that means return something useful like a string for user interaction or a number / enumerator. You shouldn't throw an exception every time you want to return status to the caller. There isn't always a user to respond of course. Then even if you did throw and exception, what if you had 100 possible options. Are you going to write 100 different exception classes or put a result type in an exception. Then you're back to square one. It may be a batch process that needs to send the string to a log or act according to the error number to retry the operation or send it to MSMQ or email someone about the issue.

Also, returning void when you could have returned a status for the user or for extra processing seems like a waste of good stack space. No status and no string mean all went well.

Now exceptional means if the process is really bad and not just status, then you gladly take the big CLR hit to throw an exception. That gives all power to the developer. In reality, a good application will catch normal and exceptional errors and act accordingly.

These say it best:
http://blogs.msdn.com/ricom/archive/2003/12/19/44697.aspx
http://blogs.msdn.com/ricom/archive/2005/03/01/382756.aspx

Then Brad Abram's the July 11th posting at:
http://blogs.msdn.com/brada/archive/2005/07.aspx

Some of the presentations with Brad and Rico touched on the fact that exception handling should be exceptional. Perform normal handling otherwise.

# October 1, 2005 9:50 AM

Joshua Flanagan said:

I agree with VinceB that exceptions aren't appropriate in ALL cases. I also realize that figuring out whether something is an "excpetional" case isn't always straightforward. But things don't have to be as bad as using a "magic number", we do have a real boolean data type, after all.
I think the TryParse methods are perfect examples of times when something will fail an awful lot, and its really unnecessary (and costly) to throw an exception.
Jeffrey Richter does a good job of covering this subject in his book.
# October 1, 2005 10:45 AM

Rick Scott said:

I really have to take EXCEPTION to this blog entry. If a decently-trafficked website had to throw and catch an exception every time a user didn't fill in something just right or some mis-match happened in the database, the site would be slow or down most of the time.

Simple scenario:

User wants to login to a popular website
User enters username, but fat-fingers it
Database takes username and finds no user record
So the Data Access Layer should throw an Exception?

No. That's bad. Just return 0 instead of the user's ID...or -1, maybe using -2 if their password didn't match or -3 if the retry-limit has been exceeded. No need to throw exceptions all over the place.

The point is this: Just because a function is "not successful" does not mean it is exceptional. If you handle all possible cases of "not completely successful" with exceptions, you are just using exceptions as flow control. And THAT is the real evil.
# October 3, 2005 10:38 AM

Jeffrey Palermo said:

Rick,
You make a very good point, and I think most people reading this blog understand not to abuse exceptions. Checking a method Exists() on a user object that returns bool is a great way in your example, but that not an "error code". That's a valid method with a concrete result.

It would be bad to have a LogIn() method that returned "-1" if the user didn't exist, a 1 if the login was successful, and a 0 if the password was bad.

# October 3, 2005 2:59 PM

Gary Willliams said:

Yes, error codes are evil. Anything that is a purely numeric representation of something is a *bad* thing. Might have been necessary back in the days when we counted bits, but these days it's a waste. Exceptions for exceptional processing and return codes for processing results. I don't see any reason to do anything else in any language that supports exceptions.
# October 4, 2005 4:38 PM

Alexandru Matei said:

Hello,

Answering VinceB comment:

"Then even if you did throw and exception, what if you had 100 possible options. Are you going to write 100 different exception classes?"

My answer is this:

- if those 100 possible error options are each handled in different ways, then yes,  we should create 100 exception classes and throw them when the function

cannot complete its task

- if some of those 100 possible error options are handled in the same way, group the error details under the same Exception class derived type.

Jeffrey Richter in his book "CLR via C#" says in Chapter 19 - Exception

The exception-handling mechanism offers several advantages over a 32-bit number.

- An exception includes a string description of the problem;

If an invalid argument exception occurs, you will know exactly which argument is causing the problem. The string might also include additional information giving you guidance as to how to improve the code.

- Exceptions also include a stack trace that tells you which path the application took when the exception occurred.

- Exceptions is that they don't have to be caught or detected at the place

they occur; any code in the thread's call stack can handle a thrown exception.

This simplifies coding substantially because you don't have to associate error detection and correction code with every statement or method call that might fail.

- perhaps the biggest benefit of all: an exception can't be easily ignored.

If a Win32 function is called and returns a failure code, it's all too easy

for the caller to ignore the return code, assume that the function worked as expected, and

allow the application to continue running as if all is fine.

All of the methods defined by types in the Microsoft .NET Framework throw exceptions to

indicate that the method couldn't complete; no 32-bit status values are returned. All programmers must therefore have a full understanding of exceptions and how to handle them in their code.

Microsoft made a great decision here! Using exception handling in your code is straightforward and allows you to write code that's easy to implement, easy to read, and easy to maintain.

In addition, exception handling allows you to write robust code that's capable of

recovering from any application situation. Used correctly, exception handling can prevent

application crashes and keep your users happy.

# October 22, 2007 8:35 AM

About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication

News

Headspring Systems

View Jeffrey Palermo's profile on LinkedIn

See my new blog at .jeffreypalermo.com