Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple return values to indicate success/failure.

Tags:

php

I'm kind of interested in getting some feedback about this technique I picked up from somewhere.

I use this when a function can either succeed or fail, but you'd like to get more information about why it failed. A standard way to do this same thing would be with exception handling, but I often find it a bit over the top for this sort of thing, plus PHP4 does not offer this.

Basically the technique involves returning true for success, and something which equates to false for failure. Here's an example to show what I mean:

define ('DUPLICATE_USERNAME', false);
define ('DATABASE_ERROR', 0);
define ('INSUFFICIENT_DETAILS', 0.0);
define ('OK', true);

function createUser($username) {
    // create the user and return the appropriate constant from the above
}

The beauty of this is that in your calling code, if you don't care WHY the user creation failed, you can write simple and readable code:

if (createUser('fred')) {
    // yay, it worked!
} else {
    // aww, it didn't work.
}

If you particularly want to check why it didn't work (for logging, display to the user, or do whatever), use identity comparison with ===

$status = createUser('fred');
if ($status) {
    // yay, it worked!
} else if ($status === DUPLICATE_USERNAME) {
    // tell the user about it and get them to try again.
} else {
    // aww, it didn't work. log it and show a generic error message? whatever.
}

The way I see it, the benefits of this are that it is a normal expectation that a successful execution of a function like that would return true, and failure return false.

The downside is that you can only have 7 "error" return values: false, 0, 0.0, "0", null, "", and (object) null. If you forget to use identity checking you could get your program flow all wrong. Someone else has told me that using constants like an enum where they all equate to false is "ick".


So, to restate the question: how acceptable is a practise like this? Would you recommend a different way to achieve the same thing?

like image 964
nickf Avatar asked Sep 16 '08 14:09

nickf


2 Answers

I agree with the others who have stated that this is a little on the WTFy side. If it's clearly documented functionality, then it's less of an issue, but I think it'd be safer to take an alternate route of returning 0 for success and integers for error codes. If you don't like that idea or the idea of a global last error variable, consider redefining your function as:

function createUser($username, &$error)

Then you can use:

if (createUser('fred', $error)) {
    echo 'success';
}
else {
    echo $error;
}

Inside createUser, just populate $error with any error you encounter and it'll be accessible outside of the function scope due to the reference.

like image 70
Jeremy Privett Avatar answered Nov 13 '22 13:11

Jeremy Privett


As long as it's documented and contracted, and not too WTFy, then there shouldn't be a problem.

Then again, I would recommend using exceptions for something like this. It makes more sense. If you can use PHP5, then that would be the way to go. Otherwise you don't have much choice.

like image 43
Chris Broadfoot Avatar answered Nov 13 '22 14:11

Chris Broadfoot