If-fu or the Art of Using If Statements

Writing complex if -statements without taking the readability aspect of the code in to the consideration will lead you quickly in despair. However, here are a few tips how you can write if -statements that are readable.

The basic idea of writing easily readable if -statements is to use the State Machine -metaphore. The idea is that you model the function as a simple state transition diagram. There are two basic ways to write a simple state machine: the negative and positive.

1. The Wrong Way ™

Here is a very common, but also a very uncomprehensible spaghetti -convention to write ifs like this:

function wrongWayIf() {
    if (failureCondition1) {
        return false;
    } else if (failureCondition3) {
        if (failureCondition2) {
          return true;
        } else {
          //do something else
        }
    }
}

2. Positive Flat If State Machine

A better idea is to use flat if-structure and a state machine -paradigm. An even better idea is to use pure Object Orientation :). But if you still want to use ifs, try to omit the usage of elses and use the following two coding conventions. The idea of the positive If State Machine is to behave like a validator – you look look for conditions that causes the validation filter to fail. Finally, if you passed all filters, you return a success.

function positiveIf() {
    if (failureCondition1) {
        return false;
    }
    if (failureCondition2) {
        return false;
    }
    //finally if nothing matches - success
    return true;
}

3. Negative Flat If State Machine

The idea of the Negative If State Machine is to look for conditions where you can bail out immidiately. You should place the most common condition as the first, and then gradually iterate through more exotic conditions. This way you can linearize the decision tree, which would look like a uncomprehensible monster, if you’d use hierarchical if-else -statements. From the performance point of view you can also optimize your code this way by analyzing, which condition is the most common, and bail out first the most common cases. You can also leave the more performance heavy operations to the latter part of your if -case list.

function negativeIf() {
    if (successCondition1) {
        //found a match, so bail out!
        return true;
    }
    if (successCondition2) {
        return true;
    }
    //finally fail if nothing matches - fail by default
    return false;
}

4. Complete State Machine Design Architecture

Instead of writing if statements in the wrong way (deep if-else -spaghetti), model your state machine instead of a network of multiple simple state machines inside one class. You can write the state transitions even on a paper or as an UML chart, so you keep track what is going on:

class MyStateMachine {
    function begin() {
        if (condition1) {
            positiveIf();
        }
        if (condition2) {
            negativeIf();
        }
       return end();
    }
//etc....
}

The idea of an object is to hold a state, which should be changed only by the accessors. However, sometimes you need to make a complex stateful object and the state machine is the next best alternative.

I hope this helps you in getting ideas about how to write more comprehensive stateful code 🙂