4 ms·
"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 thre
by 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.
- phamilton 11y agoI come from an FP background, and so I tend to avoid multiple assignment as well. In such a scenario, there's a single line that assigns rv. Each of the variables used in assigning rv are each assigned just once. I can follow the graph fairly easily until I get to the bit I need. Often its something like "what conversion rate for currency are we using?" and following that chain gets me there quickly.
- camgunz 11y agoYeah, I can definitely see how if you're disciplined it can be effective. But in my case, I've seen integer return values hold status codes from multiple modules and libraries, file handles, and enum values all in the same function just to twist everything together so that no matter where it stops executing, "rv" has some kind of value so that the ending "return rv" won't just return success. It was total madness, and it's really hard to do anything as complicated and fragile as that with early returns. I will admit though that no programming style will sufficiently protect against bad coding :). I'm sure even if this person did everything I advised, they'd still find a way to overcomplicate and confuse things. So maybe the issue is moot, or at least bigger than style.