AS3: Multiple switch/case functions VS one big one - actionscript-3

I've got 3 different switch functions that have about 4 cases each. Would it really be so bad to jam all the cases into one big switch function instead? I know it would have to go through more cases that way until it found the proper one, but wouldn't the performance hit be negligible? I'm trying to cut down on needless code so I don't have to scroll through it so much. It would save on some function declarations as well.
To clarify, I have several functions where the user can choose something. Each of those functions has a corresponding handler that uses a switch statement to see what the user chose. I'm considering just using 1 handler instead that has all of the cases.

if you mean that.
if(x < 4)
{
switch(x)
{
case 0:
case 1:
case 2:
case 3:
}
}
else if(x < 8)
{
switch(x)
{
case 4:
case 5:
case 6:
case 7:
}
}
else
{
switch(x)
{
case 8:
case 9:
case 10:
case 11:
default:
}
}
it's better you make a big switch for all because of "code readability". That switch stuff doesn't effect on performance if you're just asking for 3 switches and 4 cases each... you don't need to do that for now...
I think that's really relative to your project. A complete relative discussion depends on project. You're the one who's gonna decide about that stuff.

Putting them into one switch statement is a better practice, if the condition is the same of course. SWITCH statement does not exist in the bytecode level, so if you use more SWITCH statements then the bytecode will be way longer. Check this article.

Related

what are `switch` statements for?

Switch statements: I know what they do - I use them so many times, as per convention normally when I want to do different stuff based on the value of an Enum, but now it just hit me: Why are we using it? What was its original purpose? I mean, this:
switch(myVar) {
case Foo:
doSomething();
break;
case Bar:
doSomethingElse();
break;
default:
justAnotherThing();
break;
}
Has the exact same behaviour as:
if(myVar == Foo) {
doSomething()
}else if(myVar == Bar) {
doSomethingElse();
}else {
justAnotherThing();
}
Plus if's lets you make inequality comparisons (>, <, !=) if you need it. The only case that I may find a switch more useful is when you don't use the break statement inside: but this happens not too often and I find it terrible on code-quality.
I really can't find any benefit of using switch over if... So why was it defined for?
Some languages allow inequality comparisons in switch statements as well, e.g. Visual Basic:
Select Case x
Case < 5
// ...
Case 7
// ...
Case 10 To 15
// ...
Case Else
// ...
End Select
Basically, yes, the switch can often be written as an if/else if ladder, with the distinction that switch compares one value against a number of comparison values, if/else if can do anything in every single branch. But even that isn't the case in all languages, e.g. in PowerShell a switch can do plenty of things that you usually have to use if for:
switch -Regex ($x) {
'^\d+$' {'Number'}
}
or
switch ($x) {
{ $_ is [int] -or $_ is [double] } {'Number'}
{ $_ is [string] } {'Text'}
}
Generally, however, switch is easier to read for the common case of comparing a single value against a finite set of options. Furthermore, it enables the compiler to do certain optimizations which are harder to analyse on if/else if, such as using binary search to determine the correct case instead of linear search, or even using a jump table or arithmetic. E.g. the following switch
switch (x) {
case 0:
// Do something with 0
break;
case 1:
// Do something with 1
break;
case 2:
// Do something with 2
break;
...
}
could be compiled into the equivalent of
Action[] actions = {
() => { /* Do something with 0 */ },
() => { /* Do something with 1 */ },
() => { /* Do something with 2 */ },
...
};
if (x >=0 && x <= n) {
actions[x]();
}
The simplicity and limitations of switch are helpful in this case for an optimizing compiler because there's much less to analyse to determine what the overall structure is trying to do.
There are other features (sometimes maybe of dubious value), such as Duff's device, or being able to fall through to other cases (or goto arbitrary other cases, which, e.g. C# allows).
You may just as well ask the question why we have if statements and loops instead of just using goto. Yes, structured programming constructs are, taken one by one, strictly inferior in what they can express, compared to the more general construct. But they are more readable, make the intent clearer, and tend to be safer and easier to maintain.
switch is a pretty low-level statement, in the sense that the code in the case statements is compiled into a continuous block of instructions in memory which is simply conditionally jumped into (depends on the language in question of course, modern high-level languages may behave quite different under the hood). That's also why you have the fall-through behaviour, once a starting address is determined simply all following instructions are executed unless broken out of.
So initially it was a very natural way to jump over or into a block of instructions. Many languages have adopted the switch statement, many likely due to familiarity, but many likely also because it is indeed rather readable for certain cases, e.g.:
switch (someComplicatedCalculation($foo, $bar)) {
case CONSTANT_A:
...
case CONSTANT_B:
...
...
}
That's a pretty succinct way to express this, especially if you're maybe also depending on the fall-through behaviour.
Of course, other languages have never adopted switch, e.g. Python, and require the use of if..elif..else instead. In the end you can write similar code using either language construct, it's up to you.

Successive success checks

Most of you have probably bumped into a situation, where multiple things must be in check and in certain order before the application can proceed, for example in a very simple case of creating a listening socket (socket, bind, listen, accept etc.). There are at least two obvious ways (don't take this 100% verbatim):
if (1st_ok)
{
if (2nd_ok)
{
...
or
if (!1st_ok)
{
return;
}
if (!2nd_ok)
{
return;
}
...
Have you ever though of anything smarter, do you prefer one over the other of the above, or do you (if the language provides for it) use exceptions?
I prefer the second technique. The main problem with the first one is that it increases the nesting depth of the code, which is a significant issue when you've got a substantial number of preconditions/resource-allocs to check since the business part of the function ends up deeply buried behind a wall of conditions (and frequently loops too). In the second case, you can simplify the conceptual logic to "we've got here and everything's OK", which is much easier to work with. Keeping the normal case as straight-line as possible is just easier to grok, especially when doing maintenance coding.
It depends on the language - e.g. in C++ you might well use exceptions, while in C you might use one of several strategies:
if/else blocks
goto (one of the few cases where a single goto label for "exception" handling might be justified
use break within a do { ... } while (0) loop
Personally I don't like multiple return statements in a function - I prefer to have a common clean up block at the end of the function followed by a single return statement.
This tends to be a matter of style. Some people only like returning at the end of a procedure, others prefer to do it wherever needed.
I'm a fan of the second method, as it allows for clean and concise code as well as ease of adding documentation on what it's doing.
// Checking for llama integration
if (!1st_ok)
{
return;
}
// Llama found, loading spitting capacity
if (!2nd_ok)
{
return;
}
// Etc.
I prefer the second version.
In the normal case, all code between the checks executes sequentially, so I like to see them at the same level. Normally none of the if branches are executed, so I want them to be as unobtrusive as possible.
I use 2nd because I think It reads better and easier to follow the logic. Also they say exceptions should not be used for flow control, but for the exceptional and unexpected cases. Id like to see what pros say about this.
What about
if (1st_ok && 2nd_ok) { }
or if some work must be done, like in your example with sockets
if (1st_ok() && 2nd_ok()) { }
I avoid the first solution because of nesting.
I avoid the second solution because of corporate coding rules which forbid multiple return in a function body.
Of course coding rules also forbid goto.
My workaround is to use a local variable:
bool isFailed = false; // or whatever is available for bool/true/false
if (!check1) {
log_error();
try_recovery_action();
isFailed = true;
}
if (!isfailed) {
if (!check2) {
log_error();
try_recovery_action();
isFailed = true;
}
}
...
This is not as beautiful as I would like but it is the best I've found to conform to my constraints and to write a readable code.
For what it is worth, here are some of my thoughts and experiences on this question.
Personally, I tend to prefer the second case you outlined. I find it easier to follow (and debug) the code. That is, as the code progresses, it becomes "more correct". In my own experience, this has seemed to be the preferred method.
I don't know how common it is in the field, but I've also seen condition testing written as ...
error = foo1 ();
if ((error == OK) && test1)) {
error = foo2 ();
}
if ((error == OK) && (test2)) {
error = foo3 ();
}
...
return (error);
Although readable (always a plus in my books) and avoiding deep nesting, it always struck me as using a lot of unnecessary testing to achieve those ends.
The first method, I see used less frequently than the second. Of those times, the vast majority of the time was because there was no nice way around it. For the remaining few instances, it was justified on the basis of extracting a little more performance on the success case. The argument was that the processor would predict a forward branch as not taken (corresponding to the else clause). This depended upon several factors including, the architecture, compiler, language, need, .... Obviously most projects (and most aspects of the project) did not meet those requirements.
Hope this helps.

Why use the switch statment instead of if else statments?

Switches seem so useless as they can be replaced with if-else statements, which can do much more than just match a char/int/enum etc. I can only think of one good use for a switch, and that would be for interpreting command line args.
What are some realistic uses for a switch statement?
There are a few cases where switch is more readable and comes in handy. Usually when you have grouping of options.
Here is one of them:
int numDays = 0;
int month = 2;
int year = 2010;
// find the number of days in the month
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if ( ((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0) )
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
There's two reasons to use a switch vs if/else, in my mind:
The compiler may be able to optimize for the switch better.
The switch statement more clearly expresses the logic of the code better. Specifically, the idea that you're taking a different branch depending on the value of something, rather than depending on more complicated logic. This is, by far, the more important reason to me.
You need to remember that switches are easier to maintain - a whole bunch of nested ifs and elses can quickly become a pain to maintain.
Switches allow for easier insertion of a new case.
I use switches when I am using an enum to dictate what actions my method should take. It helps when the actions are mutually exclusive.
Switches are optimized in many languages for certain contexts. Often when possible they create a jump table or even hash table. Really, when it's possible to use a switch, it's very likely going to perform better than the (logically) same code using if/else.
There are a number of situations, one that we have to deal with a lot is if you have a lot of options, the syntax is a bit more compressed, and sometimes is easier to read than a if/then syntax.
Although an argument can be made to go either way, I find that switches, in the case of multiple options is easier to read, maintain and understand. I also have used it in a factory pattern type situation, which helps to document.
I always use switches if I'm comparing the same variable for multiple values - a switch is a lot quicker to code (and easier to maintain) than a long if-elseif chain. Imagine changing the variable name, with a switch it'll be a single edit, with an if-elseif chain it'll be several.
Also, depending on the language of choice you can use the case fall through "feature" where as with the if-elseif chain you'd end up with duplicated code.
Switch statements are great for writing finite state machine,Click here to learn more about them
It's the proper way to use the language. It lets the compiler do some optimizations and makes the code easier to read by someone who isn't you.
Also, in some languages you can switch an enum, and the compiler will warn if you miss values (I think).
well you can remove breaks from a switch statement. That way you can have this:
CASE_A:
...
BASE_B
...
so that way you can have case_a combine all the other cases below it until it hits a break. Not as nice to do that with just ifs.
A couple of points:
Some languages let you switch on other value types, such as string (Coldfusion case in point)
A switch statement may very well be much easier code to read than a big block of if/elseif/else statements
In switch statements you can break at the end of a case or allow the code to continue processing further cases in the statement. This functionality allows you to easily model some rules that if/elseif/else statements would not let you do as easily.
As others mention, keep in mind compilers and engines have optimizers, and switch statements are optimized differently.
In the case of Perl, using the switch statement can significantly reduce the complexity of your code.
Just compare these two examples.
Using given/when:
use feature qw'switch';
my $num_days;
given( $month) {
when( [ 1,3,5,7,8,10,12 ] ){ $num_days = 31 }
when( [ 4,6,9,11 ] ){ $num_days = 30 }
when( 2 ){
$num_days = 29;
$num_days = 28 if $year % 4;
$num_days = 28 unless $year % 100;
$num_days = 29 unless $year % 400;
default{ print "Invalid month.\n" }
}
Using for as a replacement for the new ~~ (smart-match) operator.
my $num_days;
for( 1,3,5,7,8,10,12 ){
if( $month == $_ ){
$num_days = 31;
last;
}
}
for( 4,6,9,11 ){
if( $month == $_ ){
$num_days = 30;
last;
}
}
if( $month == 2 ){
$num_days = 29;
$num_days = 28 if $year % 4;
$num_days = 28 unless $year % 100;
$num_days = 29 unless $year % 400;
}
unless( defined $num_days ){
print "Invalid month.\n"
}
Seems to me that the main advantage of a switch is that it makes it immediately obvious to the reader that all the options depend on the same variable. You certainly could write an if/elseif/elseif block that accomplished the same thing, but then the reader would have to carefully check that indeed it is the same variable being tested every time.
There's also the nightmare maintenance scenario where you have a long if/elseif on the same variable and someone decides to change the variable name, and so he changes all of the if's ... except he misses one.
As others have pointed out, there's also the fact that the compiler can usually optimize it better.
Duff's Device. Its usefulness in modern times is debatable, but its awesomeness is not.
It helps readability - at a glance, I know that the decision for which block of code should run is based on different values of the same variable.
It may be easier for the compiler to turn a switch statement into a dispatch table than it would be to turn the equivalent if/else soup into a dispatch table. If (and only if) that's true, you should then have O(1) dispatch to the relevant code, instead of O(log n) (or O(n), if the if/else soup is badly written).
In some (although not all) cases it may also be easier to check that you've covered the necessary tests using switch than a wodge of if/else.
I prefer using a map to a switch in most cases.
if (actionMap.contains(choice)) {
Action a = actionMap.get(choice);
a.execute();
} else {
//do something else
}
But in cases where the choices are too complicated to turn into a map or when multiple actions might be taken a switch is better.
switch (choice) {
case 1: actionOne(); break;
case 2: if(actionOne()) {actionTwo()}; break;
case 3: if(!actionOne() && (actionTwo() > 1)) {actionThree()}; result = 7;break;
default: result = actionTwo();
}
Sadly, sometimes requirements are complicated. Switch is useful in those cases where is simplified version of nested if/else constrcts.
Don't ask a python programmer this question as the language doesn't have a switch statement and encourage the use of dictionaries instead.
To answer your question, I can think of one case where a switch statement is useful.
It is useful when the language / compiler / static analyzer can make sure that you're checking all cases. This works good with enums.
If you add another item to an enumeration, you can now get warnings in all of the places where you are doing a switch on that kind of enumeration telling you that you're missing a case.

What is the difference between IF-ELSE and SWITCH?

Can someone please explain this to me?
They are pretty similar but each has a few special features.
switch
switch is usually more compact than lots of nested if else and therefore, more readable
If you omit the break between two switch cases, you can fall through to the next case in many C-like languages. With if else you'd need a goto (which is not very nice to your readers ... if the language supports goto at all).
In most languages, switch only accepts primitive types as key and constants as cases. This means it can be optimized by the compiler using a jump table which is very fast.
It is not really clear how to format switch correctly. Semantically, the cases are jump targets (like labels for goto) which should be flush left. Things get worse when you have curly braces:
case XXX: {
} break;
Or should the braces go into lines of their own? Should the closing brace go behind the break? How unreadable would that be? etc.
In many languages, switch only accepts only some data types.
if-else
if allows complex expressions in the condition while switch wants a constant
You can't accidentally forget the break between ifs but you can forget the else (especially during cut'n'paste)
it accepts all data types.
The main difference is that switch despatches immediately to the case concerned, typically via an indexed jump, rather than having to evaluate all the conditions that would be required in an if-else chain, which means that code at the end of the chain is reached more slowly than code at the beginning.
That in turn imposes some restrictions on the switch statement that the if-else chain doesn't have: it can't handle all datatypes, and all the case values have to be constant.
IF else - IT is used for taking a decisions
Switch statement - It is used to test the value of the given variable against a list of case value .
Differences Between if-else and switch
Expression inside if statement decide whether to execute the statements inside if block or under else block. On the other hand, expression inside switch statement decide which case to execute.
If-esle statement checks for equality as well as for logical expression . On the other hand, switch checks only for equality.
The if statement evaluates integer, character, pointer or floating-point type or boolean type. On the other hand, switch statement evaluates only character or a integer datatype.
Sequence of execution is like either statement under if block will execute or statements under else block statement will execute. On the other hand the expression in switch statement decide which case to execute and if you do not apply a break statement after each case it will execute till the end of switch statement.
If expression inside if turn outs to be false, statement inside else block will be executed. If expression inside switch statement turn out to be false then default statements is executed.
It is difficult to edit if-else statements as it is tedious to trace where the correction is required. On the other hand it is easy to edit switch statements as they are easy to trace.
in one word we can say
switch acts a little bit faster than if else statement!!!
The difference between Switch and if-else statement is below:
This is the general syntax of if-else ladder:
if (condition1) { //Body of if }
else if (condition2) { //Body of if }
else if (condition3) { //Body of if }
else { //default if all conditions return false }
And this is the general syntax for switch:
switch ( variable )
{
case <variable value1>: //Do Something
break;
case <variable value2>://Do Something
break;
default: //Do Something
break;
}
The if-else ladder is of type strict condition check,
while switch is of type jump value catching.
Advantages of switch over if-else ladder:
A switch statement works much faster than equivalent if-else ladder. It is because compiler generates a jump table for a switch during compilation. Consequently, during execution, instead of checking which case is satisfied, it only decides which case has to be executed.
It is more readable and in compare to if-else statements.
A Clear difference:
The if...else statement checks whether the conditions in the parenthesis evaluates to true or false
The switch statement checks if the equality of the value in the parenthesis against the value of the case keyword evaluates to true.
Example
var a = 'hello'
Example - if...else
if(a == 'hello') {
print('right!')
} else if (a == 'hi')
print('left!')
} else {
print('wrong!')
}
Example - Switch
switch(a) {
case 'hello': // a == 'hello'
print('right!')
break // You should add this
case 'hi': // a == 'hi'
print('left!')
break
default: // this executes if no equality was met in the values above.
print('wrong!')
}
// If you are not sure of either of the parenthesis value or the
// case value or you want to make more complex conditioning, you can use `true`:
var age = 18:
switch(true) {
case age < "18": // 18 < 18 == false
print("under age!");
break;
case age == 18: // 18 == 18 == true
print("right age!");
break;
default:
print("18+!");
}
i think that main difference is that in if-else blocks we can test conditions.but does not go exactly in same way in switch

What is the best way to replace or substitute if..else if..else trees in programs?

This question is motivated by something I've lately started to see a bit too often, the if..else if..else structure. While it's simple and has its uses, something about it keeps telling me again and again that it could be substituted with something that's more fine-grained, elegant and just generally easier to keep up-to-date.
To be as specific as possible, this is what I mean:
if (i == 1) {
doOne();
} else if (i == 2) {
doTwo();
} else if (i == 3) {
doThree();
} else {
doNone();
}
I can think of two simple ways to rewrite that, either by ternary (which is just another way of writing the same structure):
(i == 1) ? doOne() :
(i == 2) ? doTwo() :
(i == 3) ? doThree() : doNone();
or using Map (in Java and I think in C# too) or Dictionary or any other K/V structure like this:
public interface IFunctor() {
void call();
}
public class OneFunctor implemets IFunctor() {
void call() {
ref.doOne();
}
}
/* etc. */
Map<Integer, IFunctor> methods = new HashMap<Integer, IFunctor>();
methods.put(1, new OneFunctor());
methods.put(2, new TwoFunctor());
methods.put(3, new ThreeFunctor());
/* .. */
(methods.get(i) != null) ? methods.get(i).call() : doNone();
In fact the Map method above is what I ended up doing last time but now I can't stop thinking that there has to be better alternatives in general for this exact issue.
So, which other -and most likely better- ways to replace the if..else if..else are out there and which one is your favorite?
Your thoughts below this line!
Okay, here are your thoughts:
First, most popular answer was switch statement, like so:
switch (i) {
case 1: doOne(); break;
case 2: doTwo(); break;
case 3: doThree(); break;
default: doNone(); break;
}
That only works for values which can be used in switches, which at least in Java is quite a limiting a factor. Acceptable for simple cases though, naturally.
The other and perhaps a bit fancier way you seem to sugges is to do it using polymorphism. The Youtube lecture linked by CMS is an excellent watch, go see it here: "The Clean Code Talks -- Inheritance, Polymorphism, & Testing" As far as I understood, this would translate to something like this:
public interface Doer {
void do();
}
public class OneDoer implements Doer {
public void do() {
doOne();
}
}
/* etc. */
/* some method of dependency injection like Factory: */
public class DoerFactory() {
public static Doer getDoer(int i) {
switch (i) {
case 1: return new OneDoer();
case 2: return new TwoDoer();
case 3: return new ThreeDoer();
default: return new NoneDoer();
}
}
}
/* in actual code */
Doer operation = DoerFactory.getDoer(i);
operation.do();
Two interesting points from the Google talk:
Use Null Objects instead of returning nulls (and please throw only Runtime Exceptions)
Try to write a small project without if:s.
Also in addition one post worth mentioning in my opinion is CDR who provided his perverse habits with us and while not recommended to use, it's just very interesting to look at.
Thank you all for the answers (so far), I think I might have learned something today!
These constructs can often be replaced by polymorphism. This will give you shorter and less brittle code.
In Object Oriented languages, it's common to use polymorphism to replace if's.
I liked this Google Clean Code Talk that covers the subject:
The Clean Code Talks -- Inheritance, Polymorphism, & Testing
ABSTRACT
Is your code full of if statements?
Switch statements? Do you have the
same switch statement in various
places? When you make changes do you
find yourself making the same change
to the same if/switch in several
places? Did you ever forget one?
This talk will discuss approaches to
using Object Oriented techniques to
remove many of those conditionals. The
result is cleaner, tighter, better
designed code that's easier to test,
understand and maintain.
A switch statement:
switch(i)
{
case 1:
doOne();
break;
case 2:
doTwo();
break;
case 3:
doThree();
break;
default:
doNone();
break;
}
Depending on the type of thing you are if..else'ing, consider creating a hierarchy of objects and using polymorphism. Like so:
class iBase
{
virtual void Foo() = 0;
};
class SpecialCase1 : public iBase
{
void Foo () {do your magic here}
};
class SpecialCase2 : public iBase
{
void Foo () {do other magic here}
};
Then in your code just call p->Foo() and the right thing will happen.
There's two parts to that question.
How to dispatch based on a value? Use a switch statement. It displays your intent most clearly.
When to dispatch based on a value? Only at one place per value: create a polymorphic object that knows how to provide the expected behavior for the value.
The switch statement of course, much prettier then all those if's and else's.
Outside of using a switch statement, which can be faster, none. If Else is clear and easy to read. having to look things up in a map obfuscates things. Why make code harder to read?
switch (i) {
case 1: doOne(); break;
case 2: doTwo(); break;
case 3: doThree(); break;
default: doNone(); break;
}
Having typed this, I must say that there is not that much wrong with your if statement. Like Einstein said: "Make it as simple as possible, but no simpler".
I use the following short hand just for fun! Don't try anyof these if code clearity concerns you more than the number of chars typed.
For cases where doX() always returns true.
i==1 && doOne() || i==2 && doTwo() || i==3 && doThree()
Ofcourse I try to ensure most void functions return 1 simply to ensure that these short hands are possible.
You can also provide assignments.
i==1 && (ret=1) || i==2 && (ret=2) || i==3 && (ret=3)
Like instad of writting
if(a==2 && b==3 && c==4){
doSomething();
else{
doOtherThings();
}
Write
a==2 && b==3 && c==4 && doSomething() || doOtherThings();
And in cases, where not sure what the function will return, add an ||1 :-)
a==2 && b==3 && c==4 && (doSomething()||1) || doOtherThings();
I still find it faster to type than using all those if-else and it sure scares all new noobs out. Imagine a full page of statement like this with 5 levels of indenting.
"if" is rare in some of my codes and I have given it the name "if-less programming" :-)
In this simple case you could use a switch.
Otherwise a table-based approach looks fine, it would be my second choice whenever the conditions are regular enough to make it applicable, especially when the number of cases is large.
Polymorphism would be an option if there are not too many cases, and conditions and behaviour are irregular.
The example given in the question is trivial enough to work with a simple switch. The problem comes when the if-elses are nested deeper and deeper. They are no longer "clear or easy to read," (as someone else argued) and adding new code or fixing bugs in them becomes more and more difficult and harder to be sure about because you might not end up where you expected if the logic is complex.
I've seen this happen lots of times (switches nested 4 levels deep and hundreds of lines long--impossible to maintain), especially inside of factory classes that are trying to do too much for too many different unrelated types.
If the values you're comparing against are not meaningless integers, but some kind of unique identifier (i.e. using enums as a poor man's polymorphism), then you want to use classes to solve the problem. If they really are just numeric values, then I would rather use separate functions to replace the contents of the if and else blocks, and not design some kind of artificial class hierarchy to represent them. In the end that can result in messier code than the original spaghetti.
Use a switch/case it's cleaner :p
switch statement or classes with virtual functions as fancy solution. Or array of pointers to functions. It's all depends on how complex conditions are, sometimes there's no way around those if's. And again, creating series of classes to avoid one switch statement is clearly wrong, code should be as simple as possible (but not simpler)
I would go so far as to say that no program should ever use else. If you do you are asking for trouble. You should never assume if it's not an X it must be a Y. Your tests should test for each individually and fail following such tests.
In OO paradigm you could do it using good old polymorphism. Too big if - else structures or switch constructs are sometimes considered a smell in the code.
The Map method is about the best there is. It lets you encapsulate the statements and breaks things up quite nicely. Polymorphism can complement it, but its goals are slightly different. It also introduces unnecessary class trees.
Switches have the drawback of missing break statements and fall through, and really encourage not breaking the problem into smaller pieces.
That being said: A small tree of if..else's is fine (in fact, i argued in favor for days about have 3 if..elses instead of using Map recently). Its when you start to put more complicated logic in them that it becomes a problem due to maintainability and readability.
In python, I would write your code as:
actions = {
1: doOne,
2: doTwo,
3: doThree,
}
actions[i]()
I regard these if-elseif-... constructs as "keyword noise". While it may be clear what it does, it is lacking in conciseness; I regard conciseness as an important part of readability. Most languages provide something like a switch statement. Building a map is a way to get something similar in languages that do not have such, but it certainly feels like a workaround, and there is a bit of overhead (a switch statement translates to some simple compare operations and conditional jumps, but a map first is built in memory, then queried and only then the compare and jump takes place).
In Common Lisp, there are two switch constructs built in, cond and case. cond allows arbitrary conditionals, while case only tests for equality, but is more concise.
(cond ((= i 1)
(do-one))
((= i 2)
(do-two))
((= i 3)
(do-three))
(t
(do-none)))
(case i
(1 (do-one))
(2 (do-two))
(3 (do-three))
(otherwise (do-none)))
Of course, you could make your own case-like macro for your needs.
In Perl, you can use the for statement, optionally with an arbitrary label (here: SWITCH):
SWITCH: for ($i) {
/1/ && do { do_one; last SWITCH; };
/2/ && do { do_two; last SWITCH; };
/3/ && do { do_three; last SWITCH; };
do_none; };
Use a Ternary Operator!
Ternary Operator(53Characters):
i===1?doOne():i===2?doTwo():i===3?doThree():doNone();
If(108Characters):
if (i === 1) {
doOne();
} else if (i === 2) {
doTwo();
} else if (i === 3) {
doThree();
} else {
doNone();
}
Switch((EVEN LONGER THAN IF!?!?)114Characters):
switch (i) {
case 1: doOne(); break;
case 2: doTwo(); break;
case 3: doThree(); break;
default: doNone(); break;
}
this is all you need! it is only one line and it is pretty neat, way shorter than switch and if!
Naturally, this question is language-dependent, but a switch statement might be a better option in many cases. A good C or C++ compiler will be able to generate a jump table, which will be significantly faster for large sets of cases.
If you really must have a bunch of if tests and want to do different things whenwver a test is true I would recommend a while loop with only ifs- no else. Each if does a test an calls a method then breaks out of the loop. No else there's nothing worse than a bunch of stacked if/else/if/else etc.