Loop-switch sequence

From Infogalactic: the planetary knowledge core
Jump to: navigation, search

A loop-switch sequence (also known as the for-case paradigm[1] or Anti-Duff's Device) is a programming antipattern where a clear set of steps is implemented as a switch-within-a-loop. The loop-switch sequence is a specific derivative of spaghetti code.

It is not necessarily an antipattern to use a switch statement within a loop—it is only considered incorrect when used to model a known sequence of steps. The most common example of the correct use of a switch within a loop is an inversion of control such as an event handler. In event handler loops, the sequence of events is not known at compile-time, so the repeated switch is both necessary and correct (see event-driven programming, event loop and event-driven finite state machine).

Note that this is not a performance antipattern, though it may lead to an inconsequential performance penalty due to the lack of an unrolled loop. Rather, this is a clarity antipattern, as in any non-trivial example, it is much more difficult to decipher the intent and actual function of the code than the more straightforward refactored solution.

Example

An event-driven solution would implement a listener interface:

String key = null;
String value = null;
List<String> params = null;
int column = 0;

public void addToken(token) {

    // parse a key, a value, then three parameters 
    switch (column) {
        case 0:
            params = new LinkedList<String>();
            key = token;
            break;
        case 1:
            value = token;
            break;
        default:
            params.add(token);
            break;
    }
    if (++column >= 5) {
        column = 0;
        completeRow(key, value, params);
    }
}

But without the listener, it becomes an example of the antipattern:

// parse a key, a value, then three parameters 
String key = null;
String value = null;
List<String> params = new LinkedList<String>();

for (int i = 0; i < 5; i++) {
    switch (i) {
        case 0:
            key = stream.parse();
            break;
        case 1:
            value = stream.parse();
            break;
        default:
            params.add(stream.parse());
            break;
    }
}

And here is the refactored solution:

// parse a key and value
String key = stream.parse();
String value = stream.parse();

// parse 3 parameters
List<String> params = new LinkedList<String>();
for (int i = 2; i < 5; i++) {
    // in practice, that might be written as (i = 0; i < 3; i++),
    // but for illustration we use the same range of indices here
    // as in the switch above; the fact that the loop body does
    // not actually use the value of i proves that the
    // loop-and-switch construct was superfluous in the example above.
    params.add(stream.parse());
}

References

  1. The FOR-CASE paradigm and Switched on Loops at The Daily WTF