This is a misleading assumption. Removing else
statement does not make the code cleaner. It just increases the risk of mistakes.
For a detailed discussion, see for example the recommendation MSC01-C from the CERT C secure coding standard, which explains that the code should strive for logical completeness, as vulnerabilities can result when failing to consider all the possible alternatives. In this regard, the else
visibily demonstrates that you have considered them.
Proof by contradiction
Let's have a look at your code, and see how you could avoid the else
. The systematic approach is to llok at the possible execution graphs and regorganize them to produce an equivalent graph.
A first approach is to add a conditional for the contrary:
if (enable) {
TurnOnAllLights();
SetValueOnAllLights(1);
}
if (!enabled) { // ====> OUCH ! super risky
TurnOffAllLights();
}
Rewriting the code like that removes the else
, but it is super risky. Not in your small snippet, but in real-world if
statements, in the case where the first if-block would change the value of enabled
, which will result in both blocks being run instead of one of the two.
A second approach is to use a premature return
if (enable) {
TurnOnAllLights();
SetValueOnAllLights(1);
return; // ===> HORRIBLE IN THIS CASE
}
TurnOffAllLights();
It's not always bad to prematurely return. But in this case it is it is: it requires more brainpower to understand that it's just about an alternative. Moreover, you may multiply unnecessarily function exit points, which is not a very popular nor effective practice either. Furthermore, how would you do if you'd still have a common part of code to run after the else? Copy-paste it and repeat yourself with all the risks that it represents for the future?? This is especially tricky if this additional ode would be added later, bearing the significant risk of forgetting it in one of the branch.
Now the finale, the return to the good old GOTO; really?
if (enable) {
TurnOnAllLights();
SetValueOnAllLights(1);
goto GREAT_SPAGHETTI_CONTINUES;
}
TurnOffAllLights();
GREAT_SPAGHETTI_CONTINUES: // OUCH!
//...
}
I'll not analyse this snippet, but just remind that it took a decade to get rid of problem-solving-by-adding-another-goto, to finally discover the virtues of structured programming. Let's not go back to wild-goto age. Again, there are cases, where the use of goto could be discussed, but avoiding the else
definitively isn't.
If you could change more than the control flow
I cannot resist but to delegate the setting of the light to a single function:
TurnAllLights(enabled); // incl.responsibility for setting value correctly