Page 1 of 2

Many returns

Posted: Tue Jul 26, 2005 10:26 pm
by stukov
I always have been told to have only one return per function while coding. I see many people using plenty of them in their functions, so I am wondering if it is really bad.

Any opinions?

Posted: Tue Jul 26, 2005 11:11 pm
by nielsene
If returning early is a "special case","base case", etc. I'd say do it. It will reduce the depth of the nesting, which helps readable code and its easy to see where the special cases finish. If its more complicated, then no.

Ie, if you can write code like

Code: Select all

function foo($bar) (
  if (0==$foo) return 1;
  if (1==$foo) return 2;
  // big nasty rest of logic
  return $calcValue;
}
then I think the multiple returns are good.

Posted: Wed Jul 27, 2005 7:54 am
by timvw
It's the same as saying that goto, break, continue etc are evil.. They are only evil if you don't know (well enough) what they do :P

http://en.wikipedia.org/wiki/Structured_programming

Posted: Wed Jul 27, 2005 8:38 am
by nielsene
In case you see the term, somewhere else, the multi-return method, with most of them being simple returns at the start of the function are often called "Guard Clauses".

Posted: Wed Jul 27, 2005 10:06 am
by stukov
Now it's seems clearer, but over 100 000 visits / minute, will there be a difference at the execution time and at the ressource usage or is it only a way to make code easier to read?

Posted: Wed Jul 27, 2005 10:26 am
by nielsene
There might be a slighlt difference in execution time, but its most likely so far down in the "noise" that I wouldn't worry about it until I've profiled the application under normal/high load.

Posted: Wed Jul 27, 2005 8:41 pm
by stukov
Ok. I understand. Thanks a lot.

Posted: Thu Jul 28, 2005 3:49 am
by McGruff
It's not something I ever think about. Just keep functions nice and tight, doing one thing only, and then return as many times as you need in order to do that one thing.

Posted: Thu Jul 28, 2005 10:47 am
by pickle
Only having 1 return statement is a practice, I think, to correct for human error. For myself at least, if there's only 1 return statement, I'm more likely to make sure that 1 statement returns exactly what I want. In other words, I'm sure I've taken care of every condition. If I have return statements all over, then its harder for me to look through the code and be sure I've thought of everything.

It's kind of like having having a default case in a switch statement to make sure everything's handled, as opposed to just having specific cases and trying to be comprehensive with all my cases.

Posted: Thu Jul 28, 2005 11:12 am
by Ambush Commander
Well, if your functions are that complicated, maybe you should stick them in a class or something.

Posted: Thu Jul 28, 2005 5:53 pm
by stukov
I think I'll stick to

one return per function;
if the use of many returns is required -> the function is not simple enough -> redesign;

Posted: Thu Jul 28, 2005 7:23 pm
by McGruff
I don't think you can sustain that.

I grabbed the following two methods at random. In the first, I'm hunting through a list of query types looking for a match. As soon as I find one, I return some information about the query ($meta). There's no need to continue with the loop. If I don't find a match, the fn returns false.

In the second, I'm checking for database.table dot syntax in an sql query. Whatever the query string, I want an array with database and table values out of the function. However, if it's badly-formed (multiple dots) I need to return false since it's effectively unparsable.

Even with nice, short methods, you will need multiple return values at times. It could be a smell but not necessarily so.

Code: Select all

/*
        param (string)
        return (mixed)
    */
    function parse($sql, $currently_used_db)
    {
        $this->_currently_used_db = $currently_used_db;
        foreach($this->_recognised_queries as $query) {
            if(preg_match($query['pattern'], $sql, $matches)) {
                if(count($meta = call_user_func_array(array(&$this, $query['fn']), array($matches)))) {
                    $meta['query_type'] = $query['type'];
                    return $meta;
                }
            }
        }
        return false;
    }
    // $parts[0] db name
    // $parts[1] table name
    function _dotSyntax($query_target)
    {
        $parts = explode('.', $query_target);
        if(count($parts) == 1) {
            array_unshift($parts, $this->_currently_used_db);
        } elseif(count($parts) > 2) {
            trigger_error('unparsable: multiple dots');
            return false;
        }
        return $parts;
    }

Posted: Thu Jul 28, 2005 8:14 pm
by harrisonad
Unexpected errors caused me to return early.

Code: Select all

function ValidEmail($email){
    if(!$email) return false;
    // rest of the code, including the last return statement
}

Posted: Thu Jul 28, 2005 8:30 pm
by nielsene
harrisonad wrote:Unexpected errors caused me to return early.

Code: Select all

function ValidEmail($email){
    if(!$email) return false;
    // rest of the code, including the last return statement
}
Exactly (or maybe throw an exception in PHP5)

otherwise you end up with extra nested code

Posted: Thu Jul 28, 2005 8:50 pm
by Ambush Commander
PHP5 exceptions are really really cool (I read about them). Too bad they aren't in PHP4.