326

When I ran ReSharper on my code, for example:

    if (some condition)
    {
        Some code...            
    }

ReSharper gave me the above warning (Invert "if" statement to reduce nesting), and suggested the following correction:

   if (!some condition) return;
   Some code...

I would like to understand why that's better. I always thought that using "return" in the middle of a method problematic, somewhat like "goto".

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lea Cohen
  • 7,990
  • 18
  • 73
  • 99
  • 1
    I believe that the exception checking and returning at the beginning is fine, but I would change the condition so you are checking for the exception directly rather than not something (ie if (some condtion) return). – bruceatk Dec 12 '08 at 22:24
  • 44
    No, it will do nothing for performance. – Seth Carnegie Dec 08 '11 at 20:34
  • It is subjective and depends on which case you like more. The resulting IL code will be pretty similar. – zerkms Dec 08 '11 at 20:35
  • 3
    I'd be tempted to throw an ArgumentException if my method was being passed bad data instead. – asawyer Dec 08 '11 at 20:36
  • 2
    @asawyer Yes, there's a whole side-discussion here about functions that are too forgiving of nonsense inputs -- as opposed to using an assertion failure. _Writing Solid Code_ opened my eyes to this. In which case, this would be something like `ASSERT( exampleParam > 0 )`. – Greg Hendershott Dec 08 '11 at 21:29
  • 5
    Assertions are for internal state, not parameters. You'd start by validating the parameters, asserting that your internal state is correct, and then performing the operation. In a release build, you can either leave out the assertions or map them to a component shutdown. – Simon Richter Dec 08 '11 at 21:48
  • Nice to have asked that, which I also figured was a serious bias from resharper developers. I don't consider their refactoring cleaner than my nested if. They also enforce DRY much too far. like put `var` here and there or please remove redundant qualifiers, when I like my overqualification like they are... – v.oddou Apr 17 '14 at 07:21
  • possible duplicate of [Does inverting the "if" improve performance?](http://stackoverflow.com/questions/8437307/does-inverting-the-if-improve-performance) – Ryan Kohn Sep 16 '14 at 15:31
  • 1
    "to reduce nesting" is the explanation why it is proposed :-) – Kux Oct 24 '20 at 22:45
  • @asawyer, It's not just about checking for bad inputs. Sometimes returning early is about checking business logic if(!isEligibleForDiscount) return – Louise Eggleton May 07 '21 at 12:21

25 Answers25

365

It is not only aesthetic, but it also reduces the maximum nesting level inside the method. This is generally regarded as a plus because it makes methods easier to understand (and indeed, many static analysis tools provide a measure of this as one of the indicators of code quality).

On the other hand, it also makes your method have multiple exit points, something that another group of people believes is a no-no.

Personally, I agree with ReSharper and the first group (in a language that has exceptions I find it silly to discuss "multiple exit points"; almost anything can throw, so there are numerous potential exit points in all methods).

Regarding performance: both versions should be equivalent (if not at the IL level, then certainly after the jitter is through with the code) in every language. Theoretically this depends on the compiler, but practically any widely used compiler of today is capable of handling much more advanced cases of code optimization than this.

hdoghmen
  • 3,175
  • 4
  • 29
  • 33
Jon
  • 428,835
  • 81
  • 738
  • 806
  • 46
    single exit points? [Who needs it?](http://programmers.stackexchange.com/questions/118703/where-did-the-notion-of-one-return-only-come-from) – sq33G Dec 08 '11 at 22:10
  • 3
    @sq33G: That question on SESE (and the answers of course) are fantastic. Thanks for the link! – Jon Dec 08 '11 at 23:37
  • I keep hearing in answers that there are some people who advocate for single exit points, but I *never ever* saw someone actually advocating that, especially in languages like C#. – Andreas Bonini Dec 09 '11 at 15:03
  • 1
    @AndreasBonini: Absence of proof is not proof of absence. :-) – Jon Dec 09 '11 at 15:13
  • Yeah of course, I just find strange that everyone feels the need to say that some people like another approach if those people don't feel the need to say it themselves =) – Andreas Bonini Dec 09 '11 at 15:30
  • @sq33G Who cares / needs a single exit point? Anyone who is an experienced multi-threaded developer can answer that. That doesn't make single-exit point into developer canon or anything high-and-mighty like that, just a valuable practice of many veteran developers. (and yes, it is much less relevant these days). – Robert Altman Dec 14 '11 at 17:07
  • @Robert Altman funny, I don't recall seeing anything about multithreading in that otherwise exhaustive post. Can you elaborate? – sq33G Dec 14 '11 at 17:20
  • @sq33G Just an example of why some people insist on single exit points. ReSharper is very likely not concerned with this. If there is anything worthy of note from my comment, it is really that "style" needs to be considered in the context of what is being styled. (Read your link *after* I posted my comment, so perhaps I missed any intended irony or explanation on your part.) – Robert Altman Dec 14 '11 at 17:35
  • As mentioned, there is no clear-cut answer here. The developer would have to make the choice based on the codebase. All of the points mentioned here are valid though. If there's double-nesting in a function with 10 lines of code, then it would be easy enough to read and not an issue. Then if you take over some code with an 800-line function, then nesting should be kept at a minimum. There are other factors at play here as well. – Saturn K Nov 17 '21 at 21:20
330

A return in the middle of the method is not necessarily bad. It might be better to return immediately if it makes the intent of the code clearer. For example:

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

In this case, if _isDead is true, we can immediately get out of the method. It might be better to structure it this way instead:

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

    return normalPayAmount();
};   

I've picked this code from the refactoring catalog. This specific refactoring is called: Replace Nested Conditional with Guard Clauses.

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
jop
  • 82,837
  • 10
  • 55
  • 52
  • 22
    Probably just a matter of taste: I suggest changing the 2nd and 3rd "if" to "else if" to increase readability even more. If one overlooks the "return" statement it would still be clear that the following case is only checked if the previous one failed, i.e. that the order of the checks is important. – foraidt Nov 06 '08 at 11:24
  • 2
    In an example this simple, id agree the 2nd way is better, but only because its SO obvious whats happening. – Andrew Bullock Nov 06 '08 at 13:00
  • it also called **defensive approach** – Alexey Sep 07 '18 at 20:27
  • Why not just make this a switch statement? – TylerH Jul 27 '22 at 19:53
  • 1
    Not only is the code easier to read with multiple returns, the code is also more [orthogonal](https://softwareengineering.stackexchange.com/a/122625/11110) which makes the code much more maintainable. – hlovdal Oct 19 '22 at 07:53
  • @foraidt I disagree. Clarity and readability are important, not redundancy. Just a `return` statement is sufficient as it explicitly tells a reader that the function ends, and no further code is executed. – ban_javascript Nov 12 '22 at 03:22
105

This is a bit of a religious argument, but I agree with ReSharper that you should prefer less nesting. I believe that this outweighs the negatives of having multiple return paths from a function.

The key reason for having less nesting is to improve code readability and maintainability. Remember that many other developers will need to read your code in the future, and code with less indentation is generally much easier to read.

Preconditions are a great example of where it is okay to return early at the start of the function. Why should the readability of the rest of the function be affected by the presence of a precondition check?

As for the negatives about returning multiple times from a method - debuggers are pretty powerful now, and it's very easy to find out exactly where and when a particular function is returning.

Having multiple returns in a function is not going to affect the maintainance programmer's job.

Poor code readability will.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
LeopardSkinPillBoxHat
  • 28,915
  • 15
  • 75
  • 111
  • Also, by using such "invert if" you have an erroneous condition check and actions on error close to each other. If you did other wise it would be if (good) do something; else correct/report. This way one immediately sees error - action. – Marcin Gil Nov 07 '08 at 08:04
  • 2
    Multiple returns in a function do effect the maintenance programmer. When debugging a function, looking for the rogue return value, the maintainer must put breakpoints on all places that can return. – EvilTeach Nov 12 '08 at 22:21
  • Can't you put a breakpoint on the closing brace of the method? – g . Dec 02 '08 at 14:42
  • @g: I guess the problem with that approach is that if you have multiple returns in the method, you won't know which one it returned through if you only put the breakpoint on the closing brace. – LeopardSkinPillBoxHat Dec 03 '08 at 23:18
  • 11
    I'd put a breakpoint on the opening brace. If you step through the function, not only can you see the checks being performed in order, but it will be abundantly clear which check the function landed on for that run. – John Dunagan Dec 12 '08 at 13:24
  • 3
    Agree with John here... I don't see the problem in just stepping through the entire function. – Nailer Dec 12 '08 at 13:58
  • 6
    @Nailer Very late, I especially agree, cause if the function's too big to step through, it should be separated into multiple functions anyways! – Aidiakapi Jan 24 '12 at 14:49
  • 1
    Agree with John also. Maybe it's an old school thought to put the break point at the bottom but if you're curious what a function is returning then you'll be stepping through said function to see why it's returning what it's returning anyway. If you just want to see what it returns then put it on the last bracket. – user441521 May 04 '17 at 17:46
70

As others have mentioned, there shouldn't be a performance hit, but there are other considerations. Aside from those valid concerns, this also can open you up to gotchas in some circumstances. Suppose you were dealing with a double instead:

public void myfunction(double exampleParam){
    if(exampleParam > 0){
        //Body will *not* be executed if Double.IsNan(exampleParam)
    }
}

Contrast that with the seemingly equivalent inversion:

public void myfunction(double exampleParam){
    if(exampleParam <= 0)
        return;
    //Body *will* be executed if Double.IsNan(exampleParam)
}

So in certain circumstances what appears to be a a correctly inverted if might not be.

Michael McGowan
  • 6,528
  • 8
  • 42
  • 70
  • 4
    It should also be noted that the resharper quick fix inverts exampleParam > 0 to exampleParam < 0 *not* exampleParam <= 0 which has caught me out. – nickd Dec 02 '14 at 14:51
  • 1
    And this is why that check should be up front and returned as well given the dev thinks a nan should result in bailing out. – user441521 May 04 '17 at 17:49
56

The idea of only returning at the end of a function came back from the days before languages had support for exceptions. It enabled programs to rely on being able to put clean-up code at the end of a method, and then being sure it would be called and some other programmer wouldn't hide a return in the method that caused the cleanup code to be skipped. Skipped cleanup code could result in a memory or resource leak.

However, in a language that supports exceptions, it provides no such guarantees. In a language that supports exceptions, the execution of any statement or expression can cause a control flow that causes the method to end. This means clean-up must be done through using the finally or using keywords.

Anyway, I'm saying I think a lot of people quote the 'only return at the end of a method' guideline without understanding why it was ever a good thing to do, and that reducing nesting to improve readability is probably a better aim.

Scott Langham
  • 58,735
  • 39
  • 131
  • 204
  • 6
    You just figured out why exceptions are UglyAndEvil[tm]... ;-) Exceptions are gotos in fancy, expensive disguise. – EricSchaefer Nov 07 '08 at 15:58
  • 18
    @Eric you must have been exposed to exceptionally bad code. It's pretty obvious when they're used incorrectly, and they generally allow you to write higher-quality code. – Robert Paulson Dec 01 '08 at 20:40
  • 1
    This is the answer I was really looking for! There are great answers here, but most of them focus on examples, not on the actual reason why this recommendation was born. – Gustavo Mori Mar 15 '12 at 17:34
  • 1
    This is the best answer, since it explains why this whole argument arose in the first place. – Buttle Butkus Oct 31 '13 at 05:00
41

I'd like to add that there is name for those inverted if's - Guard Clause. I use it whenever I can.

I hate reading code where there is if at the beginning, two screens of code and no else. Just invert if and return. That way nobody will waste time scrolling.

http://c2.com/cgi/wiki?GuardClause

Piotr Perak
  • 10,718
  • 9
  • 49
  • 86
  • 2
    Exactly. It is more of a refactoring. It helps reading the code easier as you mentioned. – rpattabi Dec 14 '11 at 04:17
  • 'return' is not enough and horrible for a guard clause. I would do: if(ex<=0) throw WrongParamValueEx("[MethodName] Bad input param 1 value {0}... and you will need to catch the exception and write into your app log – JohnJohnGa Dec 14 '11 at 07:11
  • 4
    @John. You are right if this is in fact error. But often it's not. And instead of checking something in every place where method is called method just checks it and returns doing nothing. – Piotr Perak Dec 14 '11 at 07:24
  • 3
    I would hate to read a method that's two screens of code, period, `if`s or no. lol – jpmc26 Jul 15 '14 at 03:01
  • I hate it too! Believe it or not but I've seen 11k lines of code methods in C# :) – Piotr Perak Jul 15 '14 at 06:38
  • 1
    I personally prefer early returns for exactly this reason (also: avoiding nesting). However, this is unrelated to the original question about performance and should probably be a comment. – Patrick M Sep 16 '14 at 19:57
21

It doesn't only affect aesthetics, but it also prevents code nesting.

It can actually function as a precondition to ensure that your data is valid as well.

Rion Williams
  • 74,820
  • 37
  • 200
  • 327
18

This is of course subjective, but I think it strongly improves on two points:

  • It is now immediately obvious that your function has nothing left to do if condition holds.
  • It keeps the nesting level down. Nesting hurts readability more than you'd think.
Deestan
  • 16,738
  • 4
  • 32
  • 48
15

Multiple return points were a problem in C (and to a lesser extent C++) because they forced you to duplicate clean-up code before each of the return points. With garbage collection, the try | finally construct and using blocks, there's really no reason why you should be afraid of them.

Ultimately it comes down to what you and your colleagues find easier to read.

Richard Poole
  • 3,946
  • 23
  • 29
  • That is not the only reason. There is an academical reason refering to pseudo code which has nothing to do with practical considerations like cleaning stuff. This acamedical reason has to do with respecting the basic forms of imperative constructs. The same way you do not put loop exiters in its middle. This way, invariants can be rigorously detected and behavior can be proven. Or termination can be proven. – v.oddou Apr 17 '14 at 07:31
  • 1
    news: actually I have found a very practical reason why early break and returns are bad, and it is a direct consequence of what I said, static analysis. here you go, intel C++ compiler use-guide paper: http://d3f8ykwhia686p.cloudfront.net/1live/intel/CompilerAutovectorizationGuide.pdf . Key phrase : `a loop that is not vectorizable due to a second data-dependent exit` – v.oddou Jun 30 '14 at 06:27
  • In C, you'd be using goto for cleanup. @v.oddou how would you propose to make that loop vectorizable? – syockit Jul 18 '21 at 00:44
13

Guard clauses or pre-conditions (as you can probably see) check to see if a certain condition is met and then breaks the flow of the program. They're great for places where you're really only interested in one outcome of an if statement. So rather than say:

if (something) {
    // a lot of indented code
}

You reverse the condition and break if that reversed condition is fulfilled

if (!something) return false; // or another value to show your other code the function did not execute

// all the code from before, save a lot of tabs

return is nowhere near as dirty as goto. It allows you to pass a value to show the rest of your code that the function couldn't run.

You'll see the best examples of where this can be applied in nested conditions:

if (something) {
    do-something();
    if (something-else) {
        do-another-thing();
    } else {
        do-something-else();
    }
}

vs:

if (!something) return;
do-something();

if (!something-else) return do-something-else();
do-another-thing();

You'll find few people arguing the first is cleaner but of course, it's completely subjective. Some programmers like to know what conditions something is operating under by indentation, while I'd much rather keep method flow linear.

I won't suggest for one moment that precons will change your life or get you laid but you might find your code just that little bit easier to read.

Oli
  • 235,628
  • 64
  • 220
  • 299
  • 6
    I guess I'm one of the few then. I find it easier to read the first version. The nested ifs make the decision tree more obvious. On the other hand, if there are a couple of pre-conditions, I agree it is better to put them all at the top of the function. – Otherside Nov 06 '08 at 10:32
  • @Otherside: completely agree. the returns written in serial fashion makes your brain needs to serialize possible paths. When the if-tree can be mapped directly into some transicent logic, for example it could be compiled to lisp. but the serial return fashion would requires a compiler much harder to do. The point here obviously has nothing to do with this hypothetical scenario, it has to do with code analysis, chances of optimization, correction proofs, termination proofs and invariants detection. – v.oddou Apr 17 '14 at 07:36
  • 1
    No way anyone finds it easier to read code with more nests. The more block like something is the easier it is to read at a glance. There is no way the first example here i easier to read and it only goes 2 nests in when most code like this in the real world goes deeper and with every nest it requires more brain power to follow. – user441521 May 04 '17 at 17:59
  • 1
    If the nesting was twice as deep, how long would it take you to answer the question: "When do you 'do-something-else'?" I think you'd be hard-pressed to answer it without a pen and paper. But you could answer it pretty easily if it was all guard-claused. – David Storfer Aug 29 '18 at 16:21
11

Performance-wise, there will be no noticeable difference between the two approaches.

But coding is about more than performance. Clarity and maintainability are also very important. And, in cases like this where it doesn't affect performance, it is the only thing that matters.

There are competing schools of thought as to which approach is preferable.

One view is the one others have mentioned: the second approach reduces the nesting level, which improves code clarity. This is natural in an imperative style: when you have nothing left to do, you might as well return early.

Another view, from the perspective of a more functional style, is that a method should have only one exit point. Everything in a functional language is an expression. So if statements must always have an else clauses. Otherwise the if expression wouldn't always have a value. So in the functional style, the first approach is more natural.

Jeffrey Sax
  • 10,253
  • 3
  • 29
  • 40
9

There are several good points made here, but multiple return points can be unreadable as well, if the method is very lengthy. That being said, if you're going to use multiple return points just make sure that your method is short, otherwise the readability bonus of multiple return points may be lost.

Jon Limjap
  • 94,284
  • 15
  • 101
  • 152
9

Performance is in two parts. You have performance when the software is in production, but you also want to have performance while developing and debugging. The last thing a developer wants is to "wait" for something trivial. In the end, compiling this with optimization enabled will result in similar code. So it's good to know these little tricks that pay off in both scenarios.

The case in the question is clear, ReSharper is correct. Rather than nesting if statements, and creating new scope in code, you're setting a clear rule at the start of your method. It increases readability, it will be easier to maintain, and it reduces the amount of rules one has to sift through to find where they want to go.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ryan Ternier
  • 8,714
  • 4
  • 46
  • 69
7

Personally I prefer only 1 exit point. It's easy to accomplish if you keep your methods short and to the point, and it provides a predictable pattern for the next person who works on your code.

eg.

 bool PerformDefaultOperation()
 {
      bool succeeded = false;

      DataStructure defaultParameters;
      if ((defaultParameters = this.GetApplicationDefaults()) != null)
      {
           succeeded = this.DoSomething(defaultParameters);
      }

      return succeeded;
 }

This is also very useful if you just want to check the values of certain local variables within a function before it exits. All you need to do is place a breakpoint on the final return and you are guaranteed to hit it (unless an exception is thrown).

ilitirit
  • 16,016
  • 18
  • 72
  • 111
  • 4
    bool PerformDefaultOperation() { DataStructure defaultParameters = this.GetApplicationDefaults(); return (defaultParameters != NULL && this.DoSomething(defaultParameters); } There, fixed it for you. :) – tchen Nov 07 '08 at 16:02
  • 2
    This example is very basic and misses the point of this pattern. Have about 4 other checks inside of this function and then tell us it's more readable, because it's not. – user441521 Apr 24 '16 at 05:06
6

Many good reasons about how the code looks like. But what about results?

Let's take a look to some C# code and its IL compiled form:

using System;

public class Test {
    public static void Main(string[] args) {
        if (args.Length == 0) return;
        if ((args.Length+2)/3 == 5) return;
        Console.WriteLine("hey!!!");
    }
}

This simple snippet can be compiled. You can open the generated .exe file with ildasm and check what is the result. I won't post all the assembler thing but I'll describe the results.

The generated IL code does the following:

  1. If the first condition is false, jumps to the code where the second is.
  2. If it's true jumps to the last instruction. (Note: the last instruction is a return).
  3. In the second condition the same happens after the result is calculated. Compare and: got to the Console.WriteLine if false or to the end if this is true.
  4. Print the message and return.

So it seems that the code will jump to the end. What if we do a normal if with nested code?

using System;

public class Test {
    public static void Main(string[] args) {
        if (args.Length != 0 && (args.Length+2)/3 != 5) 
        {
            Console.WriteLine("hey!!!");
        }
    }
}

The results are quite similar in IL instructions. The difference is that before there were two jumps per condition: if false go to next piece of code, if true go to the end. And now the IL code flows better and has 3 jumps (the compiler optimized this a bit):

  1. First jump: when Length is 0 to a part where the code jumps again (Third jump) to the end.
  2. Second: in the middle of the second condition to avoid one instruction.
  3. Third: if the second condition is false, jump to the end.

Anyway, the program counter will always jump.

Nikita
  • 1,019
  • 2
  • 15
  • 39
graffic
  • 1,303
  • 2
  • 14
  • 18
  • 5
    This is good info - but personally I couldn't care less if IL "flows better" because people who are gonna manage the code are not gonna see any IL – JohnIdol Nov 07 '08 at 15:36
  • 1
    You really cannot anticipate how the optimization pass in the next update of the C# compiler will function compared to what you see today. Personally, I wouldn't spend ANY time trying to tweak the C# code in order to produce a different result in the IL, unless tesing shows that you have a SEVERE performance problem in some tight loop somewhere and you've run out of other ideas. Even then, I'd think harder about other options. In the same vein, I doubt that you have any idea what kinds of optimizations the JIT compiler is doing with the IL that gets fed to it for each platform... – Craig Tullis Sep 11 '13 at 22:50
6

Avoiding multiple exit points can lead to performance gains. I am not sure about C# but in C++ the Named Return Value Optimization (Copy Elision, ISO C++ '03 12.8/15) depends on having a single exit point. This optimization avoids copy constructing your return value (in your specific example it doesn't matter). This could lead to considerable gains in performance in tight loops, as you are saving a constructor and a destructor each time the function is invoked.

But for 99% of the cases saving the additional constructor and destructor calls is not worth the loss of readability nested if blocks introduce (as others have pointed out).

shibumi
  • 378
  • 2
  • 11
  • 3
    there. it took me 3 long reads of tens of answers in 3 questions asking the same thing (2 of which being frozen), to finally find someone mentioning NRVO. gee... thank you. – v.oddou Nov 21 '17 at 09:37
5

In theory, inverting if could lead to better performance if it increases branch prediction hit rate. In practice, I think it is very hard to know exactly how branch prediction will behave, especially after compiling, so I would not do it in my day-to-day development, except if I am writing assembly code.

More on branch prediction here.

nevyn
  • 33
  • 8
jfg956
  • 16,077
  • 4
  • 26
  • 34
4

That is simply controversial. There is no "agreement among programmers" on the question of early return. It's always subjective, as far as I know.

It's possible to make a performance argument, since it's better to have conditions that are written so they are most often true; it can also be argued that it is clearer. It does, on the other hand, create nested tests.

I don't think you will get a conclusive answer to this question.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • I don't understand your performance argument. Conditions are boolean so whatever the outcome, there are always two results... I don't see why reversing a statement (or not) would change a result. (Unless you're saying adding a "NOT" to the condition adds a measurable amount of processing... – Oli Nov 06 '08 at 10:09
  • 2
    The optimization works like this: If you ensure that the most common case is in the if block instead of the else block, then the CPU will usually already have the statements from the if block loaded in its pipeline. If the condition returns false, the CPU needs to empty its pipeline and ... – Otherside Nov 06 '08 at 10:39
  • I also like doing what otherside is saying just for readability, i hate having negative cases in the "then" block rather than the "else". It makes sense to do this even without knowing or considering what the CPU is doing – Andrew Bullock Nov 06 '08 at 12:53
3

There are a lot of insightful answers there already, but still, I would to direct to a slightly different situation: Instead of precondition, that should be put on top of a function indeed, think of a step-by-step initialization, where you have to check for each step to succeed and then continue with the next. In this case, you cannot check everything at the top.

I found my code really unreadable when writing an ASIO host application with Steinberg's ASIOSDK, as I followed the nesting paradigm. It went like eight levels deep, and I cannot see a design flaw there, as mentioned by Andrew Bullock above. Of course, I could have packed some inner code to another function, and then nested the remaining levels there to make it more readable, but this seems rather random to me.

By replacing nesting with guard clauses, I even discovered a misconception of mine regarding a portion of cleanup-code that should have occurred much earlier within the function instead of at the end. With nested branches, I would never have seen that, you could even say they led to my misconception.

So this might be another situation where inverted ifs can contribute to a clearer code.

Ingo Schalk-Schupp
  • 843
  • 10
  • 26
2

It's a matter of opinion.

My normal approach would be to avoid single line ifs, and returns in the middle of a method.

You wouldn't want lines like it suggests everywhere in your method but there is something to be said for checking a bunch of assumptions at the top of your method, and only doing your actual work if they all pass.

Colin Pickard
  • 45,724
  • 13
  • 98
  • 148
2

In my opinion early return is fine if you are just returning void (or some useless return code you're never gonna check) and it might improve readability because you avoid nesting and at the same time you make explicit that your function is done.

If you are actually returning a returnValue - nesting is usually a better way to go cause you return your returnValue just in one place (at the end - duh), and it might make your code more maintainable in a whole lot of cases.

JohnIdol
  • 48,899
  • 61
  • 158
  • 242
1

I'm not sure, but I think, that R# tries to avoid far jumps. When You have IF-ELSE, compiler does something like this:

Condition false -> far jump to false_condition_label

true_condition_label: instruction1 ... instruction_n

false_condition_label: instruction1 ... instruction_n

end block

If condition is true there is no jump and no rollout L1 cache, but jump to false_condition_label can be very far and processor must rollout his own cache. Synchronising cache is expensive. R# tries replace far jumps into short jumps and in this case there is bigger probability, that all instructions are already in cache.

0

I think it depends on what you prefer, as mentioned, theres no general agreement afaik. To reduce annoyment, you may reduce this kind of warning to "Hint"

Bluenuance
  • 4,813
  • 4
  • 23
  • 19
0

My idea is that the return "in the middle of a function" shouldn't be so "subjective". The reason is quite simple, take this code:

    function do_something( data ){

      if (!is_valid_data( data )) 
            return false;


       do_something_that_take_an_hour( data );

       istance = new object_with_very_painful_constructor( data );

          if ( istance is not valid ) {
               error_message( );
                return ;

          }
       connect_to_database ( );
       get_some_other_data( );
       return;
    }

Maybe the first "return" it's not SO intuitive, but that's really saving. There are too many "ideas" about clean codes, that simply need more practise to lose their "subjective" bad ideas.

Joshi Spawnbrood
  • 525
  • 6
  • 13
0

There are several advantages to this sort of coding but for me the big win is, if you can return quick you can improve the speed of your application. IE I know that because of Precondition X that I can return quickly with an error. This gets rid of the error cases first and reduces the complexity of your code. In a lot of cases because the cpu pipeline can be now be cleaner it can stop pipeline crashes or switches. Secondly if you are in a loop, breaking or returning out quickly can save you a lots of cpu. Some programmers use loop invariants to do this sort of quick exit but in this you can broke your cpu pipeline and even create memory seek problem and mean the the cpu needs to load from outside cache. But basically I think you should do what you intended, that is end the loop or function not create a complex code path just to implement some abstract notion of correct code. If the only tool you have is a hammer then everything looks like a nail.

David Allan Finch
  • 1,414
  • 8
  • 20
  • Reading graffic's answer, it rather sounds like the nested code was optimized by the compiler in a way that the executed code is faster than using multiple returns. However, even if multiple returns were faster, this optimization probably won't speed up your application that much ... :) – hangy Nov 07 '08 at 15:44
  • 1
    I don't agree - The First Law is about getting the algorithm correct. But we are all Engineers, which is about solving the correct problem with the resources we have and doing in the available budget. An application that is too slow is not fit for purpose. – David Allan Finch Dec 02 '08 at 11:06