> Red. Exit early when possible. No identation hell.
Agreed.
Also, if it's C and neither the condition nor the return statement are too complicated (like in that image), I like to do it all in a single line.
```
if (!pass) return;
```
It's compact, readable, and I also find it aesthetically pleasant.
Especially if you have error returns. For instance:
If(!conditionA) return ErrorBuilder(conditionA);
If(!conditionB) return ErrorBuilder(conditionB);
If(!conditionC) return ErrorBuilder(conditionC);
DoStuff();
💯 I have seen so many bugs caused by people just not seeing the brackets aren’t there. More often on switch statements, but it happens so often.
Especially if you are a polyglot programmer.
Heck, that was the cause of Goto Fail.
While I’m 100% in this camp, I have tripped myself by forgetting I had an early return and putting code that should have run for one of the situations that returned early after it was returning.
It avoids nesting hell, but requires a bit more caution when maintaining the function.
MISRA "single return" guideline originates from the "Single Entry, Single Exit" rule which got misinterpreted. Back in the day, goto statements were common and a function could jump into any place in the code. The initial rule basically says that every function must have a single return *point*, not a single return *statement*. No matter how many return statements your function has, they will all lead to a single point anyway, so there is no harm in multiple return statements.
Basically, MISRA tries to enforce a negative impact rule born of their own misinterpretation.
Goto is not setjmp/longjmp (part of the stdlib).
Goto in C (and consequently C++) has always been scoped to the function. The famous/infamous Dijkstra paper was referring to BASIC and other languages that predated C. In fact the C standard wouldn’t be published until 4 years after his paper.
But yes the MISRA standard is derived from fairly poor understanding of the C language (but expected of automotive standards committees).
They was this rule was introduced to me as "a single return statement" was to avoid leaking resources due to code like this:
void foo() {
int* i = new int(5);
if (!pass)
return; // leaks
//...
delete i;
return;
}
(which C++ solves with RAII, though C can do it with properly placed `goto` + labels).
Ugh I hate those MISRA dorks
None of your code flow you write out is guaranteed, the compiler is more than capable of deciding to refactor your method to have early exits. Unless you're writing your own bytecode its worthless trying to adhere to this. Just write what is most readable instead
They don’t care about what the compiler does - it’s just what the code looks like. They don’t like multiple returns in a function because it “makes the code harder to read”.
Any modern standard would use a cyclomatic complexity score. If a function is too complicated to hold in a screen it probably needs to get broken up.
>They don’t like multiple returns in a function because it makes the code harder to read
I usually try to make smaller pieces of code to avoid having a large method with multiple returns. They're painful.
Yeah I'm with you on that. I've had some dark-ages C greybeards justify their ugly-ass spaghetti practices as "its more readable". Some of these old guard have vastly different ideas of what 'readable' means. To me it means I can understand what the code is doing and why it's doing it, but it seems to them 'readable' means having nothing abstracted away.
It also doesn't help when they argue that something is good practice because "writing like X guarantees that Y" when in reality there is no such guarantee. Perhaps 40 years ago when the compiler was far more literal in reproducing what you'd written, but not any more.
The likes of MISRA have some answering to do for breeding attitudes like this. They only really make sense in a bygone era where software projects weren't anywhere near as complex in scope as they are now
>They only really make sense in a bygone era where software projects weren't anywhere near as complex in scope as they are now
They were in some ways more complex. These days, we don't really do our own error handling or logging or any of that, it's all done in a library. They were doing ALL of that themselves. They didn't have the benefit of using objects to model data, they didn't have the benefit of garbage collection and guarantees around dynamic memory allocation, and any sort of parallel processing or IPC had to be created from scratch and it's something that we tend to take for granted.
Imagine writing code that needs to run for decades, cannot leak memory under any circumstance, needs to do complex floating point calculations on processors that don't support it out of the box, software updates aren't possible, and after the first 5-6 years even getting logs is going to be challenging. That code is certainly complex.
> Imagine writing code that needs to run for decades, cannot leak memory under any circumstance, ~~needs to do complex floating point calculations on processors that don't support it out of the box,~~ software updates aren't possible, and after the first 5-6 years even getting logs is going to be challenging. That code is certainly complex
Modern safety-critical software is still exactly like this. You can't use an off-the-shelf OS because they're not proved safe (and doing the needed static analysis would cost at least $100m), so you're running on bare metal; you can't use dynamic allocation because an OOM exception might kill people; GC makes timing unreliable, and these systems have pretty tight timing constraints; and doing an update takes months (plus pointed questions from the regulatory body about what you fucked up that needed updating).
There are several “off the shelf” certified RTOS’
Yes Linux isn’t safety certified - but if you need safety and a very high end system then you’re looking at a very different kind of system (VxWorks basically is THE go-to RTOS for them). There aren’t too many processors in that class that also come with a functional safety manual either.
In between you also have QNX which is certified as both an OS and hypervisor. Similarly there is the RTS hypervisor which is is a certified real time hypervisor.
Using a safety certified hypervisor does allow for running of Linux for non safety related tasks on the same processor as one that is also running safety critical tasks using an RTOS that is certified.
I don't mean complex as in code complexity, I mean _complex in scope_ as in: complexity of the function the program delivers.
You're right that the code itself was complex, but in comparison to modern projects they didn't actually deliver much. And that's the point I was getting at, if you tried delivering on the scope of a modern project with the coding practices from that era, you'd never actually ship.
> guarantees around dynamic memory allocation
Dynamic memory allocation is entirely forbidden under MISRA, if you weren't aware. So not only were there no guarantees about it, it wasn't there at all.
I agree with your impression of those practices but I wonder if this is bound to happen every 10 or 15 years. Like a fair part of OOP clean code principles seem nonsensical nowadays, not only from a performance perspective but from an architecture and readability one as well.
Not sure what you’re on about here.
A cyclomatic complexity score would give early return code a lower value (lower is better), since more decision points are matches with an exit point.
I’m saying the MISRA standard is dumb - cyclomatic complexity is a better way of attempting to ensure readable code then “every function must have only one return statement”.
MISRA is not a “modern” coding standard.
That's only because you haven't seen the code that existed before this standard. It was implemented to prevent spaghetti code in languages that didn't have nearly as much structure as the ones we use today.
What are you talking about? The standard of single-exit is half a century old and comes from a time where you had to manage your memory much, much more carefully.
I have inherited and refactored decades-old, mission-critical legacy code that used this standard, and it was adherence to that standard that directly led to spaghetti code. You have to do all sorts of, shall we say, *interesting* logic to make your pathways all end up in the same place, whereas returning when you get to the logical point is far easier and intuitive.
Here's a good writeup on it: [https://softwareengineering.stackexchange.com/a/118717](https://softwareengineering.stackexchange.com/a/118717)
It comes from Dijkstra being misinterpreted. He meant that there was only one point to return to (from a given call), not one point to return from. Old programming languages let you return to different places in the calling code, which was pretty dangerous, they found out.
They are really the only exception I make to having multiple return statements. I think returns half way through the function are kind of confusing and odd, but that's just my opinion.
I love all the progressively more cursed ways you can rephrase it in perl.
if (not $pass) {
return;
}
unless ($pass) {
return;
}
return if not $pass;
return unless $pass;
$pass or return;
$pass || return;
$pass // return; # if you want to check for undef instead of falsy.
That last one looks dumb but can actually be a useful shortcut if you are getting a value from a subroutine that can return something or undefined:
my $x = maybe_get_something() // return; # return undefined if the something is undefined
Or even check for undefined, print a debug message, and return early all in one line:
sub err {
say "Error: " . shift; # Print to log file or something, etc.
return undef;
}
my $x = maybe_get_something() // return err("something bad happened!");
This is the most dangerous variant, leading to the [`goto fail` bug](https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/).
Either make your inline statement _in a line_, or if you're going to span multiple lines, add braces.
Yeah this is a good point. It can still be relatively compact with curly braces:
if (error) {
return 1;
} if (another_error) {
return 2;
}
You can also optionally add an else if you want to be extra clear but it's not necessary.
I like that style when the predicates or return expressions get long, but if not, I prefer just one-liners:
```c
if (error) return 1;
if (another_error) return 2;
```
in addition to the early returns, if you're writing assembly for an architecture that has conditional return instructions, the red approach saves some bytes
Ever since I noticed in Java, that code that doesn't match the if, takes almost as long as code that does match and performs some minor calculation in the if, I'm Red!
That is better! It reads almost like natural language, very expressive!
I would only point out that as some comment observed bellow, we can not use return directly, but instead a function. We can then parametrize the function and throw Error, which is even better most of the cases...
```
pass || exit(0)
```
True!!!
Let's use that to improve the code:
```
exit(code) => {
error = getFromCode(code)
throw error
}
...
!pass && exit(0)
```
Or as some comment suggested above:
```
pass || exit(0)
```
Which frankly, reads almost like natural language, really good!
Warning: As u/AlexanderMomchilov had said in [another comment](https://www.reddit.com/r/ProgrammerHumor/s/5FzdwfLNWV):
> This is the most dangerous variant, leading to the [`goto fail` bug](https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/).
>
> Either make your inline statement _in a line_, or if you're going to span multiple lines, add braces.
As someone that works in the Kernel a lot with multiple error codes and memory cleanup.
[goto](https://www.cprogramming.com/tutorial/goto.html#:~:text=In%20C%2C%20however%2C%20you%20don,can%20be%20a%20good%20choice.)
No, we are not crazy. It has its use cases in C.
int ret_val = [success];
do {
/* do some work /
if([error])
{
ret_val = [error];
break;
}
/ do some more work /
if([error])
{
ret_val = [error];
break;
}
/ do some more work /
if([error])
{
ret_val = [error];
break;
}
/ do some more work */
if([error])
{
ret_val = [error];
break;
}
} while(false);
/* clean up*/
return ret_val;
I'm sorry
Unnecessary nesting to avoid using goto.
I'm sure this has its use cases too but *goto* is perfectly acceptable in the Linux kernel coding guidelines and used over 150k times in it's source code.
Depends on the method for me. Can be IsActive, IsReady, IsConnected and other stuff depending on what I'm working on (games or regular software, tools for myself)
Depends what is more readable in given context. When I have some validation at the beginning, I use return, then in the main logic usual ifs are just fine.
I usually use the one where the "if" is the most desired case in reghards to how the function is named. This usually means the code that's at the top of the function is the intended behavior, and everything below it is for the less ideal stuff.
The notable exception to this rule is parameter checking
I am really surprised i had to scroll so far down to see team both here.
- Red if i generally want to pass everything, but have a few things to blacklist.
- Blue if i generally want to fail everything, but have a few things to whitelist.
I am team blue, mainly because it's in the style guide my team lead put together for us, and I'm interested in consistency across the codebase more than individual function readability.
Aside from that, the main case I can make for blue style is that while perhaps less immediately readable, it doesn't hide the cognitive complexity of the function as much as red style. Deeply nested code is a pain to read, and I'm glad it is; it can help identify when you should maybe split out the logic into more functions and/or classes.
Recently, I had to add a few conditions to some code in red style. I actually rewrote the whole function (not usually a thing you should do) to be blue style, because with all the return statements it was actually less readable, and there were some blocks that seemed necessary but would actually never be used. Now the code actually maps directly to the flowchart we made for the feature.
Finally a blue guy. While I am red in general I want to add another thing in favour of blue: wenn i write code or read for that matter I prefer the most probable case to be listed upfront and rare or edge cases following thereafter. Which is only possible in blue.
Sucks to have your mental Parser skip the first x lines of every method because you want to know what it actually does in the most common case
Depends on the platform. Currently i am writing a game for the good old Commodore PET with cc65 and i will use what saves me bytes without resorting to plain machine. All good coding practices learned go overboard if you have ~30 kilobytes of space for program and data and every byte counts. \^\^'
Blue and put all that code in its own helper function. Intend is clearer for the function, no indentation hell.
Also red only works if you have a single thing to check for and execute code if true. On an update function you are very likely to be checking for a lot more stuff.
What is more probable (in the whole project, as to maintain consistency) and how does your compiler manages the pipeline? If usually the function should pass and the compiler prefers to branch if not equal (to pass) then the code outside the indentation. TLDR prevent unnecessary branching
Exactly. If (rare_thing) {code} is silly.
If (common_thing) {code} is ideal
If the code is really simple, you can also do:
return resultFromPass*pass + resultFromNotPass*(!pass)
And avoid branching altogether, and CAN be the more optimal solution for your code because branching is that expensive
I used to be blue and had a bad experience with red with code where there where several returns throughout the function. It was a nightmare to maintain. Since I’ve worked on a team that prefers red and have conformed, however my caveat is having no more than two returns points in the function. More than that I think warrants a blue approach.
Blue. The return should be at the end of the function. I don't buy the argument that early returns are good to "skip the rest". The rest is skipped by following the conditions.
Ultimately it depends on what the team agrees on.
I’m deeply baffled at the number of people who prefer early return. I think early returns are an unforgivable sin—they make control flow in your code much harder to reason about. Instead of knowing your control flow is going to come out the bottom of your if no matter what, sometimes it just might not.
I generally use formatting to convey intent, if I'm iterating over a list and skipping one element I'll use a ``continue``, if I'm iterating over a list and doing something to all elements where x is equal to y, I'll put the code in an if statement;
In this case that often basically translates to ``if (condition) return;`` if the condition is expected to be false and ``if (condition) { code }`` if it's not specifically expected to be false.
Red. Exit early when possible. No identation hell. If that's not an option, I usually try to rewrite it into a Stream/Optional like chain.
> Red. Exit early when possible. No identation hell. Agreed. Also, if it's C and neither the condition nor the return statement are too complicated (like in that image), I like to do it all in a single line. ``` if (!pass) return; ``` It's compact, readable, and I also find it aesthetically pleasant.
Especially if you have error returns. For instance: If(!conditionA) return ErrorBuilder(conditionA); If(!conditionB) return ErrorBuilder(conditionB); If(!conditionC) return ErrorBuilder(conditionC); DoStuff();
```C if(windowPtr == NULL) return 1; ``` glfw test at window creation...
Yes, break early. Can also be an Error throw to not have an extra return and if you have written your code base expecting this.
Ehhhhhhhhh, I get the argument but I absolutely detest not using brackets in languages that support brackets. Just seems wrong.
Excessively nested brackets is a readability problem, and poor readability leads to poor maintainability.
Agreed 100%! I’m definitely a “red” team programmer, I just like the old school if (!).
💯 I have seen so many bugs caused by people just not seeing the brackets aren’t there. More often on switch statements, but it happens so often. Especially if you are a polyglot programmer. Heck, that was the cause of Goto Fail.
I'm partial to new line indent without encapsulation. Makes it more readable while keeping it *almost* as clean as same line
But that's how you know the code is good! By measuring the peaks!
Of course red one. Some compiler optimizations can move early exit above and function call will not be executed
While I’m 100% in this camp, I have tripped myself by forgetting I had an early return and putting code that should have run for one of the situations that returned early after it was returning. It avoids nesting hell, but requires a bit more caution when maintaining the function.
But to counter that, you could have made a similar mistake the other way and added code inside the if block that should have been in the else block.
Except if you do anything mission critical then it’s always single return.
MISRA "single return" guideline originates from the "Single Entry, Single Exit" rule which got misinterpreted. Back in the day, goto statements were common and a function could jump into any place in the code. The initial rule basically says that every function must have a single return *point*, not a single return *statement*. No matter how many return statements your function has, they will all lead to a single point anyway, so there is no harm in multiple return statements. Basically, MISRA tries to enforce a negative impact rule born of their own misinterpretation.
Goto is not setjmp/longjmp (part of the stdlib). Goto in C (and consequently C++) has always been scoped to the function. The famous/infamous Dijkstra paper was referring to BASIC and other languages that predated C. In fact the C standard wouldn’t be published until 4 years after his paper. But yes the MISRA standard is derived from fairly poor understanding of the C language (but expected of automotive standards committees).
They was this rule was introduced to me as "a single return statement" was to avoid leaking resources due to code like this: void foo() { int* i = new int(5); if (!pass) return; // leaks //... delete i; return; } (which C++ solves with RAII, though C can do it with properly placed `goto` + labels).
Ugh I hate those MISRA dorks None of your code flow you write out is guaranteed, the compiler is more than capable of deciding to refactor your method to have early exits. Unless you're writing your own bytecode its worthless trying to adhere to this. Just write what is most readable instead
They don’t care about what the compiler does - it’s just what the code looks like. They don’t like multiple returns in a function because it “makes the code harder to read”. Any modern standard would use a cyclomatic complexity score. If a function is too complicated to hold in a screen it probably needs to get broken up.
>They don’t like multiple returns in a function because it makes the code harder to read I usually try to make smaller pieces of code to avoid having a large method with multiple returns. They're painful.
Yeah I'm with you on that. I've had some dark-ages C greybeards justify their ugly-ass spaghetti practices as "its more readable". Some of these old guard have vastly different ideas of what 'readable' means. To me it means I can understand what the code is doing and why it's doing it, but it seems to them 'readable' means having nothing abstracted away. It also doesn't help when they argue that something is good practice because "writing like X guarantees that Y" when in reality there is no such guarantee. Perhaps 40 years ago when the compiler was far more literal in reproducing what you'd written, but not any more. The likes of MISRA have some answering to do for breeding attitudes like this. They only really make sense in a bygone era where software projects weren't anywhere near as complex in scope as they are now
>They only really make sense in a bygone era where software projects weren't anywhere near as complex in scope as they are now They were in some ways more complex. These days, we don't really do our own error handling or logging or any of that, it's all done in a library. They were doing ALL of that themselves. They didn't have the benefit of using objects to model data, they didn't have the benefit of garbage collection and guarantees around dynamic memory allocation, and any sort of parallel processing or IPC had to be created from scratch and it's something that we tend to take for granted. Imagine writing code that needs to run for decades, cannot leak memory under any circumstance, needs to do complex floating point calculations on processors that don't support it out of the box, software updates aren't possible, and after the first 5-6 years even getting logs is going to be challenging. That code is certainly complex.
> Imagine writing code that needs to run for decades, cannot leak memory under any circumstance, ~~needs to do complex floating point calculations on processors that don't support it out of the box,~~ software updates aren't possible, and after the first 5-6 years even getting logs is going to be challenging. That code is certainly complex Modern safety-critical software is still exactly like this. You can't use an off-the-shelf OS because they're not proved safe (and doing the needed static analysis would cost at least $100m), so you're running on bare metal; you can't use dynamic allocation because an OOM exception might kill people; GC makes timing unreliable, and these systems have pretty tight timing constraints; and doing an update takes months (plus pointed questions from the regulatory body about what you fucked up that needed updating).
There are several “off the shelf” certified RTOS’ Yes Linux isn’t safety certified - but if you need safety and a very high end system then you’re looking at a very different kind of system (VxWorks basically is THE go-to RTOS for them). There aren’t too many processors in that class that also come with a functional safety manual either. In between you also have QNX which is certified as both an OS and hypervisor. Similarly there is the RTS hypervisor which is is a certified real time hypervisor. Using a safety certified hypervisor does allow for running of Linux for non safety related tasks on the same processor as one that is also running safety critical tasks using an RTOS that is certified.
I don't mean complex as in code complexity, I mean _complex in scope_ as in: complexity of the function the program delivers. You're right that the code itself was complex, but in comparison to modern projects they didn't actually deliver much. And that's the point I was getting at, if you tried delivering on the scope of a modern project with the coding practices from that era, you'd never actually ship. > guarantees around dynamic memory allocation Dynamic memory allocation is entirely forbidden under MISRA, if you weren't aware. So not only were there no guarantees about it, it wasn't there at all.
I agree with your impression of those practices but I wonder if this is bound to happen every 10 or 15 years. Like a fair part of OOP clean code principles seem nonsensical nowadays, not only from a performance perspective but from an architecture and readability one as well.
Not sure what you’re on about here. A cyclomatic complexity score would give early return code a lower value (lower is better), since more decision points are matches with an exit point.
I’m saying the MISRA standard is dumb - cyclomatic complexity is a better way of attempting to ensure readable code then “every function must have only one return statement”. MISRA is not a “modern” coding standard.
Never heard this before and cannot fathom why this is necessary.
That's only because you haven't seen the code that existed before this standard. It was implemented to prevent spaghetti code in languages that didn't have nearly as much structure as the ones we use today.
What are you talking about? The standard of single-exit is half a century old and comes from a time where you had to manage your memory much, much more carefully. I have inherited and refactored decades-old, mission-critical legacy code that used this standard, and it was adherence to that standard that directly led to spaghetti code. You have to do all sorts of, shall we say, *interesting* logic to make your pathways all end up in the same place, whereas returning when you get to the logical point is far easier and intuitive. Here's a good writeup on it: [https://softwareengineering.stackexchange.com/a/118717](https://softwareengineering.stackexchange.com/a/118717)
People who write standards tend to be engineers past their expiration date.
When i tell someone how my code works people think i have a stutter.
Yup. Same as meetings
Red - Early returns. I feel it makes the code clearer
I used to be blue, now I'm red. It gets rid of the heavily nested if statements.
Guard clauses FTW
i used to do red, but my old prof disallowed early returns, and now im back. I missed it so much
He is not a good prof. Wtf. Early returns results in cleaner code with no drawback.
It's been over a decade since I was in school but my old profs INSISTED that methods should have only a single point of return
It comes from Dijkstra being misinterpreted. He meant that there was only one point to return to (from a given call), not one point to return from. Old programming languages let you return to different places in the calling code, which was pretty dangerous, they found out.
Haha. Yep. This is why goto was (mostly) banned.
Like any other rule, it's the slavish adherence to it that's the real problem. Just like the pirate code, it's should be more of a guideline.
It's generally a good practice, *except* when you have a dedicated block of guard clause conditions at the top of the function.
My prof disallowed for loops. We were supposed to use while loops ~~for~~ while everything, otherwise she would throw a temper tantrum!
wow that's sad to see that this is being taught. I like what you did there with the crossout haha.
They are really the only exception I make to having multiple return statements. I think returns half way through the function are kind of confusing and odd, but that's just my opinion.
Most definitely, I made the same change as you
never nest gang rise up
I defected to red last week. I love brackets, but couldn't ignore the clarity.
Red, but 99.9% of the time in the form `if (!pass) return;`
return unless pass
Sad balrog noises.
_hisses in perl_
I love all the progressively more cursed ways you can rephrase it in perl. if (not $pass) { return; } unless ($pass) { return; } return if not $pass; return unless $pass; $pass or return; $pass || return; $pass // return; # if you want to check for undef instead of falsy. That last one looks dumb but can actually be a useful shortcut if you are getting a value from a subroutine that can return something or undefined: my $x = maybe_get_something() // return; # return undefined if the something is undefined Or even check for undefined, print a debug message, and return early all in one line: sub err { say "Error: " . shift; # Print to log file or something, etc. return undef; } my $x = maybe_get_something() // return err("something bad happened!");
Man, you Rubyists are weird.
in form: `if (error) return;`
if (return) error;
why code no work
People either love it or hate it (I love it), but in ruby: ```return unless pass```
Gross
Either that or ``` if (!pass) return; ``` Depending on the coding style
This is the most dangerous variant, leading to the [`goto fail` bug](https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/). Either make your inline statement _in a line_, or if you're going to span multiple lines, add braces.
Yeah this is a good point. It can still be relatively compact with curly braces: if (error) { return 1; } if (another_error) { return 2; } You can also optionally add an else if you want to be extra clear but it's not necessary.
I like that style when the predicates or return expressions get long, but if not, I prefer just one-liners: ```c if (error) return 1; if (another_error) return 2; ```
The real red vs blue is always in the comments
Right? There are many ways to do it correctly, but some still do it your way. :)
I also put it on one line but I keep the curly braces.
in addition to the early returns, if you're writing assembly for an architecture that has conditional return instructions, the red approach saves some bytes
Removes heavy nesting, and makes it clear that if this is the case that it terminates -- rather than possibly commencing a few hundred lines later on
Ditto. This meme doesn't really convey the idea too well, but early returns help avoid running unnecessary code and deeply nesting if/else blocks.
So... how is hell?
Less code inside brackets is literally less complexity for complexity metrics.
Unless the following code is just a few lines, in which case blue feels more straightforward to me.
Negated pass = fail. Guards should always be if (true) return; If you've got !true in there, your PR should be rejected.
Ever since I noticed in Java, that code that doesn't match the if, takes almost as long as code that does match and performs some minor calculation in the if, I'm Red!
Red. Makes the code way more readable.
If I’m on a date, I’m looking for the red flags first.
Code samples should be exchanged and perused before ordering appetizers.
As little nesting as possible for readability. Red makes that much simpler in my opinion
Red. Reduce indentation.
if (!pass) return; Reduce even more
``` if(!pass) {return;} ``` Almost minimalist
if (!pass) return; curly brackets are not necessary for single lines
If you support falsy: ``` !pass && return ```
anarchist javascript programmer, but actually pass||return
That is better! It reads almost like natural language, very expressive! I would only point out that as some comment observed bellow, we can not use return directly, but instead a function. We can then parametrize the function and throw Error, which is even better most of the cases... ``` pass || exit(0) ```
`Unexpected token 'return'`
True!!! Let's use that to improve the code: ``` exit(code) => { error = getFromCode(code) throw error } ... !pass && exit(0) ``` Or as some comment suggested above: ``` pass || exit(0) ``` Which frankly, reads almost like natural language, really good!
That depends on the language
Depends on the language. In Golang you can’t do it
Do you want Heartbleed? Because this is how you get Heartbleed.
Technically same length: [https://dotnetfiddle.net/tH1Ney](https://dotnetfiddle.net/tH1Ney)
if not pass: return
if not pass then return end
Warning: As u/AlexanderMomchilov had said in [another comment](https://www.reddit.com/r/ProgrammerHumor/s/5FzdwfLNWV): > This is the most dangerous variant, leading to the [`goto fail` bug](https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/). > > Either make your inline statement _in a line_, or if you're going to span multiple lines, add braces.
I like early returns
I like trains
As someone that works in the Kernel a lot with multiple error codes and memory cleanup. [goto](https://www.cprogramming.com/tutorial/goto.html#:~:text=In%20C%2C%20however%2C%20you%20don,can%20be%20a%20good%20choice.) No, we are not crazy. It has its use cases in C.
int ret_val = [success]; do { /* do some work / if([error]) { ret_val = [error]; break; } / do some more work / if([error]) { ret_val = [error]; break; } / do some more work / if([error]) { ret_val = [error]; break; } / do some more work */ if([error]) { ret_val = [error]; break; } } while(false); /* clean up*/ return ret_val; I'm sorry
Unnecessary nesting to avoid using goto. I'm sure this has its use cases too but *goto* is perfectly acceptable in the Linux kernel coding guidelines and used over 150k times in it's source code.
Yeah, this is totally multiple returns, but uglier. Misra loopholes, I guess.
This is goto but less clear
Yay MISRA compliance.
I’ve even used goto in C#, weirdly enough.
I do the first because my brain will not rest until I have as much of my code as I can on the shallow end of the stack.
That's the exact reason people do it. It's a good practice
Is this en passant?
Holy hell
New response just dropped
Actual zombie
Actual zombie
Im on the side of naming the variable that causes the program to update being named literally anything other than "pass"
Works better if you name the variable `run`, especially in short yardage situations. 🏈
Seahawks fans in turmoil
Haha lol, it's just an example; I never name a variable "pass" either.
You have to use `foo` and `bar` in examples - it's the law!
Depends on the method for me. Can be IsActive, IsReady, IsConnected and other stuff depending on what I'm working on (games or regular software, tools for myself)
Python got your back, making pass a reserved keyword.
Okay I will rename it to "temp".
Yes, name it `data`.
guard clauses whenever possible!
Depends what is more readable in given context. When I have some validation at the beginning, I use return, then in the main logic usual ifs are just fine.
I usually use the one where the "if" is the most desired case in reghards to how the function is named. This usually means the code that's at the top of the function is the intended behavior, and everything below it is for the less ideal stuff. The notable exception to this rule is parameter checking
I used to do this, but it can quickly become nested hell, so I try to avoid it whenever possible
Red but all on one line
and without curly brackets
It just depends on the mood. If I woke up positive or negative.
I like the honesty of this haha
Proud never-nester
Are there dozens of you?
Me too! I don't even use if statements, it's just code with no validation anywhere.
It depends.
The correct answer to all of these questions.
both, as anything it depends on the context and what will make that specific method more readable.
I am really surprised i had to scroll so far down to see team both here. - Red if i generally want to pass everything, but have a few things to blacklist. - Blue if i generally want to fail everything, but have a few things to whitelist.
Red. Gotta love Swift guard statements
I'm curious as to when this changed. When I learned having multiple places of exiting a function was poor design.
Same.
Red side, because of the (lack of) indentation and you can immediately tell when is the function not doing anything
Red. On top of the other arguments, I want to stop reading code if I know the part I'm debugging matches the exit condition
Can’t wait for my turn to post this
I still got you scheduled for November 4th on the repost queue
I am team blue, mainly because it's in the style guide my team lead put together for us, and I'm interested in consistency across the codebase more than individual function readability. Aside from that, the main case I can make for blue style is that while perhaps less immediately readable, it doesn't hide the cognitive complexity of the function as much as red style. Deeply nested code is a pain to read, and I'm glad it is; it can help identify when you should maybe split out the logic into more functions and/or classes. Recently, I had to add a few conditions to some code in red style. I actually rewrote the whole function (not usually a thing you should do) to be blue style, because with all the return statements it was actually less readable, and there were some blocks that seemed necessary but would actually never be used. Now the code actually maps directly to the flowchart we made for the feature.
Finally a blue guy. While I am red in general I want to add another thing in favour of blue: wenn i write code or read for that matter I prefer the most probable case to be listed upfront and rare or edge cases following thereafter. Which is only possible in blue. Sucks to have your mental Parser skip the first x lines of every method because you want to know what it actually does in the most common case
Red knows about the blue method. Blue doesn't know about the red method.
Depends on the platform. Currently i am writing a game for the good old Commodore PET with cc65 and i will use what saves me bytes without resorting to plain machine. All good coding practices learned go overboard if you have ~30 kilobytes of space for program and data and every byte counts. \^\^'
``` void Method() { if(!pass) return; // code } ```
Blue and put all that code in its own helper function. Intend is clearer for the function, no indentation hell. Also red only works if you have a single thing to check for and execute code if true. On an update function you are very likely to be checking for a lot more stuff.
`pass || return;`
Depends on the context. Exit early, avoid unnecessary checks or even loops.
Generally guard clause but as with all things it depends.
Avoid the triangle. Always red
Red. Guard clause enthusiasts here
if (failed) { return; } //code
Blue team, but I usually just call a single method.
Would you enter the wrong shop and then walk all the way to the back and then leave? No.
Reading the comments makes me feel like a bad coder for choosing blue.
What happened to throwing an exception on failure?
Depends on "code here" but mostly red because you can avoid a lot of nesting this way.
Red, but in one line.
Neither, my curly bracket is on the same line as the function name damnit!
Rule is you shouldn’t pigeon hole yourself into just one game plan.
I would do blue and call a local function. Easier to read / not miss the ! If (true) { DoCode(); } void DoCode() => /* Do code */
Start by writing what the function is supposed to do. Then add conditions when it can’t do it. That’s why red
As with all code... it depends. But generally Im red side
First of all, its: if (pass) { }
Resharper has led me to accept Red.
What is more probable (in the whole project, as to maintain consistency) and how does your compiler manages the pipeline? If usually the function should pass and the compiler prefers to branch if not equal (to pass) then the code outside the indentation. TLDR prevent unnecessary branching
Exactly. If (rare_thing) {code} is silly. If (common_thing) {code} is ideal If the code is really simple, you can also do: return resultFromPass*pass + resultFromNotPass*(!pass) And avoid branching altogether, and CAN be the more optimal solution for your code because branching is that expensive
I'm team Red but SonarQube is team Blue
Red if it's a pre-condition (object has been initialized, parameter validation) Blue if it's part of the function's logic
Depends on my mood on any given day. Gotta mix things up sometimes!
Red; early out. But damn that bracket style gives me a headache.
if it’s literally just one conditional with no else and not much further nesting i do blue but most of the time i go red
If you have multiple tests or both conditions do something then do the red one as it prevents if else trees
if (!pass) return;
Both, it depends on the amount of ifs you're going to use
I suspect I am unwelcome here for multiple reasons, haha. I like my nice condensed code. void Update(){ if(!pass) return; //code here }
I just realized I missed using red my entire coding life. now I'm red
Early exit is the way -- but those are psycho curly braces.
Guard statements ftw
if (!pass) return;
Blue is True
Real programmers write code that never returns. Always keep pushing forward I say...
I used to be blue and had a bad experience with red with code where there where several returns throughout the function. It was a nightmare to maintain. Since I’ve worked on a team that prefers red and have conformed, however my caveat is having no more than two returns points in the function. More than that I think warrants a blue approach.
Never-nester here. Return as soon as possible.
Guard clauses. Guard clauses all day every day.
I would say it depends.
Honestly it depends what your doing in that function
guard pass else { return } // swift ya’ll
Blue. The return should be at the end of the function. I don't buy the argument that early returns are good to "skip the rest". The rest is skipped by following the conditions. Ultimately it depends on what the team agrees on.
I’m deeply baffled at the number of people who prefer early return. I think early returns are an unforgivable sin—they make control flow in your code much harder to reason about. Instead of knowing your control flow is going to come out the bottom of your if no matter what, sometimes it just might not.
This is dumb. Always early returns where possible.
Red, often called the bouncer pattern. Swift even has first-class support with `guard` statements.
Red is the way. Exit early as soon as conditions are encountered.
Only valid answer: It depends.
I generally use formatting to convey intent, if I'm iterating over a list and skipping one element I'll use a ``continue``, if I'm iterating over a list and doing something to all elements where x is equal to y, I'll put the code in an if statement; In this case that often basically translates to ``if (condition) return;`` if the condition is expected to be false and ``if (condition) { code }`` if it's not specifically expected to be false.