Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is an "if(...) return ...;" without "else" considered good style? [closed]

Tags:

This code:

if( someCondition )     return doSomething();  return doSomethingElse(); 

versus this code:

if( someCondition )     return doSomething(); else     return doSomethingElse(); 

In essence, they are the same, but what is best style/performance/... (if there is any non-opinionated part to the answer of course)? Also consider the case with multiple "if else's":

if( someCondition )     return doSomething(); else if( someOtherCondition )     return doSomethingDifferently(); //... else     return doSomethingElse(); 

Thanks!

like image 589
rubenvb Avatar asked Nov 21 '10 13:11

rubenvb


People also ask

What happens if there is no else statement?

An if statement looks at any and every thing in the parentheses and if true, executes block of code that follows. If you require code to run only when the statement returns true (and do nothing else if false) then an else statement is not needed.

Should I use if else or return?

It depends on the semantics of your code, if the else branch is the point of the method, i.e. it's named after what happens in the else branch, the early return is probably correct, especially if the first part is some sort of check.

Is else return necessary?

Don't put an else right after a return. Delete the else, it's unnecessary and increases indentation level.

Which functions should not use a return statement?

In lieu of a data type, void functions use the keyword "void." A void function performs a task, and then control returns back to the caller--but, it does not return a value. You may or may not use the return statement, as there is no return value.


2 Answers

When you have multiple return statements in a function, this is referred to as "early return." If you do a Google search for "early return" you will find link after link that says it is bad.

I say nonsense.

There are two primary reasons and one secondary reason that people claim that early return is bad. I'll go through them and give my rebuttal in order. Keep in mind this is all my opinion and ultimately you have to decide for yourself.

1) Reason: Early returns make it difficult to clean up.

Rebuttal: That's what RAII is for. A well-designed program won't allocate resources in such a way that if a the execution leaves scope early those resources will leak. Instead of doing this:

...

int foo() {   MyComplexDevice* my_device = new MyComplexDevice;   // ...   if( something_bad_hapened )     return 0;   // ...   delete my_device;   return 42; } 

you do this:

int foo() {   std::auto_ptr<MyComplexDevice> my_device(new MyComplexDevice);   if( something_bad_hapened )     return 0;   // ...   return 42; }  

And early return won't cause a resource leak. In most cases, you won't even need to use auto_ptr because you'll be creating arrays or strings, in chich case you'll use vector, string or something similar.

You should design your code like this anyway for robustness, because of the possibility of exceptions. Exceptions are a form of early return like an explicit return statement, and you need to be prepared to handle them. You may not handle the exception in foo(), but foo() should not leak regardless.

2) Reason: Early returns make code more complex. Rebuttal: Early returns actually make code simpler.

It is a common philosophy that functions should have one responsibility. I agree with that. But people take this too far and conclude that if a function has multiple returns it must have more than one responsibility. (They extend this by saying that functions should never be more than 50 lines long, or some other arbitrary number.) I say no. Just because a function has only one responsibility, doesn't mean it doesn't have a lot to do to fulfil that resposibility.

Take for example opening a database. That's one responsibility, but it is made up of many steps, each of which could go wrong. Open the connection. Login. Get a connection object & return it. 3 steps, each of which could fail. You could break this down in to 3 sub-steps, but then instead of having code like this:

int foo() {    DatabaseObject db = OpenDatabase(...); } 

you'll end up having:

int foo() {   Connection conn = Connect(...);   bool login = Login(...);   DBObj db = GetDBObj(conn); } 

So you've really just moved the supposed multiple responsibilities to a higher point in the call stack.

3) Reason: Multiple return points are not object-oriented. Rebuttal: This is really just another way of saying "everybody says multiple returns are bad, though I don't really know why."

Taken another way, this is really just an attempt to cram everything in to an object-shaped box, even when it doesn't belong there. Sure, maybe the connection is an object. But is the login? A login attempt isn't (IMO) an object. Its an operation. Or an algorithm. trying to take this algorithm and cram it in to an object-shaped box is a gratuitous attempt at OOP, and will only result in code that is more complex, harder to maintain, and possibly even less efficient.

like image 65
John Dibling Avatar answered Nov 10 '22 01:11

John Dibling


A function should always return as soon as possible. This saves semantic overhead in unnecessary statements. Functions that return as soon as possible offer the highest clarity and the cleanest, most maintainable source code.

SESE-style code was good when you had to manually write to free every resource you had allocated, and remembering to free them all in several different places was a waste. Now that we have RAII, however, it's definitely redundant.

like image 44
Puppy Avatar answered Nov 10 '22 00:11

Puppy