A World without Else
Your goal as a developer is not just to write code. It is to write good code. Best code I've written is simple and elegant. This is one of my key techniques...
Every developer probably has an eccentricity. One of mine's is that I strongly dislike else statements - probably because of code like the following. Regrettably, this code sample is i) real and ii) is a subset of the actual code - I counted 12 else statements.
} else {
cb(null, finalResponse);
return;
}
} else {
cb(null, finalResponse);
return;
}
} else {
cb(null, finalResponse);
return;
}
} else {
cb(null, finalResponse);
return;
}
}
} else {
cb(null, finalResponse);
return;
}
} else {
cb(null, finalResponse);
return;
}
} else {
cb(null, finalResponse);
return;
}
This is not due to developer laziness. On the contrary, any developer who can keep track of the state of these cascading else statements is working 12x harder. However, can you imagine the difficulty in:
- Testing - this code has to be unit tested;
- Tracing - this code has to be supported;
- Maintaining - God help the poor soul who has to change any logic
Don't get me wrong - I am not an else bigot. I just hate it when they get into a group (like the code above) and start to terrorise Developers, Testers and Ops Support.
My method for avoiding situations like the above is to:
- check for the "negative condition";
- if found, I return or set a sentry variable;
- whatever "survives" is the "positive condition" and you continue
Take the following scenario:
- boolean variable red;
- boolean variable green;
- boolean variable blue;
If I recall my high-school 2's complement correctly, there are 8 possible combinations -
# | red | green | blue |
---|---|---|---|
1 | false | false | false |
2 | false | false | true |
3 | false | true | false |
4 | false | true | true |
5 | true | false | false |
6 | true | false | true |
7 | true | true | false |
8 | true | true | true |
So, let us write this with else..
if (red === false) {
if (green === false) {
if (blue === false) {
/* red = false; green = false, blue = false */
console.log('1');
}
else {
/* red = false; green = false, blue = true */
console.log('2');
}
}
else {
if (blue === false) {
/* red = false; green = true, blue = false */
console.log('3');
}
else {
/* red = false; green = true, blue = true */
console.log('5');
}
}
}
else {
if (green === false) {
if (blue === false) {
/* red = true; green = false, blue = false */
console.log('4');
}
else {
/* red = true; green = false, blue = true */
console.log('6');
}
}
else {
if (blue === false) {
/* red = true; green = true, blue = false */
console.log('7');
}
else {
/* red = true; green = true, blue = true */
console.log('8');
}
}
}
Now, lets try that without else...
if (red === false) {
if (green === false) {
if (blue === false) {
/* red = false; green = false, blue = false */
console.log('1');
return;
}
/* red = false; green = false, blue = true */
console.log('2');
return;
}
if (blue === false) {
/* red = false; green = true, blue = false */
console.log('3');
return;
}
/* red = false; green = true, blue = true */
console.log('5');
return;
}
if (green === false) {
if (blue === false) {
/* red = true; green = false, blue = false */
console.log('5');
return;
}
/* red = true; green = false, blue = true */
console.log('6');
return;
}
if (blue === false) {
/* red = true; green = true, blue = false */
console.log('7');
return;
}
/* red = true; green = true, blue = true */
console.log('8');
return;
Or, if we really applied our minds, we could come up with something elegant like the following:
var _number = (4 * (red ? 1 : 0)) + (2 * (green ? 1 : 0)) + (1 * (blue ? 1 : 0)) + 1;
console.log(_number);
The next time you have a number of variables and permutations to handle, stop and think before you dive in. Although the first solution might get you out the gate faster, it might actually take longer to deliver and might be harder to support/maintain in the future.
EDIT: Special thanks to Waseem Ahmed for poring over the code and his suggestions to make it even easier to understand.