views:

983

answers:

13

Looking around forums and the web, i have come across the advice that a method should have single entry and exit points. My first question is does the sinlge entry point apply to java. I can't see how a method can have an entry point other than invoking it and passing argumnets to it.

The second question is that why only a single return statement, is this for the sake of the clarity of the source code, or can the compiler/jvm optomize a method with a single exit point in a way which it can't with 2 exit points.

A: 

I assume that entry point doesn't mean for any given method itself, but instead a method that allows you to start your application -- a public static void main(String[] args) method. Having a single class with a single method that's always used to start the program makes sense.

Kaleb Brasee
+15  A: 

It would be hard for a method to have more than one entry point...

As for exit points, I just use whatever gives the clearest code. Sometimes that's a single return point - at other times it makes a lot more sense to return as soon as you know the result, which may be before a whole bunch of other code... using multiple exit points can reduce nesting significantly.

Note that the "single exit point" idea made a lot more sense back in C, without exceptions and try/finally... it meant that you could put your cleanup code in one place without having to trace every exit path. With try/finally (and garbage collection) in C#, Java etc, you don't need to worry about this as much.

Jon Skeet
When goto statements were commonplace, it wasn't hard to have multiple entry points to a block of code.
Dean J
A single exit point still makes a lot of sense, even in modern languages. Exceptions are for exceptional situations, and they aren't what people are refering to when they talk about how many exit points a function has.
Adrian McCarthy
@Adrian: I think you missed my point. I'm not talking about throwing exceptions where you wouldn't otherwise; I'm talking about being able to ensure that you do something (e.g. resource clean up) "on the way out" of a method without needing to limit yourself to one exit point.
Jon Skeet
"I just use whatever gives the clearest code" - however I find that at least *thinking* in terms of single exit often leads to code that is even clearer. If you apply the rule blindly you'll get into a mess, it's true. But if you look at some code with multiple exits and consider how you coudl refactor it to have a single exit without turning into a mess I find that exercise very useful.
Phil Nash
@Phil: Considering how you might refactor code is always a useful exercise - whether from several exit points to one, one exit point to several, or anything else :)
Jon Skeet
Not sure I agree at the level of genericity that is written - but reading between the lines I think we're on the same page ;-) However, see my full reply for a little more background on my position.
Phil Nash
+19  A: 

I'm not sure what it would mean for a method to have more than one entry point.

The advice to have only a single point of return is bad advice. Consider

public void uglyAndWrong(final int hamsandwich) {
    int answer;
    if (hamsandwich % 2 == 0) {
        answer = 27;
    } else {
        answer = 13;
    }
    return answer;
}

vs.

public void comelyAndHip(final int hamsandwich) {
    if (hamsandwich % 2 == 0) {
        return 27;
    }
    return 13;
}

Having a single return statement always causes otherwise unnecessary variables to spring into being. It often causes extra braces. I'd reject that advice.

EDIT: The comments and other answers are very interesting, and make me realize how much I take for granted my own milieu as a programmer. So I modify my answer to say: in the context of contemporary programming languages, the advice is out of date, and should be rejected.

Jonathan Feinberg
public int oneliner(final int hamsandwich) { return (hamsandwich % 2 == 0) ? 27 : 13; }
BalusC
More than one entry point was easy to do when you had a goto statement in the language. It was also a path towards disaster, but that was the reason for "one entry point" as an argument.
Dean J
@Jonathan, The point of having a single return statement is more like a guideline, which is valid on small (in loc) or trivial methods. But on methods that for one or another reason are big in terms of loc I would advocate using a SINGLE return statement. From experience, a lot of bugs occur due to not having seen return statements hidden in complex code structures.
HeDinges
In all sincerity, I'd like to see an example of code that could be improved by replacing multiple return statements with a single one. it's very likely that such a routine would have multiple orthogonal problems, not necessarily related to the placement of return statements!
Jonathan Feinberg
A single exit point makes it practical to assert post-conditions. A return buried in the middle of the function is a maintenance bug in the making. Today's compilers are good enough to generate code that's just as efficient when you carry a return value down in an extra variable. The name of the "extra" variable can also help at self-documenting the code. Initializing the "extra" variable at the top helps other to see what the default value is. I see no reason to reject single-exit advice, and plenty of reasons to follow it.
Adrian McCarthy
@Adrian: I've seen plenty of horribly nested code which was *much* easier to follow after "early out" conditions were dealt with by returning appropriately. If I know the result of a method, why should I wade through loads more lines of code just to see if anything else happens? As for post-conditions: use a tool such as Code Contracts and that's handled for you. Personally I see no reason to accept single-exit advice, and plenty of reasons to reject it. Write the most readable code you can. Sometimes that will have one exit point - and sometimes it won't.
Jon Skeet
@Adrian My concern about "extra variables" has nothing to do with "efficiency", and everything to do with greater difficulty for the (maintenance) programmer.
Jonathan Feinberg
I would always prefer the first method for the second. If something is "ugly" is subjective anyways. A good rule of thumb is having only one point of exit EXCEPT for guard clauses (parameter checks etc).
EricSchaefer
@Jonathan Feinberg - your example could also be written using the ternary operator - in fact I believe it would be clearer to do so and may even make it easier for a compiler to optimise (see my response)
Phil Nash
Making something "easy for a compiler to optimise" is optimization in disguise. Optimizing something without measuring is never a good idea. Code should be easy to read, not easy to optimize. It can be optimized later, if some part of the code turns out to be too slow...
EricSchaefer
The thing about RVO is that it allows you to write more natural and expressive code than you would have if you'd been trying to manually optimise. In other words it does raise the abstraction level. My point here is not that you should be trying to prematurely optimise code, but that by adopting a style that is, itself, quite natural, you allow more scope for the compiler to optimise for you anyway without having to go out of your way.
Phil Nash
@Phil: my example was designed to reflect the structure of the problem, and not the content of a realistic method. Of course, that particular example could have been written using a ternary operator, a bit mask comparison, a Latin mass, who knows...
Jonathan Feinberg
+3  A: 

Single entry point is an idea that dates to when the "goto" statement is still around. In languages that define functions, it's no longer an issue; it's automatically enforced.

I don't think single exit point holds in languages that throw Exceptions, like, well, Java. Having a single exit point for a method that throws even a small number of exceptions would turn readable code into a disaster zone.

Dean J
I put in an answer myself, but this is the best other answer I've seen. The main point is that this is obsolete advice (unless you take up unstructured branching - gotos).
T.E.D.
A: 

I cant imagine another entry point beside a function call either.

The single return statement rule is for clarity. A function which has many different return statements is probably a good candidate for refactoring : break it in multiple functions. As for myself, I break that rule quite often for special conditions checking (which are very simple conditions) :

doSomething(param) {
    if (param == null) return null;
    //do some real stuff with param
    [...]
}

This feels perfectly clear to me.

We could also add that raising an exception is en exit point to a method. And raising an exception is a perfectly reasonnable way to exit a function when something exceptionnal happens.

I'm not a compiler guru at all, but I know that there is some optimization for tail recursion coming to Java. Tail recursion is when the last thing a function does is calling itself. And even that doesnt require that there is only one exit point in the function.

I dont think there is any performance reason to optimize the number of return statement. Readability is usually more important.

Guillaume
I'm not sure where you got your information about tail-call optimization in Java. As far as I know, Java's VM is infamously unable to properly represent tail-call optimizations, which makes languages like Clojure jump through some hoops to emulate tail calls (cf. the `recur` keyword).
Jonathan Feinberg
I was thinking of the Da Vinci project. And I thought there is a JSR in progress (but I might be wrong). Answer edited to reflect your point ...
Guillaume
+12  A: 

The stricture of having a single exit point is an instance of a good guideline turned into a bad rule.

If you have many return statements or other exit points in your code, it can make it difficult to read and reason about what it's doing and how changes can affect it. A long method with multiple return statements will likely be more bug-prone and costlier to change than the same method with one return statement at the end.

Of course, if your methods are long enough that they're getting tough to scan, that's a problem in itself - you might wish to break the long method into a set of smaller ones that are easier to reason about.

Instances where it makes sense to exit mid-method include:

  • Input validation: It's acceptable to return immediately on invalid input, or on any input that's simple to evaluate and doesn't need to go through the whole method body. These returns should be clustered at the top of the method for readability, and the rest of the method will probably benefit from keeping it simple and having that single exit point at the end.
  • Exceptions: If you've run across a problem where it makes no sense to do anything but abort the method and throw an exception, there's no need to wait until the end.

Finally: I'll agree with Jonathan Feinberg in that a method as short as he describes does not sacrifice any readability by returning directly rather than stashing the answer and returning later. Though brevity could be further enhanced by changing it to:

public void shortAndSweet(final int hamsandwich) {
  return (hamsandwich % 2 == 0) ? 27 : 13;
}

Which, funnily enough, takes us back to a single exit point...

bradheintz
not that I disagree with the answers that have more votes, it surprises me that **this** answer doesn't (yet) get more upvotes.
Lieven
Agreed. I voted it up :-)
Phil Nash
Thanks! It means a lot to me that you felt strongly enough to comment.
bradheintz
+5  A: 

Warning: C# code ahead! :)

IMO, as soon as you know there's a problem, or going to be a problem, GET OUT! Exceptions are also exit points. (Oh, and don't throw exceptions that you can't recover from - that's another bad thing I see a lot.)

public int MyMethod(IMyInterface someThing, int someOtherThing)
{
    if (someThing == null)
    {
        throw new ApplicationException("Why did you send me a null thing?");
    }
    if (someOtherThing < 0)
    {
        throw new ApplicationException("Great, now the value is less than 0!");
    }
    // Continue with code...
    return value;
}
Jarrett Meyer
+1: exceptions are soo undervalued. The Java way would be `IllegalArgumentException` by the way.
BalusC
And in C# it should be ArgumentNullException and ArgumentOutOfRangeException :)
Jon Skeet
Yes, those would be better exceptions. I wasn't really thinking about the exception type - just the bail out of the method.
Jarrett Meyer
+1  A: 

First, I don't know how a Java method can have more than one entry point. Fortran has the ENTRY statement, which provides alternative entry points into functions and subroutines (different things in Fortran), and in internal constructs it's sometimes possible to do similar things internally (look up Duff's Device for a very good or very bad example).

Second, the reasons for single return points are stylistic in nature, and sometimes relate to attempts to reason formally about programs. I know of only one technical reason for it: having one exit point makes it easier for the compiler to check all execution paths, when that's important for warnings.

One traditional reason has been to make sure cleanup code is run, which simply doesn't work in languages with exceptions. In Java, cleanup code is run by try {...} finally {...}, and by RAII in C++.

Another reason has been to avoid confusion, as the code reader might have trouble understanding when certain code is run if there have been arbitrary returns. This is more valid, but in general handling simple special cases like invalid input and returning immediately makes the method more readable.

David Thornley
+1  A: 

These pieces of advice were actually meant for programmers in the olden days when most iteration and branching was done with goto-like statements. They don't make much sense if you are using a modern language, but people continue to repeat them like a religous creed without understanding what they mean.

The basic idea is that if you have a subroutine you should not use "goto"s to jump into it at multiple places, nor should you use goto's to jump out of it at multiple places.

If you avoid goto's in modern langauges, the first isn't really possible. The second is possible with more structured statments like "return", "exit", and with exceptions. The thing is, they are well-defined structured statments. The subprogram's stack will get cleaned up just fine if you use them, and anybody reading the code knows just where control will go when they come across them.

Some folks still insist that exiting a routine anywhere but the very last statement is a Bad Thing. If that works for them, fine. But I really hate seeing code with boolean flags, temporary variables and convoluted nexted "if"s just to avoid a second return statement.

T.E.D.
+3  A: 

It a symptom of Cargo Cult Programming. Back in the day, when OOP wasn't mainstream, people had to be convinced that GOTO was a prime cause of spaghetti code. You could have code that had multiple GOTOs jumping in and multiple GOTOs jumping out.

A cry went out to find a solution to all the pasta-based code. OOP was on the horizon and definitely helped with inheritance, encapsulation, and overloading. But in the interim, it was declared that to solve the maze of twisty little execution paths all alike (but different), programmers should only allow one entry and one exit. On the battlefield of software, this was an act of triage to stop the bleeding. Now that we have objects, methods, public/protected/private, the Single Entry Single Exit (SESE) mantra is more like a tourniquet.

Making code easier to read should never be a bad thing outside of needing pure performance. Even then, the optimized code can be isolated and not allowed to become the standard coding style for everyday, barely use 1% cpu programs.

Kelly French
A: 

Forget multiple entry - once upon a time you could do it in Fortran, and you can still do it in assembler, but it's not really an issue now.

For returns, it's still an issue, and not clear cut. On the one hand, if you take simple LISP recursive functions and translate them directly into a C-ish language, it makes sense to have a separate return for each branch. There are also other situations where common sense will tell you it is sensible to have multiple returns.

Where a single return point is a good thing is where you want to be sure you will get a chance to take action before the function returns, such as doing cleanup. To put it more broadly, if you have two statements in a row:

Statement 1;
Statement 2;

It helps you to understand the code if you can be sure that if control gets to Statement 1, barring a crash or infinite loop, it will eventually get to Statement 2. It is easier to be sure of this if Statement 1 has no other way to finish up, other than falling out the bottom.

Mike Dunlavey
+1  A: 

I agree with others here who say that SESE (Single-Entry, Single-Exit) is not as relavent as it used to be, but I don't think it's redundant.

Functions and methods with a single exit tend to be easier to reason about - especially if there are resources that need to be managed. Even in a managed environment there may be things that need to be done in a certain order.

Personally I do aim for SESE by default. If I'm finding it doesn't come easily, or it leads to unnecessary nesting or other complexity I see that as a code smell and investigate if I need to refactor in other ways - e.g. decomposing a longer method into smaller components that can each be SESE'd.

But even beyond that there are certainly cases where SESE is more of a burden than not. Typical examples are methods that check optional pre-conditions up front and return early if not met. But I very rarely (if ever) find cases where an early return is nested right in the middle of a method where it didn't make more sense to refactor.

There may also be scope for compiler optimisation. In C++ having either a single returning expression or a single variable that gets returned at the end may allow the compiler to do Return Value Optimisation which means it uses the instance of the variable the caller is assigning to, rather than creating a local instance. There is likely scope for similar optimisations in other languages.

Phil Nash
A: 

I haven't much seen mentioned code size and performance. Personally I aim for a single exit point provided it makes sense, and from a performance PoV especially if there are large or expensive to destruct local objects involved. That code has to be inserted somewhere and I'd like it easy for the compiler to emit it exactly once. Likewise it makes sense to bail out before constructing those heavy objects. If a function returns an object (not a pointer or reference) it might help to construct it as an argument to (the single) return (return classname(args);). Exceptions should probably "naturally" end up together too, for it is usually better to check whether there was any error at all before watching for specific errors.

In my experience, if you get convoluted nested ifs and loops, multiple state variables, or more than a few exit points (returns, exceptions, longjmps, gotos, (come from)s, what have you) then it usually means it's time and past time to split the function up into its constituent logical parts, and doing that in turn usually makes it easier again to shuffle closer to SESE, but only as far as practicable.

To end with a possibly worn quote, it "should be as simple as possible, but no simpler". Here meaning that if a rule or guideline introduces unnecessairy complexity and makes it harder to read the code, it wasn't appropriate for the situation.

Bounce