Structuring an if-else clause inside a for loop [closed]

  softwareengineering

Suppose I am doing an if-else clause inside a for loop. I like to structure it as

for (...)
    if (...)
        // (part A)
        continue;
    //(part B)

rather than

for (...)
    if (...)
        // (part A)
    else
        (part B)

but I can imagine that coders might have strong opinions on this. Is there a standard? Apologies if this has been asked; I couldn’t find it.

3

Restating the context

Apologies if this has been asked; I couldn’t find it.

That might have to do with the fact that you’re thinking about loops, where this is not really about loops. In both your examples, the loop part (for (...)) is exactly the same, while the difference is only inside that loop. Just to show more clearly what I mean, lets move the relevant bits out of the loop (plus adding brackets to make more clear what belongs to what):

// The loop ===
for (...) {
    DoThing();
}


// Option A ===
void DoThing(){
    if (...){
        // (part A)
        return; // "continue;" becomes "return;"
    }
    // (part B)
}


// Option B ===
void DoThing(){
    if (...){
        // (part A)
    }
    else {
        // (part B)
    }
}

So what your question comes down to is “early return vs. else”.

Answering the question in that context

Is there a standard?

Well, there is not a standard. There are several. The two options you presented are 2 different standards. You’d think that was it, but there’s advocates for a third one, else AND return:

int max(int a, int b)
{
    if (a > b)
        return a;
    else
        return b;
}

Those are all valid, they all work.

What to do?

My advice would be to favour early returns. It can greatly reduce visual clutter and for that reason seems to be preferred by the majority of programmers here on software engineering as well as on stackoverflow (1, 2). There are also numerous blogs etc. advocating that style (1, 2, 3), but honestly, they’re all just reiterating the same point.

Guidelines, not rules

Even if you say for yourself “I will use early returns”, every “rule” in software engineering comes with the implicit adage “…except if you have a good reason (not) to do that.

For example, for small statements it’s often easier to read

if(condition) DoThingA();
else DoThingB();

than

if(condition){
    DoThingA();
    return;
}
DoThingB();

So, why not just use else then? It’s better to not restrict yourself here.

3

No, there is no “standard.” That’s why you can’t find it. The loop structure you use will depend entirely on your specific program logic and requirements. Use continue when your program logic dictates that you should abandon a loop iteration early.

In general, you would use continue or break when you determine that your work is done in that loop or loop iteration. For example, a search loop would break when the item being searched is actually found, since any further work in that loop only serves to chew up clock cycles unnecessarily.

Questions that ask “is there a ‘standard’ for [some ordinary piece of work]” often labor under the incorrect assumption that there is one right/true/correct/best way to do everything. There isn’t. Even if there were, it won’t be the “correct” way five years from now, or maybe even five minutes from now.

Software development is not a pattern-matching exercise. Instead of asking yourself what is the “standard” way to do something, ask yourself if it suits your purpose.

6

There are many ways to achieve the same result using different language features. Then you should choose the version that most clearly shows your intent – it’s all about readability.

Using “else” vs. early-abort

Use else to express “There are two similarly-ranked alternatives”.

If the two branches created by an if condition are comparable in rank / probability, I prefer to have both indented (placed in its own sub-block), using else in-between.

If one branch is a special situation allowing an early abort of the main control flow, and the other branch is the normal continuation, then I prefer an early-abort keyword like break, return or continue, depending on the context. This way, the normal continuation stays on the same indentation level as the code before the condition, indicating that it’s the normal sequence of steps.

Early-abort using “return”

Use return to express “I’m finished (early) with this function”.

This one is very popular, because it’s easily understood. If you see the return keyword, you know that this leaves the currently-executing method. You don’t have to search for the place where to continue. I use this quite often.

Early-abort using “break”

Use break to express “I’m finished (early) with this loop”.

This leaves the currently-executing loop. It’s not that easily readable: you have to look for the next enclosing for / while / do-while loop, and you should keep in mind that none of the looping elements (e.g. i<10 or i++) is executed any more (ok, you’d expect that).

Early-abort using a labeled “break” (Java)

Use break label to express “I’m finished (early) with the named block”.

This is valid only inside a block with that label. There aren’t many situations where you’d need that, so it’s quite unusual to such a degre that many developers don’t even know that this construct exists. To understand the code, you have to search backwards for the label, and then skip the block forward to reach the continuation point.

Early-abort using “continue”

Use continue to express “I want to immediately jump to the next iteration”.

This leaves the currently-executing loop iteration. It’s not easily readable: you have to look for the next enclosing for / while / do-while loop, and you should keep in mind that the looping elements (e.g. i++ and i<10) are executed before the next iteration starts. I’ve rarely used that.

So, choose the one that best expresses the intent of the conditional situation.

LEAVE A COMMENT