5 ms·
To me, this only makes sense if you always read source code sequentially. Humans are not machines, and most often you will not be reading code (especially code
by glastra 11y ago
To me, this only makes sense if you always read source code sequentially. Humans are not machines, and most often you will not be reading code (especially code with branches) in a top-bottom manner.
Having multiple return statements in a method actually renders the method LESS readable. I understand the first proposal is also usually implemented with many return statements, but they could be replaced with a variable assignment, variable that is then returned at the end of the method (as in the example). If that variable is final (or whatever the C# equivalent is), that's even better.
- adamc 11y agoI don't think I fully understand your comment. Regardless of whether I've read the whole program top-down, it is definitely easier for me to understand early-exit logic in a routine than to keep the mental stack of conditionals going, particularly when (as is often the case) the early exits consist of various deviations from the "main sequence" code (e.g., validations failing or other edge-cases).
- glastra 11y agoI was speaking from a general point of view. I find early exit on validation failure acceptable, although it'd make more sense to use exceptions and not a simple return. A sufficiently complex method with 5 return statements all scattered in between to treat real cases (i.e. not failures or conditions that should raise an exception) is certainly less readable than the same functionality refactored to a single return statement at the end with the proper use of branching. Aside from readability, it also increases maintainability. What if you have to introduce a modification to your logic that applies a transformation to the result? Should you modify it in 5 places, or 1?
- SideburnsOfDoom 11y ago> What if you have to introduce a modification to your logic that applies a transformation to the result? Should you modify it in 5 places, or 1? In 1 place, clearly. The multiple-return version would require a bit more refactoring at this point, either extracting another method or introducing the "return value" state var at that point. Why not code it with single return up front? Simple: most likely, You Aren't Going To Need It. The YAGNI principle says to make the code more complicated when you need to, not before.
- SideburnsOfDoom 11y ago> A sufficiently complex method with 5 return statements ... is certainly less readable than the ... single return statement at the end version In all cases? How can you even measure that? How can you do it in a way that's free of bias? If you've never used a style, of course you will find it harder. Dogmatic assertions that boil down to "what I'm used to is objectively better because of how it feels to me" are IMHO harmful.
- glastra 11y agoI cannot measure that on anyone else other than myself. This is a place to express opinion. I've read (and sadly written) enough code in both styles to know what _I_ (and all the peers I've bothered to ask with concrete examples, for that matter) find easier to understand, but there's of course all kinds of bias in there as well. Taking comments in HN as fact or truth is harmful, and (replying to your other comment) waving acronyms around is equally harmful, if not more. You can't possibly assert that writing code in one or another way is easier or harder, or that the code is "more complicated" (precisely what we don't seem to agree on). To be honest, I find it easier to write methods with single return statements (and exceptions to handle... well, exceptions[^1]). It all seems clearer in a "stream of thought" kind of way. Engrish is hard, sorry. [^1]: Early returns are exceptions for lazy coders.
- SideburnsOfDoom 11y ago> You can't possibly assert that writing code in one or another way is easier or harder In general, of course not. I think that both single-return and multiple-return styles can be valid and readable. But of course both can be obfuscated. But give me a particular piece of logic and I might give an opinion on which style I would use for it. & if you think YAGNI is harmful, you should see the pointless code from people who have never thought that way!
- conceit 11y agothe term callback hell comes to mind, although I'm not sure that's the entire problem you quoted
- phamilton 11y ago"Oh... We call function foo. Let's go see what function foo returns. (Scroll to the end of the function)" With a single return, I can at least follow that thread fairly easily and sometimes it's just a few lines back in a large function. With many returns, I'm forced to start at the beginning of the function. There a dozen or so other culprits that make this difficult. Assignment in a block can be just as bad, for example, since I can't know which assignment occured without looking at all of them.
- SideburnsOfDoom 11y ago> sometimes it's just a few lines back in a large function Large functions that have both side effects and return values are themself the readability problem. Early return is not, it is a succinct way to express some functions with return values.
- glastra 11y agoExactly. See single return statement, highlight variable, see branch structure at a glance, ???, profit.
- Vaskivo 11y agoI disagree. The function signature should be explicit about what it does and returns. If it has a static/defined return type I know what I can expect from it. The function name should also be explicit about what it does and returns. Scrolling down to the end just to see a 'return books' statement is usually useless. If I need to read the whole function, I'd rather have early exits instead of nested ifs. It's easier to read because it follows the logic of "if (such and such condition): nothing else to do -> return;"
- camgunz 11y agoI like this ergonomics argument, particularly from a reader's perspective. But having had to read some single return value code recently, I found that the return value returned at the end of the function was rather unhelpful; it usually boiled down to "return rv;". I then had to go back up to the top of the function and follow through the nest of passed conditionals and side effects, fall throughs, and failed conditionals to see how "rv" was modified throughout the function. The non-linearity cost me a lot more thought, whereas with multiple return value code the failed conditionals are "tossed" out of my head very quickly. I think, given that you almost always end up reading the whole function anyway (which is probably good), linear is better than non-linear and consistency (bail early) is better than inconsistency (anything goes) when it comes to error handling.
- AlisdairO 11y agoCompletely agreed. I think early returns deep in the logic of a method can be problematic, but I think early returns at the top of a method before you get to the meat of the logic are very readable.
- SideburnsOfDoom 11y ago> Having multiple return statements in a method actually renders the method LESS readable Does it? I don't find it that. However, if you have never read code of this style before, it will be unfamiliar to you and you will find it less readable. But you can overcome this with practice. I would rather say that it depends - both are valid styles, sometimes it's more readable to use multiple return statements and sometime less. As a programmer you know both and pick the option that is better suited to the problem at hand.
- Bognar 11y ago> Having multiple return statements in a method actually renders the method LESS readable. I 100% disagree. Introducing a variable instead of using multiple returns means I now have to keep track of yet another variable throughout the entire rest of the method. Is it modified before it's returned? Gotta read the whole thing to find out. Early returns reduce the complexity of a method by reducing the number of possible states as you move through the method.
- glastra 11y ago> Early returns reduce the complexity of a method by reducing the number of possible states as you move through the method. As I said in other comments, early returns for exceptions and bad input are fine. They are exceptions, though, not return statements. Go ahead and use return if you want/can, although I wouldn't. If it's not for an exception or input validation failure, then we have something like: "Alright, so here we do this, unless this, that and that other condition over there were true earlier, because the method would've returned then..." I find that the complexity to keep track of with this approach is pretty much the same, or even more depending on the branching.
- cballard 11y agoSwift solves this with "guard" statements, which must return if their condition fails. This is most commonly used in combination with converting optional values to non-optional values, to prevent pyramids of doom. guard let something = maybeSomething else { return ... }
- deleted 11y ago[deleted]
- btilly 11y agoI have seen this claimed many times, and I've never seen any research for it that in the end came down to more than personal prejudice. On the other hand http://www-cs.stanford.edu/people/eroberts/papers/SIGCSE-1995/LoopExits.pdf http://www-cs.stanford.edu/people/eroberts/papers/SIGCSE-199... offers concrete reasons why early returns make sense.