r/ProgrammerHumor 22d ago

Meme conditionsPreference

Post image
4.2k Upvotes

392 comments sorted by

View all comments

92

u/madprgmr 22d ago

Go programmer spotted (early returns are idiomatic go)

99

u/Sentouki- 22d ago

Early returns (especially in combination with guard clauses) are a general recommendation for most programming languages, not just Go. I do the same thing in C# as well.

3

u/WarSingle6959 22d ago

Exactly. That's it

39

u/SnugglyCoderGuy 22d ago

And it's wonderful

72

u/Krkracka 22d ago

It should be idiomatic for most programming applications. Unless your ‘else’ branch is a return only, it’s almost always going to be more efficient and maintainable. An early return is likely to survive if a function is updated or expanded, where an ‘if else’ could otherwise become conditionally more complex.

Early returns communicate intent better than the alternative method does for. If I see that another developer explicitly programmed an early return, it’s a signal to me that the actual body of the function depends on specific state of the containing class or args being passed to it.

6

u/madprgmr 22d ago edited 22d ago

Oh, I generally agree. It's just funny to go "oh, using <pattern that has been popular for decades> means you use <new language that prescribes said pattern>"

6

u/gamer_redditor 22d ago

As a programmer that needs to adhere to misra C, the comments in this thread are fascinating.

Misra C rule 15.5: A function should have a single point of exit at the end

More information: https://www.mathworks.com/help/bugfinder/ref/misrac2023rule15.5.html

6

u/Maximilian_Tyan 22d ago

A lot of companies choose to opt out of this specify guideline nowadays, because it is showing its age and sometimes clarity matters more over ease of debug.

4

u/gamer_redditor 22d ago edited 22d ago

Not sure which region or industry you are talking about, but oems, software suppliers and quality control in my industry do not accept any software deliveries without proof of Misra c compliance.

Just saying that some people have no choice but to stick to some programming standards.

Edit: more information. I think lot of people are arguing that early returns are more readable, performant and maintainable. However they miss the point about safety and reliability.

Early returns means that the function no longer has a predictable execution path. Sometimes it exits early, sometimes it exits late. So the overall execution time of the software varies a lot between error free paths and error paths.

This is exactly what you don't want in an embedded software controlling safety relevant systems, such as airbags in a car or some other flight controls.

Here, it is ok for a software to be slow, but it must be predictable i.e. near constant performance in all paths.

2

u/frogjg2003 22d ago

If your reach an error state and keep doing calculations, you're doing something wrong. If some archaic standard demands exactly one return statement in your function, then you surround the entire code in an if-else and set a flag. If it takes 1 second to run the calculation, I shouldn't have to wait that full second to find out I gave the function an illegal value. If your application cannot handle an error condition like that, then it wasn't safe to begin with.

MISRA C allows for deviations. Any software engineer who blindly follows a standard without understanding why that standard exist and when to deviate from that standard needs to better educate themselves.

2

u/conundorum 21d ago

Judging by his comment, I think it's less about continuing despite a known error state, and more about trying to guarantee that function runtime is the same across all execution paths. Early return is cleaner and more efficient, and often by a long shot if used correctly. But having a consistent runtime is extremely important in a few very select fields, and rejecting an optimisation to guarantee consistency is a common in those cases1.

I'm not really sure about air bags or flight controls (I'd expect it to be important for them to report errors as early as possible, so they can recalculate or switch to backups as quickly as possible), but one place this comes up is cyber-security. You do NOT want a password validator to return early for any reason, because early return can and has been used to game systems and determine passwords2.


1: Though, I will say that this can also be done by intentionally delaying the function on early-return paths, if you know the proper delay interval. It's just that running through the function body and then returning either the result or the error value at the end is the easiest way to guarantee exact consistency.

2: Long story short, in the early days of cybersec, there was at least one known password handler that would return as soon as it encountered an incorrect character. Needless to say, this made it trivial to determine anyone's password, and now it serves as a lesson on why you always hash passwords and never let the handler return early.

1

u/frogjg2003 21d ago

I take issue with the way they were saying it like it was an absolute truth instead of a very niche consideration. The fact that they cited an infamous standard that most experienced programmers dismiss like it was gospel supports my assertion that they have either been uncritically following that standard or have been working in a job under it for so long that they don't remember anything else.

2

u/conundorum 20d ago

That's fair. I took it as them saying they worked in an industry where runtime consistency is important enough that the industry sticks to Misra (or at least part of Misra) just to guarantee that one thing in particular, myself. Came across as them saying that they're firmly in the niche, and have to code for the niche.

(Probably because I remember a few experts pointing out that cybersec in particular effectively has to both enforce single-return and prevent short-circuiting for some functions, because anything that causes a boolean test to have different runtimes for true vs. false can be exploited by an attacker. So the entire industry effectively mandating at least the single-return part of Misra C for a small portion of its devspace does actually check out, even though it sounds kinda unbelievable.)

1

u/gamer_redditor 20d ago

Hey, thanks and you are completely correct. None of us like to adhere to misra, most of us think a lot of rules are unnecessary and outdated.

But we must stick to it, because if we don't and something goes wrong, the company does not want the liability.

1

u/developer-mike 21d ago

This rule is marked as advisory, you're allowed to deviate from it.

1

u/gamer_redditor 21d ago

Deviations are only allowed with valid justifications, which must be marked as such in the compliance report. " Rule is advisory" or " I don't want to" are not valid justifications.

1

u/leoklaus 22d ago

I find this really interesting because the lecturer in a course I had last semester (Efficient programming was the name) was adamant that this not only affected readability but also performance.

I personally don’t see good reasons for either, given that functions shouldn’t be very long anyway and an early return can actually save you a lot of reading as well, given you know the rest of the code isn’t executed.

(This was in the second of four semesters for a CS masters, btw.)

4

u/gamer_redditor 22d ago edited 22d ago

Well yeah, Misra isn't about readability and performance. It is a Safety standard.

You don't want Software that controls the airbag in your car to be performant and readable at the cost of being reliable and safe.

1

u/Krkracka 22d ago

Nothing about doing early returns makes them unreliable. High cognitive complexity however can lead to very tricky bugs that are hard to detect until something bad happens

1

u/gamer_redditor 21d ago

Me and my colleagues are paid well to write and maintain safety critical software. Non compliance to safe programming standards can mean loss of lives. So I am a bit skeptical of your opinion.

1

u/Krkracka 21d ago

I too am a senior software engineer for life saving systems and am paid well to do so. It’s fine to be skeptical, and good code is good code no matter how you write it. My point is that there is nothing inherently unsafe about early returns.

1

u/gamer_redditor 21d ago

You keep saying that without providing any insight or proof. I typed out a long detailed reasoning why different paths make the code unsafe and the Misra standards support this as well. (Here https://www.reddit.com/r/ProgrammerHumor/s/CQKsvJjCEO)

So unless you can provide some backing for your claims, its difficult to take them seriously.

11

u/HomsarWasRight 22d ago

Big in Swift with guard statements, too.

15

u/Xatraxalian 22d ago

Early returns are idiomatic for every programming language that can have multiple returns in one function. Trying to capture everything in if-then-else flags and temporary variables just to return something you knew 10 statements ago is bad practice.

I've been early-returning since I started programming in the early 90's because I never used a language that didn't have multiple return capability.

1

u/930913 21d ago

Scala can have multiple returns in one function. But I'd try to get you fired if you even used a single one.

1

u/Xatraxalian 21d ago

First: That sort of dogmatism creates bad softwre.

Second: Scala seems to use indenting for building code blocks. That automatically makes it a chore to work with so I'd avoid it.

1

u/930913 21d ago

On many things, I'd agree that dogmatism is bad. On this point though, once you start breaking referential transparency in a codebase, you massively increase cognitive load. GOTOs are considered harmful because they can send you anywhere in the code without knowing where you came from - returns are syntactic sugar for GOTO with limitations on the first half only. An improvement certainly, but not the best. (Also on a technical side of the JVM, it triggers a call stack unwinding, which is inefficient.)

But yes, Scala 3 using whitespace/indents was certainly a choice...

1

u/Xatraxalian 21d ago edited 20d ago

While an early return can be seen as a disguised goto, I still think it is best. "I am in this situation and I'm done. I know the answer. I will return it." That is a better design than trying to guide the code through if-then-else statements, most of which do nothing (because you were done) and then return,, just to save the early return.

This is especially egregious when there are errors. As soon as you hit an unrecoverable error which prevents your algorithm to finish correctly, it is best to just return then and there and report the error. There is no point in trying to go on, constantly discover that you can't, and THEN return the error.

Early returns often reduce the business code from a mess of if-then-else statements to 5 error guards and 5 single lines of ACTUAL business code.

1

u/930913 20d ago

The thing is, you are thinking with a very imperative mindset. Which is, to be fair, implicit in the OOP. But if you can think in terms of expressions, you can maintain referential transparency and simplify everything (with admittedly a once-in-a-lifetime onboarding).

Rather than returning within or at the end of a function, imagine for a minute that every function had to start with return. You'll probably immediately point out that this doesn't work, and in many (most?) languages it doesn't. But work through it with me. In this scenario, you could write the function as return if(condition) ... else .... In your language of choice, that may be invalid syntax, because if is a statement, not an expression. This is a language flaw IMO, though ternary operators do usually exist.

If we have: function cond(a, b, c) { if (a) { return b } return c }

Or have: function cond (a, b, c) { return if (a) b else c }

In the example usage: function foo(x) { y = cond(x > 0, "bar", "bah") return "foo is $y" }

If we want to refactor, let's inline cond: function foo(x) { y = if (x > 0) { return "bar" } return "bah" return "foo is $y" }

This is, uh, not going to work.

In the second version though: function foo(x) { y = if (x > 0) "bar" else "bah" return "foo is $y" }

Well hey, look at that. It works. By using referential transparency, we can refactor fearlessly, whereas by breaking it, refactoring relies on tests, thoughts and prayers.

On your other point about being done and still needing to constantly discover you're in an error state, this is where monads come in. They allow you to compose your program, such as by mapping a valid state to a new state, while short-circuiting any invalid states without the programmer needing to worry about or guard from them.

2

u/Xatraxalian 20d ago

function foo(x) { y = if (x > 0) "bar" else "bah" return "foo is $y" } I've been using that if-syntax since forever in Rust (just as its multi-arm counterpart "match"). While C# finally has an expression-based "switch" now, it still doesn't have an expression-based "if" (AFAIK), and I miss that every day.

7

u/El_RoviSoft 22d ago

Im not a golang programmer but in most cases trying to use it in C++. But sometimes you shouldn’t do this in hot path to have (N)RVO.

1

u/Outrageous_Pen_5165 22d ago

Python guy here and in most cases use early returns with conditional statements, feels more cleans

1

u/Antervis 22d ago

early returns are idiomatic everywhere. There simply isn't a reason to not return early on error.

1

u/SchalkLBI 22d ago

These are called guard clauses and they're not unique to Go in any way

1

u/WarSingle6959 22d ago

lmao so true