22

As you know, in Eclipse you can turn on "Unnecessary 'else' statement" check that will trigger on if-then-else with premature return. And, from my experience, there are two most possible situations when use such statement:

1) Pre-check:

if (!validate(arg1)) {
    return false;
}
doLotOfStuff();

2) Post-check:

doLotOfStuff();
if (condition) { 
    return foo; 
} else {
    return bar; 
}

In the second case, if the trigger is on, Eclipse will suggest you to change the code to:

doLotOfStuff();
if (condition) { 
    return foo; 
} 
return bar; 

However, I think that the return with else statement is more readable as it is like direct mapping of business logic. So I am curios if this "Unnecessary 'else' statement" code convention is widespread or code with else statement is more preferable?

Vitalii Fedorenko
  • 110,878
  • 29
  • 149
  • 111
  • *Kind of related:* http://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement – Felix Kling Apr 21 '10 at 10:09
  • 3
    Why are you turning the trigger on if you disagree with its suggestions? There's a good reason why it's off by default; it's the software equivalent of "argumentative"… – Donal Fellows Apr 21 '10 at 10:19

10 Answers10

20

Generally I would prefer the structure of the code to follow the structure of the underlying "business" logic. In this case, my approach would depend what condition represents. If it is an error check, for example, which won't normally be hit but might occasionally be used, then the asymmetry of the second form matches the asymmetry of the logic.

doLotOfStuff();
if (condition) { 
    return foo; 
} 
return bar; 

But if either possibility is reasonable and it's simply a choice between them, I would allow the structure of the code to show that symmetry.

doLotOfStuff();
if (condition) { 
    return foo; 
} else {
    return bar; 
}

The code is there for the programmer to read, not the compiler.

Andy Mortimer
  • 3,619
  • 20
  • 14
11

It was once considered (and probably still be by some) that functions should have one entry point (easy but was relevant when you consider assembly language) and one exit point.

One exit point is nice from a debugging standpoint (as in you can put one watch/break on one line and know you'll go through it) but can lead to some horrific nesting so more often than not readability tends to win out. Which produces the least nesting, the least lines of code and the most readable end result? Ultimately that tends to be far more important than anything else.

For what it's worth the last can be better expressed as:

return condition ? foo : bar;

assuming condition isn't terribly long.

Don't get overly concerned with supposed code "purity". It's an irrelevant distraction. Make things readable and generally be consistent.

Alberto Zaccagni
  • 30,779
  • 11
  • 72
  • 106
cletus
  • 616,129
  • 168
  • 910
  • 942
  • You mean exit-points, do you? exist -> exit – Mnementh Apr 21 '10 at 10:13
  • 3
    +1: Deep nesting is definitely damaging to readability. Let's face it, most functions are "check a bunch of preconditions, do the processing, enforce the postconditions" and when silly rules applied to the syntax of the preconditions cramp the principal purpose of the function, you know there's something wrong. – Donal Fellows Apr 21 '10 at 10:23
4

Well, I think that using multiple return is not readable.

I prefer code as:

String result = null;

doLotOfStuff();
if (condition) { 
    result = foo; 
} else {
    result = bar; 
}

return result;

Multiple returns is complicated to understand. But in your case I will prefer the postCheck

doLotOfStuff();
if (condition) { 
    return foo; 
} else {
    return bar; 
}
Jerome Cance
  • 8,103
  • 12
  • 53
  • 106
  • 1
    As a general rule, a good function will have only one entry and one exit. The main exception to this is sometimes short functions can have multiple exits without negatively impacting readability. – Tom Cabanski Apr 21 '10 at 10:08
  • 7
    I'd say it depends on the function. Sometimes a return statement in the middle of the function clearly indicates that at this point no further processing is done and needed. If you have several nested `if-else` statements it might not be that clear which of this code is still processed and which not. – Felix Kling Apr 21 '10 at 10:12
  • @Tom Cabanski: Readability wins most, if all function are short. – Mnementh Apr 21 '10 at 10:14
  • @Tom, Why does a good function have only one exit? – Steve Kuo Apr 21 '10 at 19:56
  • 1
    @TomCabanski Also longer methods can take advantage from multiple returns. Take the preconditions for example. If those are not met, you can insert an early return. So the reader does not have to go all through the clutter just to see that some precondition was not met and all code was unnecessary to execute and read. – Torsten Feb 03 '16 at 09:43
4

Well, some well-known Java experts argue that one should always strife to minimize the scope of things and that's also my opinion.

My teachers at university always tormented me that I must write stuff like this as posted by somebody before:

String result = null;
doLotOfStuff();
if (condition) {
    result = foo;
} else {
    result = bar;
}
return result;

The variable result has now a pretty big scope. In addition with a lot of nesting this tends to get very unreadable if you do a little bit more here, say you have another for-loop.

I think this is much better:

doLotOfStuff();
return condition ? foo : bar;

This is straight to the point. I see immediately what's going on, no checking of curly braces.

I think it's very good to

  • Minimize scope
  • Minimize indention (that is avoid curly braces)
  • Minimize method length

The "Unnecessary else statement" warning helps with that.

Alex
  • 41
  • 1
  • 3
3

I find this form

doLotOfStuff();
if (condition) { 
    return foo; 
}
return bar; 

to be more readable than the one with the else, it's less code and more intuitive if you think about it as a guard statement as in Fowler's Refactoring.

Question about multiple return points.

Community
  • 1
  • 1
Alberto Zaccagni
  • 30,779
  • 11
  • 72
  • 106
  • Oh, seems like I just ripped off Montecristo's answer. Sorry. – Chris Apr 21 '10 at 10:25
  • I find this also to be more readable. I think it's the way you get used to read something. If you are used to read code in the if-else or the if-return way, you'll prefer the one or the other more. – Torsten Feb 03 '16 at 09:38
2

I know that without the IDE checking this for me I nearly always use the unnecessary else statement. Often I find it reads better initially with it, but usually remove it when it is pointed out as I can see the fact that it is unnecessary and it then bugs me...

Sam Holder
  • 32,535
  • 13
  • 101
  • 181
2

Call me a bad boy but I would usually go with:

doLotOfStuff();
return condition ? foo : bar;

Single return statement, very readable.

Chris
  • 4,450
  • 3
  • 38
  • 49
1

In my opinion, the eclipse check is not very useful. What you should do depends on your program context. Else clauses are for alternatives (either this or that) whereas falling through to a return (no else clause) is more appropriate where you have a number of conditions that may be true and the fallthrough is more of a default reaction that you don't really invoke too often. So you use both in code that conveys meaning and as such checking for presence or absence is not useful.

Paul de Vrieze
  • 4,888
  • 1
  • 24
  • 29
0

Some of programmers claim that return in the middle of function is bad practice. Maybe for easy checking at function entry as in your 1st example it is OK and acceptable, but in other cases I would prefer setting result variable as in Jerome response.

Michał Niklas
  • 53,067
  • 18
  • 70
  • 114
0

If I trace the following code, I will notice that the first if-block is an exceptional code block. However, if I add an "else" to that, I may treat both are operational code block.

Also, for the main operational block, there may be some nested blocks. I prefer minimizing the nested level.

public String myMethod(input) {
    if (!validate(input)) {
        return "invalid input";
    }

    operation1();
    if (someCondition) {
        operation2();
    } else {
        operation3();
    }
    operation4();
    operation5();
    return operation6();
}
Franz Wong
  • 1,024
  • 1
  • 10
  • 32