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...

A World without Else

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:

  1. Testing - this code has to be unit tested;
  2. Tracing - this code has to be supported;
  3. 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:

  1. check for the "negative condition";
  2. if found, I return or set a sentry variable;
  3. 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 -

#redgreenblue
1falsefalsefalse
2falsefalsetrue
3falsetruefalse
4falsetruetrue
5truefalsefalse
6truefalsetrue
7truetruefalse
8truetruetrue

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.

Read more