views:

793

answers:

8

What is the better practice of the following two switch/case statements?

Is there an easier way (less code) to do this?

switch (myValue)
{
    case 1:
    {
        methodFor1();

        break;
    }
    case 2:
    case 3:
    {
        methodFor2or3();

        if (myValue == 2)
                methodFor2();

        if (myValue == 3)
                methodFor3();

        break;
    }
}

...or...

switch (myValue)
{
    case 1:
    {
        methodFor1();

        break;
    }
    case 2:
    case 3:
    {
        methodFor2or3();

        switch (myValue)
        {
            case 2:
            {
                methodFor2();

                break;
            }
            case 3:
            {
                methodFor3();

                break;
            }
        }

        break;
    }
}
+2  A: 

One more alternative:

switch (myValue)
{
    case 1:
    {
        methodFor1();
        break;
    }
    case 2:
    {
        methodFor2or3();
        methodFor2();
        break;
    }
    case 3:
    {
        methodFor2or3();
        methodFor3();
        break;
    }
}
Pukku
+6  A: 
switch (myValue)
{
  case 1:
    methodFor1();
    break;
  case 2:
    methodFor2or3();
    methodFor2();
    break;
  case 3:
    methodFor2or3();
    methodFor3();
    break;
}

Why all the hassle just to avoid repeating methodFor2or3() once?

Tomalak
And by the way - excess empty lines *really* hurt readability.
Tomalak
This is the most readable, and thus, the most maintainable.
Eddie
Note, in the example given, methodFor2or3 is called /before/ methodFor2 or methodFor3. But the point is well taken.
Adam Bellaire
@Adam Bellaire: You are right. Personally, I would not expect calling order to be an issue for separate functions. I would rather consider it a code smell and would completely refactor it.
Tomalak
@Tomalak: That is a very dangerous assumption. What if methodFor2or3() was prepareForProcessing() and methodFor2() was process2() and methodFor3() was process3()??
Software Monkey
Personally, I would quite likely call methodFor2or3 at the start of method2 and method3.
Software Monkey
@Software Monkey: It's just a sample, after all. If certain preparation was absolutely necessary before some function can run, I would factor preparation into that function (or pack the two calls into a third function). Otherwise it would be "relying on side effects", which isn't good style, IMHO.
Tomalak
Nevertheless - I've changed calling order to match the original question. The question was not about calling order, so the answer should not provide a red herring in this regard. :-)
Tomalak
A: 

If there is only one (fairly simple) line in common between the two cases (as the function call in your example), then I prefer to double that line just for the sake of better readability. Otherwise, it's a matter of taste. I tend to prefer if conditions inside the case statements, because that way you can't confuse the various levels.

David Hanak
+2  A: 

Since functions are first class objects in actionscript3, you could build a hash of values to functions, like so:

var myDict:Dictionary = new Dictionary(); 
myDict[1] = methodFor1; 
myDict[2] = methodFor2;


function handleStuff(myVal:Number):void{
    var myFunction:Function = myDict[myVal];
    myFunction();
}

hope this helps!

inkedmn
+1  A: 

How about something more like:

var method:String = "methodFor" + String(value);
this[method]();
if (value == 3) methodFor2or3();

You might think of splitting out the or3 call if it's simpler code you want:

switch (value) {
    case 1: methodFor1(); break;
    case 2: methodFor2(); break;
    case 3: methodFor3(); break;
}
if (value == 2 || value == 3) methodFor2or3();
Typeoneerror
A: 

When you're dealing with programming flow of control issues, "less code" isn't really the attribute you want to optimize on. It's far better with structural issues to bend your code towards being simple and readable.

So for the above, the first option isn't bad, although the 'flow-through' case for 2 can easily be missed. Better is to just do the parent switch on a 1 or 2, then in the second case call another function that handles the sub-cases (formally 2 and 3), and make this driven by a different (sub-case) variable (to insure that you're not overloading the 'meaning' of the initial 'value' variable.

Philosophically, all three cases are part of the same switch, OR they are not. If they are, then they should be treated equally (and indistinguishably from each other). If they are not, then they should be driven by two separate variables and handled in two separate functions. Trying to save 'bandwidth' by combining them complicates thing unnecessarily.

Paul.

Paul W Homer
Actually, I prefer "less code" for readability. Readability is extremely important to me, because I'm sick and tired of looking at crap code written by my predecessors at every job I've had.
Eric Belair
The problem with "less code" is that as an objective, it ultimately leads one to stuff like the obfuscated C contest (or APL). If you always program like you're making examples for a textbook, the results are better.
Paul W Homer
A: 

I am answering assuming that you know the example case you gave is contrived and is better written in other ways. If you just want to know if it's best to nest switches or to use if-else within a switch, it totally depends on taste and the individual situation.

In my opinion, the fact that your block is inside a switch makes no difference. If the logic would be better served by a switch, use a switch (nested or not). If it would be better served by an if-else, use that.

Adam Bellaire
+1  A: 

In my programming of switch statements, I aim for making each case have at most one line of code + a break;. This is because switch can quickly get big and complicated, and my brain isn't good at complicated.

So, in your case, I would write:

switch (myValue)
{
    case 1:
    {
        methodFor1();
        break;
    }
    case 2:
    {
        methodFor2();
        break;
    }
    case 3:
    {
        methodFor3();
        break;
    }
}

and then make methodFor2 and methodFor3 each call methodFor2or3.

Jay Bazuzi