Try-catch style



  • Good day

    I'm looking for some guidance and/or opinions regarding good style when using try-catch blocks.  When (as is more often than not the case) the statement that may throw the exception is followed by other statements to be executed if and only if said exception is not thrown, I see a lot of this pattern:

    try {
        //statement that may throw exception here
    }
    catch(Exception e) {
        //statements to deal with failure here
        return;
    }
    //statements to be executed if and only if exception is not thrown here

    Particularly when there are multiple instances of this pattern in a method nested at various levels I'm not comfortable with the proliferation of exit points because it means that I can't trace an execution path through the method simply by reading branching/looping conditions and observing braces and indents - I now have to check every block for return statements.  Is it just me who has a problem with this?  Unfortunately all the alternatives I can think of are worse.  Any ideas?

    Regards
    me



  •  Isn't this the same "problem" as doing:

    function asdf()
    {
        // code...
        if (x) {
            return x;
        }
    
    // more code
    
    if (y) {
        return y;
    }
    
    // more code
    
    return z;
    

    }



    Return statements can be anywhere in the function body.  Your best bet is to get an editor that clearly highlights return statements.



  • catch(Exception e) {
        //statements to deal with failure here
        return;
    }

    This is bad form.  Your function should only catch the exception if it can actually deal with it and continue on successfully.  You could catch it, do some last minute cleanup and rethrow (or throw a different exception).  Though cleanup would be better placed in a finally block if your language supports it.  Doing a normal return implies non-exceptional execution.

    The type of code above would make sense if you didn't want your exceptions crossing a module boundary.  Then you may have to return an error code instead.

    Otherwise, you wouldn't catch at all (though depending on the language, you may need a finally block to do function cleanup).  You just let the exception wind up the stack.  So your function either succeeds or passes an exception.

    In a language with destructors (destructors can clean up any allocations when an exception is thrown)

    f()
    {
      s1;
      s2;
      s3;
    }

    Without  destructors:

     f()
    {
      try {
        s1;
        s2;
        s3;
      }
      finally {
        // clean up
      }
    }

    If you have an optional statement in your function, then you can do try/catch and handle the problem as you wish.  Otherwise let the upper levels decide what to do in the case of error. 

    If you look at David Abrahams' exception safety guarantees (http://www.boost.org/community/exception_safety.html) he describes 3 level of exception safety:

    basic: don't break the class and don't leak resources.
    strong: roll-back semantics.  Put everything back the way it was.
    no-throw:  function guarantees it will not throw

    The basic guarantee is what I described above.  Clean up by using  RAII or finally clauses so nothing is leaked.  The strong guarantee is usually done with the create and swap method.  You create a temporary object with all the updated values.  If that does not throw, then following statements swap the contents with safe instructions (e.g. simple pointer assignment).  If there is an exception, the temporary will be removed either by its destructor or the garbage collector.



  • Not sure if this is obvious, but an exception should never be used where regular logic would work. Perhaps some of the try catch blocks can simply be removed in place of other conditionals.

    Otherwise I agree I'm not a big fan of the return in the catch block -- although I do prefer the use of return in general over if/then or big if blocks.



  • :belt_onion:

    @chebrock said:

    Not sure if this is obvious, but an exception should never be used where regular logic would work.

    A rule of thumb of mine is to only use exceptions if your function is unable to perform the actions it had promised to do. As already mentioned: only use catch if you can actually do something about it. Don't be afraid to use try{ } finally { } pattern a lot (without the catch): if an underlying function throws, you can clean up in the finally and you leave the exception handling to a higher layer.



  • @bjolling said:

    @chebrock said:

    Not sure if this is obvious, but an exception should never be used where regular logic would work.

    A rule of thumb of mine is to only use exceptions if your function is unable to perform the actions it had promised to do. As already mentioned: only use catch if you can actually do something about it. Don't be afraid to use try{ } finally { } pattern a lot (without the catch): if an underlying function throws, you can clean up in the finally and you leave the exception handling to a higher layer.

    True. I'd rather have a function throwing an exception than having it eat the exception silently. This is exactly the kind of situation t hat usually leads to TRUE, FALSE, FILE_NOT_FOUND situations.


  • @DogmaBites said:

    Otherwise, you wouldn't catch at all (though depending on the language, you may need a finally block to do function cleanup).  You just let the exception wind up the stack.  So your function either succeeds or passes an exception.

     

    This is all well and good until it isn't all well and good.  If you are writingGUI code for instance you can' just allow the exception to keep going up the stack unless you want your users to stop using your product.


  • :belt_onion:

    @tster said:

    @DogmaBites said:

    Otherwise, you wouldn't catch at all (though depending on the language, you may need a finally block to do function cleanup).  You just let the exception wind up the stack.  So your function either succeeds or passes an exception.

     

    This is all well and good until it isn't all well and good.  If you are writingGUI code for instance you can' just allow the exception to keep going up the stack unless you want your users to stop using your product.

    You can't swallow your exception somewhere in between either. If your application doesn't produce the correct results and doesn't indicate somehow an exception has occured, users will stop using your product before your can say "bug report".


  • :belt_onion:

    @aassddff said:

    Particularly when there are multiple instances of this pattern in a method nested at various levels I'm not comfortable with the proliferation of exit points...

    Nobody really answered this part of the OP's question, so I'll have a first go at it.

    I think your question should be the other way around. Instead of nesting try-catch-finally blocks, I tend to create separate functions for simplicity's sake. Try-catch actually helps you (e.g. with many exit points) to exit cleanly under all circumstances when dealing with complex functions.

    try{ someting that can fail; }

    catch (the specific exception you can handle)  { ; }

    finally { clean up your resources; }

    return;

     

    My 2 year old daughter also mentions:

    rd ftyjtkiooplo414kh(-sesdfg



  • @tster said:

    @DogmaBites said:

    Otherwise, you wouldn't catch at all (though depending on the language, you may need a finally block to do function cleanup).  You just let the exception wind up the stack.  So your function either succeeds or passes an exception.

     

    This is all well and good until it isn't all well and good.  If you are writingGUI code for instance you can' just allow the exception to keep going up the stack unless you want your users to stop using your product.

    I'm sorry, I wasn't clear.  You should let it go up until you can actually deal with it.  Catching it in the middle, where you don't know what you should because of the exception is bad form.  It's usually the upper levels that know whether it should just be logged, throw up a dialog saying "Sorry Dave, I can't do that." or try an alternate method.

    The OP looked like middle level code simply eating the exception and going on with life. 



  • @DogmaBites said:

    @tster said:

    @DogmaBites said:

    Otherwise, you wouldn't catch at all (though depending on the language, you may need a finally block to do function cleanup).  You just let the exception wind up the stack.  So your function either succeeds or passes an exception.

     

    This is all well and good until it isn't all well and good.  If you are writingGUI code for instance you can' just allow the exception to keep going up the stack unless you want your users to stop using your product.

    I'm sorry, I wasn't clear.  You should let it go up until you can actually deal with it.  Catching it in the middle, where you don't know what you should because of the exception is bad form.  It's usually the upper levels that know whether it should just be logged, throw up a dialog saying "Sorry Dave, I can't do that." or try an alternate method.

    The OP looked like middle level code simply eating the exception and going on with life. 

     

    Yes, I was just wanting to point out that sometimes you are writing code that can't pass exceptions to somewhere else.  The general idea of exception is exactly that.  Something to pass along until something knows what to do with it.



  •  You are stepping into a "holy war" when starting a discussion about "single exit point" vs "multiple exit point" which I believe what your post is really regarding. Personally I go with "single exit point" and only have a return statement at the end of the method.

     Talking specifically about a try/catch block IMHO having a return statement in a catch block shows fundamentally flawed exception handling. As posters above have mentioned if the code knows how to handle the exception then handle it and continue on, if it does not know how to handle it (i.e. what business rules apply to receiving that exception) it should bubble the exception up and eventually that exception would reach something that knows how to handle it. If nothing knows how to handle it then it is more than likely a fatal exception.



  • @mjparme said:

    You are stepping into a "holy war" when starting a discussion about "single exit point" vs "multiple exit point" which I believe what your post is really regarding. Personally I go with "single exit point" and only have a return statement at the end of the method.

    Wow, your code must be an overly-verbose mess of slop from trying to enforce such a useless superstition on yourself. 



  • @mjparme said:

    Personally I go with "single exit point" and only have a return statement at the end of the method.
    Lemme guess, your functions often end like this:

    }
    }
    }
    }
    }
    }
    return;
    }



  • @bstorer said:

    @mjparme said:
    Personally I go with "single exit point" and only have a return statement at the end of the method.
    Lemme guess, your functions often end like this:

                }
    }
    }
    }
    }
    }
    return ret;
    }
    FTFY


  • @morbiuswilters said:

    @mjparme said:

    You are stepping into a "holy war" when starting a discussion about "single exit point" vs "multiple exit point" which I believe what your post is really regarding. Personally I go with "single exit point" and only have a return statement at the end of the method.

    Wow, your code must be an overly-verbose mess of slop from trying to enforce such a useless superstition on yourself. 

     

     

    Single exit point is overly-verbose??? Slop? I think you have it backwards, multiple-exit point is far sloppier than single-exit point.



  • @bstorer said:

    @mjparme said:
    Personally I go with "single exit point" and only have a return statement at the end of the method.
    Lemme guess, your functions often end like this:

                }
              }
            }
          }
        }
      }
      return;
    }

     

     

    Umm, no, not at all. Why would my methods end like that?



  • @mjparme said:

    Umm, no, not at all. Why would my methods end like that?
     

    int myfunction() {
      int r;
      r = doSomething();
      if (r==SUCCESS) {
        r = doSomethingElse();
        if (r!=ERROR) {
          r =doYetAnotherThing();
          if (r==SUCCESS_TOO) {
             ...

    instead of

    int myfunction() {
      int r;
      r = doSomething();
      if (r!=SUCCESS) {
        return r;
      }

      r = doSomethingElse();
      if (r==ERROR) {
        return r;
      }

      r =doYetAnotherThing();
      if (r!=SUCCESS_TOO) {
        return r;
      }
      ...



  • @mjparme said:

    @bstorer said:

    @mjparme said:
    Personally I go with "single exit point" and only have a return statement at the end of the method.
    Lemme guess, your functions often end like this:

                }
    }
    }
    }
    }
    }
    return;
    }

     

     

    Umm, no, not at all. Why would my methods end like that?

    ... when they can end like this?

    [code]
      the_end:
        return ret;
    }
    [/code]
    


  • @mjparme said:

    Talking specifically about a try/catch block IMHO having a return statement in a catch block shows fundamentally flawed exception handling. As posters above have mentioned if the code knows how to handle the exception then handle it and continue on, if it does not know how to handle it (i.e. what business rules apply to receiving that exception) it should bubble the exception up and eventually that exception would reach something that knows how to handle it. If nothing knows how to handle it then it is more than likely a fatal exception.

    But what if the suggested way of handling the exception is to return some pre-defined default value?



  • @mjparme said:

    Single exit point is overly-verbose??? Slop? I think you have it backwards, multiple-exit point is far sloppier than single-exit point.

    Nonsense. An unnecessary adhesion to the single-exit philosophy results in more nested code, more break and continue statements (unless you consider those to be multiple-exit, too, in which case you've just created even more nesting), and more local variables to hold flags and return values. And how, Mr. Single-Exit-Point-Proponent, do you throw exceptions? Are those not exit points, too? Let me give you a couple pseudocode examples; you tell me which of the following is cleaner and more readable:

    int multiple_exit_fib (int n)
    if n < 0
    return ERR
    if n == 0
    return 0
    if n == 1
    return 1
    return multiple_exit_fib(n - 1) + multiple_exit_fib(n - 2)

    int single_exit_fib (int n)
    if n < 0
    ret = ERR
    else if n == 0
    ret = 0
    else if n == 1
    ret = 1
    else
    ret = single_exit_fib(n - 1) + single_exit_fib(n - 2)
    return ret



  • @bstorer said:

    int single_exit_fib (int n)
    if n < 0
    ret = ERR
    else if n == 0
    ret = 0
    else if n == 1
    ret = 1
    else
    ret = single_exit_fib(n - 1) + single_exit_fib(n - 2)
    return ret



    This example is much cleaner IMHO. Much rather use the else-if than the ifs with multiple returns. So in addition to being an evil multiple exit point person you are also an evil no bracket around single line control structure person:-)

    Yes, exception handling is an exit point although I find that a moot point in any multiple-exit vs single exit point discussion because exception handling code is readily apparent whereas it is quite easy to miss a "return" statement amonst a lot of other code. Break and continue aren't method exit points so I am not sure how those are relevent.

     Plus, exception handling, break, and continue are tired arguments from the multiple exit point camp. Can you come up with something original? :-)



  • @mjparme said:

    Single exit point is overly-verbose??? Slop? I think you have it backwards, multiple-exit point is far sloppier than single-exit point.

    Do you know what overly-verbose means?  It means you spend more time nesting and contorting the code so you can have one exit point.  Multiple exit point is not sloppier and you aren't going to find many decent software engineers who advocate for single exit point. 



  • @mjparme said:

    This example is much cleaner IMHO. Much rather use the else-if than the ifs with multiple returns.
    It's far less readable. You have to traverse the entire function just to know exactly what happens when n is, for example, less than zero. The multiple exit version makes it clear that no further work is done. And yes, this case may not be complex to traverse, but when that function is even twenty lines of code, it gets unpleasant.
    @mjparme said:
    So in addition to being an evil multiple exit point person you are also an evil no bracket around single line control structure person:-)
    No, I'm a Python person. Besides, it's pseudocode.
    @mjparme said:
    Yes, exception handling is an exit point although I find that a moot point in any multiple-exit vs single exit point discussion because exception handling code is readily apparent whereas it is quite easy to miss a "return" statement amonst a lot of other code.
    So you'd be okay with me doing this:

    if n < 0
    throw ArgumentException("n must be greater than or equal to zero")
    How is that different?
    @mjparme said:
    Break and continue aren't method exit points so I am not sure how those are relevent.
    Break and continue also create multiple paths, which is in violation of the same structured programming theorem that advocates single exit points. If you advocate a rule, it might help to understand the actual reasoning behind the rule instead of clinging to it blindly.
    @mjparme said:
    Plus, exception handling, break, and continue are tired arguments from the multiple exit point camp. Can you come up with something original?
    Yes, important, relevant points often come up frequently. I wonder why that is? I suppose I could come up with some insane theory about how multiple exit points make a programmer live longer, if you'd like.



  • @mjparme said:

    Yes, exception handling is an exit point although I find that a moot point in any multiple-exit vs single exit point discussion because exception handling code is readily apparent whereas it is quite easy to miss a "return" statement amonst a lot of other code.

    O_o

     

    If you are not able to find return statements, how are you finding exceptions?  Shouldn't this be something your IDE handles instead of something that changes the structure and readability of your code? 



  • @bstorer said:

    If you advocate a rule, it might help to understand the actual reasoning behind the rule instead of clinging to it blindly.

    Why all the animosity? I am not trying to force you to use single-exit point, I prefer it for my own coding. I believe it makes code MORE readable, less error prone, and much easier to refactor. If you don't agree with me so be it. I don't think I have ever had an issue where my methods had to use an insane amount of nesting to achieve single-exit point. I am not sure where that belief comes from.

     I understand that single exit point is more a structured programming idea rather than OO as OO languages have constructs that render it mostly impossible to achieve 100% of the time (i.e. exception handling). However, that doesn't stop me from using at when at all possible and I would say 95% of the time it is acheivable. If I run across a situation where I have to/need to use multiple exit points I don't lose sleep over it.

     



  • @mjparme said:

    Why all the animosity?
    There's no animosity. I doubt you said to yourself one day, "You know, I think I multiple exit points are a bad idea." You undoubtedly picked it up somewhere, and I wonder whether you understand why it was created in the first place. That you don't understand how continues and breaks factor into it leads me to believe you do not.
    @mjparme said:
    I don't think I have ever had an issue where my methods had to use an insane amount of nesting to achieve single-exit point. I am not sure where that belief comes from.
    Anybody else feel like finding an example? I don't have any readily at hand, and I don't want to bother digging through the codebase to find one.



  • @bstorer said:

    Anybody else feel like finding an example?
     

     

    Some gawdaweful Crystal Reports code:

     

    if not(isnull({PI_Contract.Renewed from Contract ID Link})) then 0 else
        if isnull({PI_Contract.PI_Contract Id Link}) then 0 else
            if isnull({PI_Contract.Active}) then 0 else
                if isnull({PI_Contract.Accounting Approved}) then 0 else
                    if isnull({PI_Contract.Contract Start Date}) then 0 else
                        if isnull({PI_Contract.Contract End Date}) then 0 else
                            if isnull({PI_Contract.Deleted}) then (
                                if {PI_Contract.Accounting Approved} and {PI_Contract.Active} and ({PI_Contract.Contract Start Date} <= {?DateTo}) and ({PI_Contract.Contract End Date} >= {?DateFrom}) and ({PI_Contract.Contract Start Date} >= {?DateFrom}) then (
                                    shared numbervar NewContractSales := shared numbervar NewContractSales + ({Order_.Total} * {PI_Order_Recognition_Split.Split Percentage} / 100);
                                    shared numbervar NewContractSalesTot := shared numbervar NewContractSalesTot + ({Order_.Total} * {PI_Order_Recognition_Split.Split Percentage} / 100);
                                    shared numbervar NewContractSales;)
                                else 0)
                            else (
                                if not({PI_Contract.Deleted}) and {PI_Contract.Accounting Approved} and {PI_Contract.Active} and ({PI_Contract.Contract Start Date} <= {?DateTo}) and ({PI_Contract.Contract End Date} >= {?DateFrom}) and ({PI_Contract.Contract Start Date} >= {?DateFrom}) then (
                                    shared numbervar NewContractSales := shared numbervar NewContractSales + ({Order_.Total} * {PI_Order_Recognition_Split.Split Percentage} / 100);
                                    shared numbervar NewContractSalesTot := shared numbervar NewContractSalesTot + ({Order_.Total} * {PI_Order_Recognition_Split.Split Percentage} / 100));
                                    shared numbervar NewContractSales;);



  • I don't think simply preferring one or the other is correct.  In some cases, where you have some postscript code that has to run, then single exit is better.  However, when you are simply calculating a value I think it is more clear to simply return when you are done.  Finding the last assignment is just as hard as finding the last return.

     If you are not using exceptions, then something like this at the beginning is easy to understand

    if ( !sanity_check)
        return ERROR_CODE;

    Otherwise, you add a nesting level to your function. 



  • @waco.huber said:

    Some gawdaweful Crystal Reports code:
    Dear God, you have to work with that monstrosity?! I'll pray for you.



  • @mjparme said:

    I understand that single exit point is more a structured programming idea rather than OO

    Single-exit is a programming idea, but not an instrinsically superior one. Neither is multi-exit point. The mistake isn't either using one or the other, the mistake is actively changing your coding habits to absoluetly ensure your codes uses one.

    Single-exit is not the superior method, nor the inferior one. It depends, and nobody cares. The slop argument is bunk; the code clairty argument is equally bunk.

    @mjparme said:

    OO languages have constructs that render it mostly impossible to achieve 100% of the time

    This is never a problem. If it becomes one, then there's something else that's the real problem, such as an oversized and/or too-overloaded function.

    @mjparme said:

    However, that doesn't stop me from using it when at all possible and I would say 95% of the time it is acheivable.

    You mean that you make an effort to change your code to prevent multi-exits? That's a waste of time. I suppose you're used to it by now, but you've achieved nothing. As I said, it's this mentality -- not the method itself -- that is the mistake. Single-exit is not the golden hammer.



  • @dhromed said:

    Single-exit is a programming idea, but not an instrinsically superior one. Neither is multi-exit point. The mistake isn't either using one or the other, the mistake is actively changing your coding habits to absoluetly ensure your codes uses one.

    Single-exit is not the superior method, nor the inferior one. It depends, and nobody cares. The slop argument is bunk; the code clairty argument is equally bunk.

    I have to disagree here.  Coding for the purpose of preserving a single exit point results in bloated, unreadable code.  Several examples have been posted, but ultimately the result is always the same: with multiple exit points you can jump out of the function and know that whatever follows after is only executed if the return condition was not met.  With single exit point the condition ends up wrapping the rest of the code.  When you get several levels of this, you end up with really insane "arrow code".  The fact is, this is less readable because you have to trace through the entire function to make sure that nothing else is executed under a certain condition.  When you follow the "get out as soon as you can" rule, the programmer who is reading the code knows nothing else is going to happen in that function.



  • @morbiuswilters said:

    I have to disagree here.  Coding for the purpose of preserving a single exit point results in bloated, unreadable code.  Several examples have been posted, but ultimately the result is always the same: with multiple exit points you can jump out of the function and know that whatever follows after is only executed if the return condition was not met.  With single exit point the condition ends up wrapping the rest of the code.  When you get several levels of this, you end up with really insane "arrow code".  The fact is, this is less readable because you have to trace through the entire function to make sure that nothing else is executed under a certain condition.  When you follow the "get out as soon as you can" rule, the programmer who is reading the code knows nothing else is going to happen in that function.
    I agree with this wholeheartedly, but I just want to add one further point. Nobody in favor of multiple exit points is advocating that every function must have multiple exit points. Such a stance would be completely insane. We just don't see a reason to chain yourself to a rule when breaking it results in better code.



  • @bstorer said:

    We just don't see a reason to chain yourself to a rule when breaking it results in better code.
     


     



  • Thank you everyone for contributing to the discussion to date.  There have been quite a number of good points made, I think.  I'm still working through the implications of all the ideas.



  • I am pretty sure the origin of "single entry/exit points" applied mainly to the three basic structures and only indirectly to functions.  The idea is that you can take the flowchart of, say, a loop and wrap it with a box with a single entry/exit point and abstract it away.  Functions are similar in that you have a single entry point (the first instruction of the function - never jumping into the middle of a function) and a single exit point (the single instruction that you jump to when the function returns).  It doesn't matter how many return statements you have inside the function; they always lead to the same point.  That is, when your function is drawn as one box in a flowchart, there is only one line in and one line out.  Exceptions, coroutines, and often gotos do break this "rule," but multiple return statements do not.

    That's my rationalization, anyway. :)

     



  • Sorry for the late reply...

    What about using functions for the blocks?

    void myFunc(...) {
      try {
           func1(...);
           if (...) { 
              func2(...);
           }
           ...
      } catch ([Some[Other]]Exception e) {
         handle error here
      } finally {
         mandatory cleanup/followup code here
      }
    }
    

    void func1(...) throws SomeException {
    statement1;
    statement2;
    ...
    }

    void func2(...) throws Some[Other]Exception {
    statement1;
    statement2;
    ...
    }



  • @dhromed said:

    return statement preferences...

    @morbiuswilters said:

    return statement preferences...

    @bstorer said:

    return statement preferences...

    I don't think I really appreciated until this point just how passionate people are on this particular topic. Nor do I think I realized how much people assume that if you give one example of paradigm X (for instance, only have one return point) you insist always on that paradigm.  I think the correct answer is "use the construct that makes the most sense for the given situation" because the other general rule of thumb I have observed is "one size fits none."

    Regarding return points: my general approach is - if I can see the entire function on the screen I don't mind multiple return points. If the function is 1000 lines long (and I've had to maintain code like this...terribly factored in my opinion) then having a single return point is a godsend when you're looking at an if...else block with conditions that make some assumptions because two pages up a return took care of the other possibilities (maybe not a problem, perhaps, if there were actually comments in the code...).



  • @too_many_usernames said:

    I think the correct answer is "use the construct that makes the most sense for the given situation" because the other general rule of thumb I have observed is "one size fits none."
     

    Yesh.



  • I personally don't really care either way between multi/single exit points, i just like to write clean code and don't give a toss about the amount of exit points.

    However if I would have to make a decision I would say multiple exit points.

    I just love using early exits like

    [code]if (!is_numeric($var)) return false;[/code]

    Although it could just as easily have been a throw of a exception of course.

    But in the end I think most of the code I've written, have used only single exit's. The reason for this is simple, I'm a strong believer in writing single purpose methods. I would much rather write 5 methods that only have 3 lines then one method that has 10 lines. 

    There are of course always exceptions, but with the 5 methods I can be much more specific in their naming, making the using of the object interface much more intuitive.

     



  • @too_many_usernames said:

    I don't think I really appreciated until this point just how passionate people are on this particular topic.
    Until now I wasn’t even aware that there is an issue with the number of function exit points.



  • @Bombe said:

    @too_many_usernames said:

    I don't think I really appreciated until this point just how passionate people are on this particular topic.
    Until now I wasn’t even aware that there is an issue with the number of function exit points.

    Me neither, it's funny what people will get worked up about.

    However, since reading this I've looked at some of my old code and been amazed at the lengths I've gone to to achieve a single exit point.  I didn't realise I was doing this, I think it's a hangover from learning stuctured programming in BBC Basic.  When I allow myself to have multiple returns, the code is a lot clearer and less indented.  Mmm, educational.



  • @Bombe said:

    @too_many_usernames said:

    I don't think I really appreciated until this point just how passionate people are on this particular topic.
    Until now I wasn’t even aware that there is an issue with the number of function exit points.

    Most people need to be bitten by it to become aware :)

    While I'm not religious about it, I do approve of the desire to try and limit the number of exit points as much as possible.
    Certainly no more than a single exit point should exist for normal process flow, if there is that's a sure sign the method has multiple responsibilities and needs to be split up.

    Makes debugging and maintenance a lot easier to perform.



  • Personally, I think we should be far more concerned with the number of function entry points.



  • Does that mean that you would do this

    Sub Something(param1 as string)
    If param1 is nothing then
    throw new argumentnullexception
    else
    ... do stuff
    end if

    Multiple exit points are sometimes necessary.  I have noticed that I sometimes avoid them, sometimes I don't.  I wish I would decide...



  • @piptheGeek said:

    Does that mean that you would do this

    Sub Something(param1 as string)
    If param1 is nothing then
    throw new argumentnullexception
    else
    ... do stuff
    end if

    Multiple exit points are sometimes necessary.  I have noticed that I sometimes avoid them, sometimes I don't.  I wish I would decide...

     

    Don't worry or even think about exit points, just write clean, readable code.



  • @merphle said:

    Personally, I think we should be far more concerned with the number of function entry points.

     

    Unless you're talking about a language with first-class continuations...

    Or my sarcasm detector is broken.



  •  I agree with DogmaBites... don't catch it if you can't continue processing.


Log in to reply