views:

96

answers:

5

Hello all,

As a PHP programmer faced a lot with (deepgoing) statements I'm curious how you handle this. Are you using switch, if-elseif-else or if-else structures?

I personally prefer using the switch selector when dealing with more than 2 cases. Is this also the best way from a performance perspective? And how about nested statements?

I'm curious to your preferred methods and answers.

Example

The need of three-option-selector:

Using switch:

switch($option)
{
  case 1 : $result= "foo"; break;
  case 2 : $result= "bar"; break;
  default : $result= "foobar";
}

Using if-elseif-else

if($option == 1)
{
  $result= "foo";
} elseif ($option == 2)
{
  $result= "bar";
} else
{
  $result= "foobar";
}

Using if-if-else

if($option == 1)
{ 
  $handle = "foo";
}
if($option == 2)
{
  $result = "bar";
}
else
{
  $result = "foobar";
}
+1  A: 

I find switch handy when you have one piece of logic shared amongst many cases. ie.

case 1:
case 2:
case 3:
    // do stuff for 1, 2 and 3
    break;
case 4:
    // other stuff just for 4
    break;
default:
    // fallback for everything else
    break;

its also important to note that switch does loose comparison which might be undesired in certain scenarios

don't have too much to say from a performance point of view

Janek
switchs are generally faster than regular ifs
Alix Axel
is that across all programming or just with php? can you elaborate more as to why switches are faster?
Sneakyness
I agree with you, it looks neater and you can easily fetch a group if a certain criterium was found.
Ben Fransen
+1  A: 

Everyone but the novice programmer knows that a switch is faster than an if..else, but a switch can't replace every compound expression you might put in an if statement (such as two expressions with a logical AND)

Also, if you're talking about deeply nested code like this

function foo()
{
  if ( /* expr1 */ )
  {
    // code

    if ( /* expr2 */ )
    {
      // code 

      if (  /* expr3 */ )
      {
        // code
        if ( /* expr4 */ )
        {
          // code          
        }
      }
    }
  } 
}

Then all I can say is, please stop doing that. Have some guard conditions that will force the function to exit early instead. Here's the above re-written with this style.

function foo()
{
  if ( !/* exp r1 */ )
  {
    return;
  }
  // code 1

  if ( !/* expr 2 */ )
  {
    return;
  }
  // code 2

  if ( !/* expr 3 */ )
  {
    return;
  }
  // code 3

  if ( !/* expr 4 */ )
  {
    return;
  }
  // code 4
}

Of course, both of these in a real application could probably be refactored even better by adding more functions.

Peter Bailey
I've never quit took the approach from your second example, but it makes clear sense to me. Besides code becomes much more readable, especially when you are nested in 10 times or so. Btw, i didn't knew about the performance thing ;)
Ben Fransen
+1  A: 

I would say if you look at the three examples, the most beautiful and clean one is easy to pick: The switch statement. If you can live with switch's loose comparison, pick that. On that level, performance considerations are usually pointless as the potential gains are minuscule.

Pekka
I know the benefits are very little but if you know whats best for processing why not standard use it? Optimalization comes in bits, not chunks ;) All peaces must work together to get it 'smooth'.
Ben Fransen
I see what you mean but I don't share your view: You may save a few milliseconds, but your code will become harder to read and harder to maintain. In almost every application, there are usually bottlenecks that, when optimized, save the dozen- or hundredfold in processing time.
Pekka
+1  A: 

I usually prefer to use the neatest looking, most understandable method. However, I try and avoid ever needing to ask the question. Having to use a large amount of if/else blocks in your code indicates a problem with your design.
Given that it is easy to create associative arrays, there is no reason why you can't map a key to a function or value which will probably outperform switch statements for anything other than trivial data sets. Or even better use polymorphism which is a far neater solution and often turns a large if or switch block into a single function call.

Yacoby
Also a nice point you made by mapping functions into array. Correct me if I'm wrong but weren't arrays always read in the same speed, undependant of the location of an index?
Ben Fransen
Depending on the implementation, it may be closer to O(n log n) or even O(log n) rather than a linear search of O(n)
Yacoby
Obviously you have studied more math than me.. :/ I'm not into log.. ;)
Ben Fransen
+1  A: 

If you need these kind of micro-optimizations, you should use another language. As a lazy programmer, I like to go for this kind of things :

class blabla{
  private $_actions;
  public function __construct(){
    $this->_actions = array(1 => '_firstAction',
                            2 => '_secondAction',
                            3 => '_thirdAction');

  }
  public function whatever($choice){
    if(isset($this->_actions[$choice])){
      $this->{$this->_actions[$choice]}();
    }
  }
  private function _firstAction(){}
  private function _secondAction(){}
  private function _thirdAction(){}
}
Arkh
But doens't that kinda skrew up your code making it read-unfriendly?
Ben Fransen
For 2 or 3 different choices, it may seem less readable. But if you have 10 of them, I like my neat arrays a lot more than a big switch or if/else block.
Arkh
There you've got a point too ;) +1!
Ben Fransen