Why is "else" rarely used after "if x then return"?

JavaCoding StyleIf StatementFunction Exit

Java Problem Overview


This method:

boolean containsSmiley(String s) {
    if (s == null) {
        return false;
    }
    else {
        return s.contains(":)");
    }
}

can equivalently be written:

boolean containsSmiley(String s) {
    if (s == null) {
        return false;
    }

    return s.contains(":)");
}

In my experience, the second form is seen more often, especially in more complex methods (where there may be several such exit points), and the same is true for "throw" as well as "return". Yet the first form arguably makes the conditional structure of the code more explicit. Are there any reasons to prefer one over the other?

(Related: Should a function have only one return statement?)

Java Solutions


Solution 1 - Java

The else in that case would be redundant, as well as create unnecessary extra indentation for the main code of the function.

Solution 2 - Java

In my experience, it depends on the code. If I'm 'guarding' against something, I'll do:

if (inputVar.isBad()) {
    return;
}

doThings();

The point is clear: If that statement is false, I don't want the function to continue.

On the other hand, there are some functions with multiple options, and in that case I would write it like this:

if (inputVar == thingOne) {
    doFirstThing();
} else if (inputVar == secondThing) {
    doSecondThing();
} else {
    doThirdThing();
}

Even though it could be written as:

if (inputVar == thingOne) {
    doFirstThing();
    return;
}
if (inputVar == thingTwo) {
    doSecondThing();
    return;
}
doThingThree();
return;

It really comes down to which way most clearly shows what the code is doing (not necessarily which bit of code is shortest or has the least indentation).

Solution 3 - Java

This is a pattern called Guard Clause. The idea is do all the checking upfront to reduce nested conditions to increase readability.

From the link:

double getPayAmount() {
    double result;
    if (_isDead) {
        result = deadAmount();
    } else {
        if (_isSeparated) {
	        result = separatedAmount();
	    } else {
	        if (_isRetired) {
	            result = retiredAmount();
	        } else {
                result = normalPayAmount();
	        }
	    }
    }
    
    return result;
}

Using the Guard Clause, you'll get to see this result:

double getPayAmount() {
    if (_isDead) return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetired) return retiredAmount();
    
    return normalPayAmount();
};

Solution 4 - Java

You will see this all over:

if (condition) {
    return var;
}
// by nature, when execution reaches this point, condition can only be false,
// therefore, the else is unnecessary
return other_var;

Most of the time the addition of an else clause is not only unnecessary in this case, but a lot of times, it gets optimized away by the compiler.

Think of how the computer thinks of this code (in terms of machine code, simplified into pseudocode here for demonstration purposes):

0x00: test [condition]
0x01: if result of test was not true, goto [0x04]
0x02: push [var] onto stack
0x03: goto [0x05]
0x04: push [other_var] onto stack
0x05: return from subroutine

The code (again, this is a pseudocode and not assembly) would act the exact same way for an if/then/else conditional.

It is, by many people, considered bad and/or confusing practice to have multiple possible exit points for a function, as a programmer must think of every possible path through his code. Another practice is the following:

return (condition) ? var : other_var;

This simplifies the code, and does not create any new exit points.

Solution 5 - Java

I prefer writing it like this:

boolean containsSmiley(String s) {
    return s != null && s.contains(":)");
}

Solution 6 - Java

The else is redundant. Also some IDEs (Eclipse) and analysis tools (maybe FindBugs) may flag that as a warning or an error, so in that case programmers are likely to remove it.

Solution 7 - Java

Like any "discussion" about coding styles there is no correct answer. I prefer to apply these considerations:

  1. Does the code work as expected in all situations. (Principle of least surprise)

  2. Can the next developer (myself or someone else) understand what it is doing and why.

  3. How fragile is the code with respect to change.

  4. Is is simple as it needs to be and no more. I.e. no over or under engineering.

Once I'm happy that I have satisfied the above, the rest generally just falls falls into line.

Solution 8 - Java

I would prefer the first option, as it is more human-readable.

As an analogy, compare the next 2 sentences: "If today is raining, then take an umbrella, else take sunglasses." and "If today is raining, then take an umbrella, take sunglasses". The first sentence corresponds to the first block of code from the question, the second one – to the second. The first one is much more clear and readable, isn't it?

Solution 9 - Java

Someone else probably noted this already, but I'd recommend against using null values in general where strings are expected. If you really want a check to prevent someone passing null values, you can use asserts (at dev time) or unit tests (deploy):

boolean containsSmiley(String s) {
    assert s != null : "Quit passing null values, you moron.";
    return s.contains(":)");
}

I've switched to a general rule of thumb: Never. Ever. pass null values, unless an external API calls explicitly asks for it. Second: If an external method may return null values, replace it with a sensible non-null value (such as an empty string) or add a neat check. I grow sick of repetitive if (thing == null) checks.

But that's a bit offtopic. I like putting short conditions on top and guard clauses, removing elses if program flow dictates it'll never get there.

Solution 10 - Java

It's religious argument and at the end of the day it doesn't matter. I'd even argue that the first form is more readable in some circumstances. If you have large chunks of code in an if-elseif-elseif-else, it's easier, at first glance to see what the default return is.

if (s == null) {
    return false;
}
else if (s.Contains(":))")) {
    return true;
}
else if (s.Contains(":-(")) {
    return false;
}

return s.contains(":)");

Solution 11 - Java

Occam's Razor is the principle that "entities must not be multiplied beyond necessity."

Solution 12 - Java

The if statement is checking/enforcing your contract/expectation of not receiving null values. For that reason, I would prefer to see it separated from the rest of the function as it doesn't have anything to do with the actual logic of what you're trying to accomplish (though this case is very simple).

In most cases, though, I prefer code to be as explicit as possible in its intent. If there's something that you can restructure about your function to make it more readable for others, do it. As a professional programmer, your goal should really be to program for those who have to maintain your code after you (including yourself 2 years later...). Anything you can do to help them out is worth doing.

Solution 13 - Java

Cause it's nicer. You know you could also use '{' '}' to create several levels of nesting, but nobody really does it for just the heck of it.

Solution 14 - Java

While having an else is correct and there's nothing wrong with it in terms of logic and runnability, I like to avoid the initial WTF moment when the function has no return statement outside of the if/else scope.

Solution 15 - Java

The first form is simply less verbose - when you return a value you automatically leave the scope of the function you're in and return to the caller, so any of the code thereafter will only execute if the IF statement doesn't evaluate to true and subsequently return anything.

Solution 16 - Java

I'd argue for readability. If you're scanning screens of code trying to figure out what the code does, it's a visual prompt to the developer.

...but it's not really needed because we all comment our code so well, right? :)

Solution 17 - Java

In my opinion, the second one makes more sense. It serves as more of a 'default' action, like a switch. If it doesn't match any of the other exit points, then do that. You don't really need an else there. I would say if the entire function is only if and elseif, then an else would make sense there because it's one giant conditional. If there's multiple conditionals and other functions that are run within it, then a default return at the end would be used.

Solution 18 - Java

As you can see, different people have different opinions on readability. Some people think that fewer lines of code tends to make the code more readable. Others think that the symmetry of the second form makes it more readable.

My take is that probably, both views are correct ... for the people who hold them. And the corollary is that you cannot write code that everyone finds optimally readable. So, the best advice is to follow what your mandated coding standard says to do (if it says anything on this) and generally use your common sense. (If you are burdened with some vociferous nitwit that insists that his way is "right" ... just go with the flow.)

Solution 19 - Java

Because there is an optional (switched off by default) warning in eclipse if else is used in such situation ;).

Solution 20 - Java

Well, some of the reason is just convention, but there is one advantage to the form above...

It's typical when coding a return statement, to make the last statement your default return value. This primarily aids during refactoring - else clauses tend to get wrapped up in other structures, or might accidentally be moved deeper into the tree.

Solution 21 - Java

I would prefer one exit point over multiple from maintenance perspective. Final result can be modified(or decorated) at one exit point rather than n exit points.

Solution 22 - Java

The second form if simpler/shorter. This doesn't always mean clearer. I suggest you do what you find clearest.. Personally I would write.

static boolean containsSmiley(String s) { 
    return s != null && s.contains(":)"); 
} 

Solution 23 - Java

Because it's the same as writing one of the following which brings the evidence about the intention of the programmer:

boolean containsSmiley(String s) {
    if (s == null)   // The curly braces are not even necessary as the if contains only one instruction.
        return false;

    return s.contains(":)");
}

Or even this:

boolean constainsSMiley(String s) {
    return string.IsNullOrEmpty(s) ? false : s.Contains(":)");
}

These two forms are:

  1. More elegant;
  2. Easier to read;
  3. Leaner and swifter for the reading programmer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTodd OwenView Question on Stackoverflow
Solution 1 - JavaDelan AzabaniView Answer on Stackoverflow
Solution 2 - JavaBrendan LongView Answer on Stackoverflow
Solution 3 - JavaEugene YokotaView Answer on Stackoverflow
Solution 4 - JavaamphetamachineView Answer on Stackoverflow
Solution 5 - JavaChaosPandionView Answer on Stackoverflow
Solution 6 - JavaJuha SyrjäläView Answer on Stackoverflow
Solution 7 - JavadrekkaView Answer on Stackoverflow
Solution 8 - JavayaskovdevView Answer on Stackoverflow
Solution 9 - JavacthulhuView Answer on Stackoverflow
Solution 10 - JavaIgor ZevakaView Answer on Stackoverflow
Solution 11 - JavaldogView Answer on Stackoverflow
Solution 12 - JavaTim CokerView Answer on Stackoverflow
Solution 13 - Javauser392942View Answer on Stackoverflow
Solution 14 - JavaAnthonyView Answer on Stackoverflow
Solution 15 - JavaAarononthewebView Answer on Stackoverflow
Solution 16 - JavaSteveCavView Answer on Stackoverflow
Solution 17 - JavaanimusonView Answer on Stackoverflow
Solution 18 - JavaStephen CView Answer on Stackoverflow
Solution 19 - JavaHa.View Answer on Stackoverflow
Solution 20 - JavajayshaoView Answer on Stackoverflow
Solution 21 - JavaSushantView Answer on Stackoverflow
Solution 22 - JavaPeter LawreyView Answer on Stackoverflow
Solution 23 - JavaWill MarcouillerView Answer on Stackoverflow