|
I consider early return easier to work with than mutation.code:
code:
|
# ? Feb 29, 2016 21:21 |
|
|
# ? May 17, 2024 20:39 |
|
fleshweasel posted:I consider early return easier to work with than mutation. I edited in something similar in my previous post: LeftistMuslimObama posted:
|
# ? Feb 29, 2016 21:27 |
|
Yeah, I don't really get it. If anything single point of return takes more effort to trace. In strict single point of return, you often end up doing something where you calculate your return value, but then just wait to the end to return it, which just adds more logic you have to look at to make sure you're not modifying it later somehow. That's not to say that single point of return is a garbage idea. It's just like any sort of design rule. Follow it most of the time and break it when it makes sense to do so.
|
# ? Feb 29, 2016 21:31 |
|
fleshweasel posted:I consider early return easier to work with than mutation. Yeah pretty much. The first case is a very common pattern and more clear than the second case, especially when there are several preconditions. There's a mindset some people have where they would rather reduce everything to a rule rather than apply judgement to specific cases. Actually this reminds me of an old coding horror in this code base I used to work with, where multiple styles were mixed with reckless abandon. code:
code:
HappyHippo fucked around with this message at 21:39 on Feb 29, 2016 |
# ? Feb 29, 2016 21:36 |
|
I tend to find that "return once" code tends to get way more Rube-Goldbergesque anyway, since you start having to introduce flag variables and weird nulls (or Options/Maybes if you're lucky) to direct control flow. It introduces more points of failure into the function, which tends to suppress any benefit you gain from making it exit in one place. Granted, there are cases where escaping early is detrimental to clarity, it's a context thing. I don't think "always escape ASAP" is great advice either. I really like Rust's way of handling returns where most expressions return a value unless squelched. It tends to make you think in a way that looks like "what will the result of this expression be at the end", which lets you compose things really easily. Though even though I love it and use it all the time, embedding arbitrary expressions in type constructors may be a horror. code:
code:
code:
Linear Zoetrope fucked around with this message at 21:42 on Feb 29, 2016 |
# ? Feb 29, 2016 21:37 |
|
LeftistMuslimObama posted:Probably just me being a terrible programmer, but wouldn't this mean that working with lists of, say, structs would be really painful. Like, if I need to make a process table under these rules I'd have to pre-allocate an array of however many at startup and then be stuck with those, yeah? If I only end up needing 3 out of the 64 I allocated in a particular run, I've wasted a lot of memory. If I bump up against the ceiling of 64, I have to write a bunch of code to deal with that. I don't know what's the environment in which this rules are enforced, but in business programming (ie, doing stupid boring things like preparing payrolls and balancing bank accounts) you don't use a lot of data structures. The most complicated thing you run into is usually an array of a pre-fixed size, and all the fancy data relationships are usually in the database. In this kind of environment, it actually makes sense to ban dynamic allocation. It is not needed, and it can introduce nasty bugs. Fake edit: actually, if you have the misfortune of having to use COBOL, you simply don't even have the option to use dynamic allocation. Period.
|
# ? Feb 29, 2016 21:54 |
|
Dr. Stab posted:Yeah, I don't really get it. If anything single point of return takes more effort to trace. Nah, just do this: code:
|
# ? Feb 29, 2016 22:07 |
|
Jsor posted:Granted, there are cases where escaping early is detrimental to clarity, it's a context thing. Dr. Stab posted:That's not to say that single point of return is a garbage idea. It's just like any sort of design rule. Follow it most of the time and break it when it makes sense to do so.
|
# ? Feb 29, 2016 22:15 |
|
X++ code:
quote:check* A Boolean method that checks a condition. If the condition is not fulfilled, it must put a warning on the Infolog, and return false. As always I like to mention that the company who wrote this bills for $350/hr, plus they charge a library package fee of something like $200,000 initially, and $60,000/yr for updates. And they maintain rights to customer code they write. I need to get in on that.
|
# ? Feb 29, 2016 22:16 |
|
I normally like early return, especially for "bail early in error situations", but there's one situation where I end up regretting it. When debugging, I often find it useful to temporarily add in some logging to a function, like "called foo with parameter 3", "foo returned 7". With multiple return, it's a (minor) annoyance to add this in because the outbound logging has to go into multiple places (or I have to rename foo to foo_inner and make a wrapper).
|
# ? Feb 29, 2016 22:18 |
|
Qwertycoatl posted:I normally like early return, especially for "bail early in error situations", but there's one situation where I end up regretting it. When debugging, I often find it useful to temporarily add in some logging to a function, like "called foo with parameter 3", "foo returned 7". With multiple return, it's a (minor) annoyance to add this in because the outbound logging has to go into multiple places (or I have to rename foo to foo_inner and make a wrapper). If you were working in Python, you could just make a decorator that logs parameters and return values, and slap that decorator around whatever function you're debugging at the moment. Which is basically what you suggested in the parenthetical. I miss Python. Okay, what I really miss is functions as first-class objects. Java is not an awful language, but it's pretty far from the kind of language I actually like.
|
# ? Feb 29, 2016 22:20 |
|
TooMuchAbstraction posted:If you were working in Python, you could just make a decorator that logs parameters and return values, and slap that decorator around whatever function you're debugging at the moment. Which is basically what you suggested in the parenthetical. you can do effectively the same thing in java with aspectj or whatever
|
# ? Feb 29, 2016 22:39 |
|
fleshweasel posted:This may be the worst can of worms to open, but is there any hard evidence that connects the use of multiple return with increased defects? No. I haven't done the history research to know where this bad idea comes from or how it ended up in MISRA, but I can guess. Structured programming (e.g. "gotos bad" --famous dude) appeared on the scene about the same time as Hoare logic (aka axiomatic semantics) just prior to 1970. I believe one line of argument in favor of structured programming centered on the fact that Hoare logic proved you could easily reason about it, while you couldn't do so easily with gotos. A side effect of this argument, because typical formulations of Hoare logic assumed a single return to simplify its presentation, was the belief that multiple returns must be hard to reason about too. This was false, and it's quite easy to fix up Hoare logic to handle multiple returns trivially, but of course that required actually understanding what you're talking about instead of just cargo-culting poo poo. And so I think we see this bit of sage advice handed down the generations in standards documents, backed by grey beards remembering the structured programming wars, and everyone not willing to think deeply about its foundation or justification.
|
# ? Feb 29, 2016 22:42 |
|
More: A first you might just look at the line numbers and the closing brace and think hey a 2,100 line class is bad but that's not that uncommon. No. That's a single method in a single class. To tie that into the single/multiple points of return: trying to trace changes in a single point of return in a method like this sucks. Small concise methods whatever, but for methods like these multiple points of return can be extremely helpful in debugging. Otherwise I have to debug an extra 1,500 lines of code to see if something has been modified. Oh and nice descriptive method there EndLengthyOperation(); which is actually a global class method written by either Microsoft or the enterprise solution provider who Microsoft bought it from. Thank god I only have to work with this stuff all of 3-4 months of the year or so. Knyteguy fucked around with this message at 23:41 on Feb 29, 2016 |
# ? Feb 29, 2016 23:33 |
|
crazypenguin posted:
To me actually Hoare-triple style reasoning is an argument for multiple returns, since it's basically means you can stick AND NOT BadCondition into the pre- and post- conditions of all the statements after the return rather than having something like AND someErrorFlag <=> BadCondition, which feels simpler if you don't actually want to do any further work when BadCondition is true. Edit: somewhat less straightforward if the return is inside a loop, though, since it becomes related to zero-iteration case, but one would hope that the empty-set case makes sense, too. OddObserver fucked around with this message at 23:43 on Feb 29, 2016 |
# ? Feb 29, 2016 23:40 |
|
Plorkyeran posted:I don't think I've ever seen one that didn't involve the return being hidden in a macro or huge and weirdly formatted line. If there's a meaningful amount of cleanup that has to happen before exit, the duplication can suck. (Barring finally or RAII or similar.) We can agree that else-after-return is an abomination, I hope.
|
# ? Feb 29, 2016 23:56 |
|
There's nothing wrong with else-after-return. Generally as long as the else branch also always returns. And maybe in some other contrived situation.
|
# ? Mar 1, 2016 00:04 |
|
Subjunctive posted:If there's a meaningful amount of cleanup that has to happen before exit, the duplication can suck. (Barring finally or RAII or similar.)
|
# ? Mar 1, 2016 00:15 |
|
What basically we can witness here with these dogmatists is that they take the set of reasonably-written functions, identifies some properties P_1, ..., P_n on them, defines f mapping whether (P_1, ..., P_n) will likely create a reasonably-written function, and then (here comes the ridiculous part) picks a sub-rectangle of f's support that they like, often (because they're bad at thinking) a particularly idiosyncratic one.
|
# ? Mar 1, 2016 01:08 |
|
Qwertycoatl posted:I normally like early return, especially for "bail early in error situations", but there's one situation where I end up regretting it. When debugging, I often find it useful to temporarily add in some logging to a function, like "called foo with parameter 3", "foo returned 7". With multiple return, it's a (minor) annoyance to add this in because the outbound logging has to go into multiple places (or I have to rename foo to foo_inner and make a wrapper). In c++ you can have a logging object that you initialize at the top of the function, feed it log lines thru method calls, and then when you return it's destructor gets called to actually do the logging.
|
# ? Mar 1, 2016 03:42 |
|
Plorkyeran posted:I guess using goto to jump to the cleanup results in only having one return, but I've never met a single-return advocate that'd be okay with using goto for any reason and it's still an early exit from the actual logic of the function. If early exiting results in cleanup duplication, then you're handling cleanup poorly and even in the absence of an early exit it's probably going to be hard to verify that everything is always cleaned up correctly. "early exit from the actual logic of the function" describes any flow control, then. If you're allocating resources, then you typically have to clean up at exit, in the case of error if nothing else. Multiple exits, multiple places you have to free the newly allocated structure or release the handle or whatever. Some languages have ways of letting you specify at-exit behaviour that you can use to unify the logic, but not all. else-after-return is a foolproof signal that someone wasn't actually thinking carefully about the flow control in their function. Everyone is sloppy sometimes, but it should get caught in code review and elicit a "whoops", not a faux-intellectual defense.
|
# ? Mar 1, 2016 04:14 |
|
Subjunctive posted:else-after-return is a foolproof signal that someone wasn't actually thinking carefully about the flow control in their function. Everyone is sloppy sometimes, but it should get caught in code review and elicit a "whoops", not a faux-intellectual defense. What do you think of the argument that an explicit else, even after a return, provides a clearer visual indication that either one thing or the other is happening, but not both? (Or am I misunderstanding what everyone is talking about?)
|
# ? Mar 1, 2016 05:12 |
|
GrumpyDoctor posted:What do you think of the argument that an explicit else, even after a return, provides a clearer visual indication that either one thing or the other is happening, but not both? (Or am I misunderstanding what everyone is talking about?) I think it doesn't hold up, or there would be an else after every branched return. Nobody has that as their house style. If people don't know that return is the end of the function, I don't think there's much to do other than practice reading code?
|
# ? Mar 1, 2016 05:15 |
|
Subjunctive posted:else-after-return is a foolproof signal that someone wasn't actually thinking carefully about the flow control in their function. Everyone is sloppy sometimes, but it should get caught in code review and elicit a "whoops", not a faux-intellectual defense. This is complete horse hockey. code:
Else after return is perfectly natural and turns bugs from missing return statements into compile time errors.
|
# ? Mar 1, 2016 05:27 |
|
Subjunctive posted:I think it doesn't hold up, or there would be an else after every branched return. Nobody has that as their house style. If people don't know that return is the end of the function, I don't think there's much to do other than practice reading code? Return is an end to a function. One of potentially many.
|
# ? Mar 1, 2016 09:57 |
|
Subjunctive posted:else-after-return is a foolproof signal that someone wasn't actually thinking carefully about the flow control in their function. Everyone is sloppy sometimes, but it should get caught in code review and elicit a "whoops", not a faux-intellectual defense.
|
# ? Mar 1, 2016 12:57 |
|
sarehu posted:This is complete horse hockey. If you're worried about that, why bother with all that ornamentation. code:
|
# ? Mar 1, 2016 13:12 |
|
sarehu posted:This is complete horse hockey. Subjunctive is literally cited in an article called something like 'No-else-after-return considered harmful', btw. I'm not sure he's giving this one up easily.
|
# ? Mar 1, 2016 13:25 |
|
Brain Candy posted:If you're worried about that, why bother with all that ornamentation. Because this is bad and you should feel bad.
|
# ? Mar 1, 2016 13:26 |
|
Volte posted:This seems like a style choice and nothing more. In fact I have often missed a return where I should've had one (probably just logged the condition and forgot to return) and so my implicit "else" branch actually gets run every time. This can be hard to debug if it's code that gets run a lot and doesn't do anything blindingly obvious immediately. Do you always else after branched return? It combines in a pretty ugly way with early exit, that's for sure. code:
versus code:
(Similarly with yield and throw instead of return, obviously. And conditional break or continue within a loop.)
|
# ? Mar 1, 2016 13:42 |
|
Has anyone posted JSFuck yet? http://thedailywtf.com/articles/bidding-on-security
|
# ? Mar 1, 2016 14:01 |
|
HardDisk posted:Because this is bad and you should feel bad. I used to do this code:
code:
|
# ? Mar 1, 2016 14:02 |
|
canis minor posted:I used to do this I don't see anything wrong with the first one, I agree that it's nicer than the second one in this case.
|
# ? Mar 1, 2016 14:15 |
|
Subjunctive posted:Do you always else after branched return? It combines in a pretty ugly way with early exit, that's for sure. Early-exit is a pretty obvious case where you don't want to put the else case inside an actual else block. One section of code is "preferred", in that it is of far greater scope and complexity than the bit which is inside the condition, so it makes sense to leave it un-nested. But if you have two sections of roughly equivalent size and complexity, leaving one of them un-nested implies a distinction between the two that isn't actually present.
|
# ? Mar 1, 2016 14:18 |
|
Subjunctive posted:Do you always else after branched return? It combines in a pretty ugly way with early exit, that's for sure. The difference here is that your examples have code between the conditional checks which makes it stack in a gross way. So yeah I wouldn't do it in that case.
|
# ? Mar 1, 2016 14:33 |
|
canis minor posted:I used to do this This is actually really clever, but I've found that clever code is usually harder to debug for not that much gain. I also find that ternary operators are a kind of gateway drug for clever code. That said, I kinda like this.
|
# ? Mar 1, 2016 14:43 |
|
Subjunctive posted:Do you always else after branched return? It combines in a pretty ugly way with early exit, that's for sure. If this was in C#, Resharper would offer to condense the first version into the second one. I personally would go with the second approach anyway because indentations like that are annoying to sift through.
|
# ? Mar 1, 2016 14:44 |
|
Volte posted:I guess I'm specifically talking about cases where an if-elseif (with each one returning) chain is terminated by a default else, vs just falling off and putting the default case underneath the if block. If you forget a return in one of the conditional blocks, then the default case will run as well, unlike if there is an explicit else block. In fact, the compiler can warn that not all code paths return a value in that case. So only for else statements in terminal position? Seems weird to me to have a different style for that -- you can forget the return in the early-exit case, too -- but I guess you can make your style rules as complex as you like as long as everyone can internalize them. Would you reject a patch during code review for not having else-after-return-where-else-is-terminal-and-itself-returns? Would you do that if the function returns void, meaning that the compiler can't tell you that you missed a major piece of flow control? E: Drastic Actions posted:If this was in C#, Resharper would offer to condense the first version into the second one. I personally would go with the second approach anyway because indentations like that are annoying to sift through. Resharper is clearly good and cool.
|
# ? Mar 1, 2016 14:50 |
|
Chin Strap posted:Has anyone posted JSFuck yet? http://thedailywtf.com/articles/bidding-on-security hahaha holy poo poo
|
# ? Mar 1, 2016 14:54 |
|
|
# ? May 17, 2024 20:39 |
|
JSFuck was used to defeat the script filter on eBay and work an XSS recently, I believe.
|
# ? Mar 1, 2016 15:08 |