Should a failed function return a value or throw an exception?

March 11, 2010 – 5:58 pm Tags:

You have created a nice, well written function, but you realize you forgot something: The failure case.

What should a function do when it fails? There are two schools for this – the “throw an exception” school and the “return an error value” school.

But which of these is the correct approach?

Some background

Back in ye olden times there were no exceptions. Languages like C are still being used today. In such languages the choice is quite easy to make.

However, what about languages that do support exceptions? Should you strive to use the language’s features to their fullest, and always throw an exception? Are error returns just relics?

If you listen to people talk about this, it often turns into a debate about what they like. If you grew up with languages that had no exceptions, chances are you still prefer return codes. Similarly, if you used a lot of Java or other exceptional language, you might end up flaming return codes.

However, I think both of them deserve merit and have their uses.

Basics

As you may have heard, exceptions are for exceptional conditions.

But what is an exceptional condition? What isn’t?

Let’s take an example: Your application attempts to load a resource file – for example the configuration settings for your database – and it’s missing.

Is this an exceptional condition? Maybe. It depends on one thing: Is it normal for it to be missing, or should the file always be there?

function loadConfiguration() {
  var file = open('configuration.ini')
 
  if(exists(file)) {
    read(file)
  }
  else {
    throw "Configuration file is missing"
  }
}

So this pseudo-code could be a simplified configuration loading function. In this case the configuration file has to exist – let’s say it’s some internal file.

But what if the file is something that contains settings the user has selected? In that case it might be perfectly fine for the file to not exist. The user may not have added any custom settings and as such, it’s normal for the file to be missing. In this case our function could look like this:

function tryLoadConfiguration() {
  var file = open('configuration.ini')
 
  if(exists(file)) {
    read(file)
    return true
  }
  else {
    return false
  }
}

Note that I also changed the name of the function a bit. It may be a good idea to try indicating that the function will be returning a value – It tries to do it, so the name is more expressive of the permissive nature and that it’ll return whether it succeeded or not.

Other examples

Other good examples are various string related functions. In many languages, there exists a function to determine whether a string contains another string, and this function usually return -1 on failure.

It’s normal for this function to not succeed, afterall, we are using it to test whether or not the condition is met.

There are also more “pure” arguments for either side. Exceptions are essentially objects, so they can convey more information than just the fact that things went wrong. On the other hand, an exception can be thrown deep in the code but appear on the surface unless caught early enough. This could make tracking the origin and cause of the exception more difficult.

Ned Batcheler has some good reasons for exceptions compared to error returns on his blog in addition to these. However, is this all?

Deeper considerations

It’s not all just talk about exceptional conditions or technological preferences.

An often forgotten fact is application stability. If you are writing critical code that should be as stable as possible, what should you use? Return values.

An uncaught exception can bring down a whole application. An unhandled return code might not really cause anything at all. Sometimes it’s important to consider this factor too.

There are probably other things like this too. If you know any more examples of more special things to take into account, post a comment please.

Conclusion

We can say that exceptions can be convenient. We can also say you can easily use exceptions too much, and that how to decide whether to use them or return codes is difficult. It comes with experience, but I hope this post sparked some ideas for you. Damien Katz’s blog also has a (long, long) post on exceptions, error codes and reliability which is kind of related.

When do you think it’s a good idea to use exceptions? Return values? How do you decide? Share in the comments!

Share this:
  1. 28 Responses to “Should a failed function return a value or throw an exception?”

  2. Application stability is certainly important. But is it really served with error codes? It’s all about the “fail early” principle. If there’s a bug in your code and it makes the application crash, that may be a good thing, because you might fix the bug instead of letting it stay and cause subtle, perhaps sporadic problems that are extremely hard to stamp out.

    The string function you mention is different because its purpose is to return an answer. It’s a query. Part of the answer is to have more of those. In the file example, I would have a separate function to test for the existence of the file. That would make the both the function itself and the client code easier to read. (Although the function in this case is so simple it wouldn’t matter much.)

    The refactoring Replace Exception with Test makes this point. http://refactoring.com/catalog/replaceExceptionWithTest.html

    By Dagfinn Reiersøl on Mar 11, 2010

  3. Yes, functions should return values, but only if they are designed to do a comparison, or if they are designed to return a value.

    function is_divisible($x, $y) {
    // return: 1|0 (true|false)
    // if the remainder of
    // x%y greater than 0 (not divisible)
    if (($x % $y)>0) {
    // not divisible
    return 0;
    } else {
    // we’re divisible
    return 1;
    }
    }

    $a = 50; $b = 2;

    if (test_case($a,$b)) {
    echo “Woo! $a is divisible by $b”;
    } else {
    echo “Ono! $a is not divisible by $b”;
    }

    By Zach on Mar 12, 2010

  4. That should be if (is_divisible($a, $b)) {
    not test_case()

    By Zach on Mar 12, 2010

  5. My general rule of thumb is that exceptions are used in object-oriented programming. In procedural programming, I tend to have functions return error values; in object-oriented programming, I throw exceptions.

    By Brandon on Mar 12, 2010

  6. I see major issues with saying error codes improve stability. If you have a true Exception, then something bad happened regardless of whether your throw an Exception or not. Your application has already crashed, and not stopping there is just asking for more problems (and often unintended and unexpected problems).

    By jason on Mar 12, 2010

  7. Has to do a lot with perspective too. Not perspective of the programmer but perspective of the function. I.e. if I have a function in the M part of an MVC app, say find(id) that attempts to locate a given record in a data store of some sort, then the question arises, if the record with the given id doesn’t exist is that exceptional? Definitely *not.* It is perfectly normal for a given ID to not exist in the data store. In such a case i return NULL.

    However, what if you are in a controller (reached, e.g., by a user clicking on a link that is supposed to load a resource given a record id) and call find(id) and NULL is returned? Is that exceptional? I would say yes because it is *not* normal that your site be displaying a link to a record that does not exist. In this case an exception is warranted, but it should be the calling method in the controller object that throws the exception.

    Perhaps another way of saying exceptions are for non-normal cases is to say: use an exception if an implicit promise has been broken: someone along the line has broken their contract.

    By David P. on Mar 12, 2010

  8. … also, would agree very much with Dagfinn and jason. Not sure who said it but … “Crash loudly.” Otherwise you’ll get into more trouble, and probably won’t be able to figure out what happened since the “evidence” will have gone cold.

    By David P. on Mar 12, 2010

  9. The only blanket answer you can ever give to this debate is: “it depends on the context”. Some functions can return false as normal behavior, and some require an exception to be thrown if anything goes wrong. It all depends on how it’s called and handled in context.

    In production, I think it’s actually even MORE important to use exceptions than error status returns because when something doesn’t work the way it should, I want to know about it immediately. Crash loudly for sure. Exceptions can be caught at the root level and be emailed or logged automatically before displaying an error to the user. It’s much harder to do that with return status codes.

    By Vance Lucas on Mar 12, 2010

  10. You should always return a value so the program can handle it. Unless you are catching the exceptions, you should not use them. They are really for collecting technical information and should never be displayed to the end user.

    By Luke on Mar 12, 2010

  11. Coming from a Java background I try to avoid mixed return types because it introduces unpredictable behaviour in your application. Using exceptions forces you, and your colleagues, to think about your code. BUT! Nowadays I tend to use Smarty for my templates and since exception handling is only introduced in version 3 of it, I am sadly forced to use mixed return types.

    By Timo on Mar 13, 2010

  12. An interesting topic. I think that one important point you’ve skipped over here, and one that I think is conspicuously absent from most discussions I’ve read on Exception handling in PHP is that you should avoid throwing Exception.

    Quite often I’ve seen something like:

    throw new Exception($errno);

    which is basically the same as using a return value.

    The beauty of exceptions vs. return values is that they allow you to handle the situation wherever you like, not just at the point you called the method.

    I generally create classes that extend Exception habitually even if my declaration is just like this:

    class SomeCustomException extends Exception{}

    There’s nothing worse that code catching an exception it shouldn’t! the catch(Exception …) should be the *parachute* sitting outside the entire operation of your app – it’s a sign that something went REALLY wrong because there was an exception that wasn’t caught by anything.

    So the answer to the question of whether to use exceptions or return values is: you should use both by themselves or together.

    Some examples:

    1. Db::connect(): returns a mysql result resource or throws AccessDeniedException, InvalidHostException or DbServerException

    2. Curl::exec(): returns the result of the page execution (could be ” which == FALSE but not === FALSE), or throws CurlException which contains a curl error message and curl error number

    Basically a return value should pertain to the *name* of the method – to it’s original purpose. An exception is some condition that prevented it’s original purpose from being carried out.

    Good topic. I think there’s not enough discussion about PHP exception handling going on.

    By Iain Dooley on Mar 13, 2010

  13. I prefer to use exception handling because with custom exceptions you can identify the problem and take the appropriate action. In best case scenarios a function should only have a logical exception, but there are cases when functions have allot of things and can throw different errors.

    By razvantim on Mar 13, 2010

  14. Another option for handling failing functions is the Null object pattern. I personally don’t like the PHP practice of returning error codes – I think the Python model of always throwing exceptions is much better. I’ve previously written about this topic too: http://codeinthehole.com/archives/33-Return-false-with-prudence.html

    By David Winterbottom on Mar 14, 2010

  15. Thanks for your comments all.

    David, good point about the null object there. I’ve actually written about them here before, see http://codeutopia.net/blog/2009/09/12/what-is-a-null-object-and-when-are-they-useful/

    By Jani Hartikainen on Mar 14, 2010

  16. Wow. I really want to slap you for your “If you are writing critical code that should be as stable as possible, what should you use? Return values.”-comment.

    That’s exactly when you should use a CHECKED EXCEPTION. This *forces* the developer to handle the error case(s) rather than giving them ability to ignore a return value.

    By Bram on Mar 19, 2010

  17. There’s often a fear that throwing exceptions is an old-school way of doing things, and that every time we make the decision to throw an exception, it just results in more code. Code to handle the exception, code to put acceptable messages on the screen, code to log the exception, codes embedded in the exceptions that can be quantified. This is all true, and can be a pain in the ass.

    But what’s even worse is when the decision is made to have a function return an error code, and have execution continue. What I’ve seen happen many times is users reporting ‘strange errors’ that shouldn’t ever really happen, but obviously do. Using an error code doesn’t really ever give devs the information necessary to diagnose issues, and the application winds up having many hard to reproduce issues that never yield a trail to follow.

    Therefore, I usually like to throw exceptions, as even if the extra code to handle exceptions isn’t written, PHP + Apache can be configured to log stack traces to the apache error_log, which actually gives devs something to go on. It also allows code to crash hard and crash early, meaning that an error that happens early doesn’t have to be accounted for in the far flung reaches of the execution path.

    By Chris Henry on Apr 4, 2010

  18. Why not return an Exception?

    By LarryTheCanary on Jun 2, 2010

  19. “an exception can be thrown deep in the code but appear on the surface unless caught early enough. This could make tracking the origin and cause of the exception more difficult.”

    Well ex.StackTrace() exists for precisely this purpose :)

    By Kaustubh on Oct 18, 2010

  20. In Java ;

    I we have to deal with returnObject and it’s details in every steps in a function, it is very possible for us to miss/forget to check a return code in somewhere.

    If methods that we rely on throws exception compiler forces us to handle in a right way !

    So I prefer “throw exception always” instead of returning errorCodes/returnObjects;

    Also returning errorObjects makes my code longer than expected. Unnecessarly i need to check errorCodes catching them with my eyes.

    And Of course there are cases in which you have to return codes. and They must be handled in upper levels in the software by checking the operation result/exception’s details if they are exists.

    By Serkan Sunel on Feb 23, 2011

  21. I agree with most of the reasons for exceptions but also don’t really like to have code littered with code testing for a condition and throwing exceptions because it increases the amount of code and therefore complexity. I have written a little wrapper that one can put around a php built-in function that normally returns an error code. Here goes:

    function ex($ret, $type='Exception', $user_message=null)
    {
       if ($ret !== false && $ret !== null ) return $ret;
       $error = error_get_last();
       $file = $error[file];
       $line = $error[line];
       $message = $error[message];
    //   log::debug("THROW: FILE: $file($line): ERROR: $message): $exception($user_message)");
       if (!is_null($user_message)) $message = $user_message;
       throw new $type($message);
    }

    Note: the commented lines are for error logging using our own error logging library.

    Usage:

    
    $file = ex(fopen("invalid.txt", 'r'));
    
    

    The above will throw an Exception if file is invalid. To throw a specific exception, you can also use it like:

    
    $file = ex(fopen("invalid.txt", 'r'), MyOwnException);
    

    In a language like C++, one could #define a macro that redefines certain critical stdio.h functions to throw instead of just returning a return code. This way you can add exception throwing to the code by just including the header with the #defines.

    By Fhulu Lidzhade on Oct 11, 2011

  22. as one of the guys above said … exceptions are used in object-oriented programming. In procedural programming, I tend to have functions return error values; in object-oriented programming, I throw exceptions.

    By new exception on Jun 13, 2013

  1. 7 Trackback(s)

  2. Mar 13, 2010: PHP-help » Jani Hartikainen’s Blog: Should a failed function return a value or throw an exception?
  3. Mar 13, 2010: Jani Hartikainen’s Blog: Should a failed function return a value or throw an exception? | PHP NEWS
  4. Mar 20, 2010: Max’ Lesestoff zum Wochenende | PHP hates me - Der PHP Blog
  5. Apr 29, 2010: RV | Developers » Blog Archive » Exceptions vs Failure Return Codes
  6. Jun 9, 2010: Throw an exception or return an error value | DevReference.org
  7. May 6, 2011: How to use built-in SPL exception classes for better error handling | CodeUtopia - The blog of Jani Hartikainen
  8. Aug 2, 2012: Macroblog Base10 » Code review recommendations and Code Smells

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)