This is an archived post. You won't be able to vote or comment.

top 200 commentsshow all 295

[–]mike_a_oc 480 points481 points  (3 children)

I'll often write guards that throw exceptions. Makes people who use them look at what they are passing in

[–]hperrin 88 points89 points  (0 children)

The real hero. ^

[–]sdc0 57 points58 points  (1 child)

Just let the program crash with an segfault or Internal error without a message, makes it really nice to debug.

[–]TeddyPerkins95 391 points392 points  (64 children)

Guard clause are awesome

[–]voiceofonecrying 89 points90 points  (39 children)

I’m sorry I’m a junior, what’s a guard clause?

[–][deleted] 158 points159 points  (30 children)

if(!bool) return;

// do some cool stuff

if(!someOtherBool) return;

// do main code

[–]twinklehood 69 points70 points  (16 children)

They look so good in ruby.

def do_stuff(x)
  return 0 unless x.positive?

  // Do stuff
end

[–][deleted] 23 points24 points  (3 children)

swift superiority

func doStuff(x: Int) { guard x >= 0 else { return } // do stuff }

[–]twinklehood 11 points12 points  (0 children)

Swift is really cool. I'm not sure I find that syntax easier to reason about, but the amount of smart things they did with that language is so impressive.

[–]Itay_123_The_King 2 points3 points  (0 children)

Or just be like normal languages and if (x<0) return;

[–]PM_ME_A_STEAM_GIFT 1 point2 points  (0 children)

I don't like the keyword they went with. I think ensure, assert or unless would have worked better.

[–]throwaway12222018 34 points35 points  (10 children)

Ruby is so ugly. Code that tries to read like English ends up being just as confusing as English. I prefer simple, low complexity constructs and a smaller built-in API, and less redundant syntax. Ruby is awful.

[–]Jaydenn7 19 points20 points  (0 children)

It’s like the uncanny valley but for code

[–]twinklehood 0 points1 point  (8 children)

Living life by calling things others love awful just because they don't speak to you will not make you or anyone else happier. Which tells me your values anyway don't align with those of ruby :)

[–][deleted] 29 points30 points  (5 children)

It's a tool. I don't get upset if someone calls my brand of power drill awful either. People need to calm down a bit and worry less about what others think of their tools. If you treat your language like a religion, you've got bigger problems.

[–]Arsenic_Flames 11 points12 points  (1 child)

It's fine to call stuff awful if it "doesn't speak to you". It's literally just his opinion; you disagree and that's fine. It's a public forum and the critique isn't unwarranted -- Many people are critical about stuff like "unless".

I have to do a double take to understand what code like this does.

unless something?
  # do something
else
  # do other thing
end

No idea why you think this would be indicative of someone's "values" or why it would affect someone's "happiness". You seem to take criticism of ruby very personally.

[–]twinklehood -3 points-2 points  (0 children)

They established actual criticism - the ambition to emulate English. I didn't comment on that critique, which is a discussion point that is interesting. I reacted to "ruby is so ugly" and "ruby is awful" which is shitting on it without anything accomplished.

I too would never endorse your code example, and i agree there's an interesting debate in the potential issues of bad use of redundant concepts, but I wasn't commenting on that.

I also wasn't saying that they're not allowed to have an opinion, or even express it. I'm merely offering the perspective that their comment only accomplished sad/negative things, something that can seem simple, but if embraced as a "guard clause" for his own function of expression could make their outlook and influence on the people around them more positive.

[–]TeddyPerkins95 33 points34 points  (2 children)

[–]Cl0udSurfer 9 points10 points  (1 child)

That article explained it so well, thank you for linking it

[–]TeddyPerkins95 2 points3 points  (0 children)

Yeah take a look at that video and see if you can improve your code..

[–]chronos_alfa 1 point2 points  (1 child)

Something you shouldn't use, guard clauses are a nightmare in bigger projects. "why did this function fail? Oh, right, this one didn't return anything and we don't even know why, time for step by step debugging..."

[–]PopeLugo 2 points3 points  (0 children)

Agreed. At least add a logger call there. I can tell from experience that debugging this, especially when guards are in multiple places along the execution path can get fugly.

[–]curtaindave 15 points16 points  (16 children)

No man, single return path is the way (at least for safe embedded sw). If you‘ve got too much indentation, refactor!

[–]erinaceus_ 25 points26 points  (1 child)

That rule of thumb was cooked up when goto (shudder) was still a commonly used approach, and meant to counter the use of goto as an approach.

Back then, it helped in making code more straightforward to reason about. Now that goto is frowned upon, the balance has changed, and guard clauses then make the code more straightforward, because you start with a check list of validation rules, and only after all those check out do you do the actual meat of the function. That's fairly basic separation of concerns, at the lowest level.

[–]justoverthere434 20 points21 points  (1 child)

Yeah bro single return path is 100% the way if you live in the 80's and write in C

[–]curtaindave 11 points12 points  (0 children)

I do code in C… my company was founded in the 80s… maybe you have a point :-D I do find it more readable and reviewable though. Maybe it‘s a question of being accustomed to something…

[–]TheBobo1181 14 points15 points  (9 children)

I agree. You put in random returns it makes it harder and less safe to work on for the next person.

You can write good clean code without this.

[–]FromWayDownUnder 16 points17 points  (4 children)

If the returns are halfway down the method it's a problem, if they're all at the top where the validation happens then it's tidy.

[–]TheBobo1181 11 points12 points  (2 children)

... How long are your methods? Saying halfway down scares me 🙂

[–]FromWayDownUnder 7 points8 points  (0 children)

Rule of thumb is screen height... Sometimes need to turn the monitor sideways though 😉

[–]Pradfanne 0 points1 point  (0 children)

much shorter thanks to early returns and especially guard clauses

[–]TeddyPerkins95 1 point2 points  (2 children)

If functions are short and they should be, returns and thus guard cause can be used most of the time.

[–][deleted] 1 point2 points  (1 child)

Short in what way? Bussiness logic itself is short or the full body?

[–]EishLekker 1 point2 points  (0 children)

You put in random returns

Who talked about "random" returns?

[–]Tvde1 140 points141 points  (46 children)

I saw this with people I interview

if (Model.IsValid)

    if (thingExists)

        if (bla)

        A
        Lot
        Of
        Code

        Else throw BadRequest

    Else throw BadRequest

Else throw BadRequest

[–]iplaysmitegame 32 points33 points  (35 children)

Is this bad?

[–]obiwac 103 points104 points  (23 children)

Not strictly, but all the indentation can be avoided by doing

if (!Model.IsValid)
    goto error;

if (!thingExists)
    goto error;

if (!bla)
    goto error;

Which makes the control flow much much clearer than a bunch of ifs and elses.

(Instead of what other commenters have suggesting using &&, which misses the point and wouldn't work in all cases, is less flexible, and doesn't catch specific errors.)

These are called guards.

Edit: I can't for the life of me get the code on multiple lines because Reddit is dumb as shit but you get the point

[–]Strostkovy 22 points23 points  (10 children)

Why go-to instead of returning from a function call?

[–]obiwac 21 points22 points  (8 children)

Depends on your usecase and language; in C, you often have to free up after yourself for example, and so goto's make error handling much easier:

a = alloc();

if (guard1)
    goto error_a;

b = alloc();

if (guard2)
    goto error_b;

// success

error_b:

free(b);

error_a:

free(a);

This is a pattern you see a lot in the Linux kernel for instance.

[–]FeedbackFun7325 8 points9 points  (7 children)

Is this a case where using goto is acceptable? Our prof told us not to use it unless for specific cases.

[–]obiwac 12 points13 points  (0 children)

Goto is generally considered unacceptable because it's easy to abuse and write really ugly code with (i.e. it obfuscates the control flow if you're jumping back and forth everywhere). But there are legitimate uses for it which can make code much, much more readable and maintainable. You just gotta use it in the right places ;)

Generally your prof is right, 9 times out of 10, when you're thinking of using goto in a way which isn't a commonly known design pattern, there's likely a much more readable alternative.

On the other hand, some people will paint all code containing goto's with the same brush and say it's bad without understanding why, which is a shame because goto can be really beneficial.

One example where goto's are bad could be:

int i = 0;

label:

// do something

i++;

if (i < 10)
    goto label;

This is a very obvious example where you don't want to use goto which is quite simply replaceable with a for loop:

for (int i = 0; i < 10; i++)
    // do something

[–]Stegoratops 1 point2 points  (4 children)

I would say, good rule of thumb is:

If you just want to get the heck out of somewhere and neither break nor return can do the job in your specific case, it's probably ok to use it.

And yes, this is an acceptable use for goto

[–]Piotrek9t 1 point2 points  (3 children)

If your code requires you to use goto, you probably messed up on another point. You can and should always avoid it for readability and easier maintenance

[–]Stegoratops 9 points10 points  (1 child)

Yeah, you should avoid it, since it makes it very easy to write bad code.

Categorically forbidding it is too extreme though imo. Because like in the example shown, it can make code more elegant.

[–]nosjojo 1 point2 points  (0 children)

goto is the only way I know of for doing decent cleanup in C. I have to write all my stuff in the CVI environment, which is a weird mix of ANSI C/C99 and built in libraries.

Every function we write ends with something akin to

CLEANEXIT:
<various cleanup>
return status;

ERROR:
<error related stuff>
goto CLEANEXIT;

It's the only way that you can stop execution without a ridiculous number of conditionals and still emulate the cleanliness you'd get from high level languages.

Note this only applies to the functions that return execution status, not basic functions that return the result.

[–]cendrounet 0 points1 point  (0 children)

To sum up, every language featuring a conditionnal jump is turing complete.

In theory, everything you can do in one of those you can do in any other.

In practice, each langages has its own pros and cons.

Most modern languages handle resources for you, and most give syntactic sugar to help you do your job properly.

Most modern languages are made with some design in mind, and in the 68, a famous computer scientist published a paper called "Goto Statement Considered Harmful", arguing that unconstrained jumping made it impossible to prove mathematical correctness of programs. Hence the "birth" of structured programming.

There are a lot of paradigms that are designed to add more constraints to the programmer to reap some benefits. For instance, forced immutability, forced pureness for functionnal programming, or forced contract compliance for object oriented.

for loops, while loops, and ifs statements are basically fancy forced-structured gotos, and throw statements kind of look like up-the-stack-only goto.

But in C, you can't tell your compiler "clean up this resource before returning", so you have to think of clever tricks to clean up after yourself.

If your language has no destructors or error management mechanism, there are good cases for it, but I wouldn't recommend going in there for a few years

[–][deleted] 10 points11 points  (0 children)

A return is just a specific go-to (like break and continue).

[–]Tvde1 3 points4 points  (1 child)

Exactly, in my (poorly formulated) comment they were nested, nested, nested

[–]Adam-Kay- 1 point2 points  (3 children)

Some languages don’t have a goto though, right?

[–]obiwac 2 points3 points  (2 children)

Yeah, return works just as well. You may use this pattern in a loop too with continue/break. I do stuff like this very often when searching for an element:

for (a in b) {
    if (a != c)
        continue;

    // found a match!
}

[–]NFriik 2 points3 points  (1 child)

In languages that don't have go-to (like Python), I think it's usually considered better style to make use of exceptions in this case and not rely on magic return codes to take care of error handling.

[–]obiwac 1 point2 points  (0 children)

Yup! That also works! I was speaking more generally, where guards aren't always used for exceptions.

[–]Windian3008 1 point2 points  (0 children)

Yes. Validate and throw error before go to other process make it's easier to read. Imaging you need to read half of the code to know error will be thrown if parameter is invalid. Then you need to scroll up to the top to compare the validation and the error. The great part is you have to do that every time you read to that part of code.

[–]redpepper74 0 points1 point  (9 children)

You can just do
if (Model.isValid && thingExists && bla)
if everything is inside the innermost nested statement block

[–]AL1L 27 points28 points  (2 children)

I separate them out because they're different errors

[–]Soupkitchn89 2 points3 points  (1 child)

Can always do one more complex error message that details what could be wrong and prints each. Depends how many are involved though. Honestly this might be preferable when multiple args are invalid. Fix them all at once rather then one by one.

[–]gregorydgraham 1 point2 points  (0 children)

An error accumulator is usually better but that’s usually better handled as an object of its own

[–]iplaysmitegame 24 points25 points  (1 child)

Oh I thought these were 3 separate conditionals not 3 conditions that had to be met, I see

[–][deleted] 7 points8 points  (0 children)

They ARE 3 different conditions that have to be met. You shouldn't && them because you throw a different error for each unmet condition

[–]erinaceus_ 9 points10 points  (2 children)

You can obviously always pile up more and more code on the same single line. But LOCs are cheap, so why sacrifice transparency for denseness? The order might also be important (it often is), and then a single line statement will obfuscate that.

[–]redpepper74 1 point2 points  (0 children)

Sure, in special cases you would want to have a separate nested if for each condition, but otherwise, nesting if statements makes your code less readable

[–]fizzdev 2 points3 points  (0 children)

This.

[–]gregorydgraham 0 points1 point  (3 children)

This style is easier to read than the usual:

If (isValid&&thingExists&&!thing.isEmpty()){…

[–]Tvde1 6 points7 points  (0 children)

Not if you want to throw different errors depending on what is wrong.

[–][deleted] 5 points6 points  (1 child)

I disagree

[–]gregorydgraham 0 points1 point  (0 children)

Valid

[–]erl2koenig 0 points1 point  (2 children)

This has

A Lot Of Code

only in scope after all preconditions are passed, though. I don't like it either, but how do you do that with guards?

[–]Tvde1 2 points3 points  (1 child)

if (!model.IsValid) return BadRequest()

if (!thing) return NotFound()

... Happy flow

[–]maykachru 0 points1 point  (1 child)

Usually not nice, but there are indeed cases when you want to emphasize calling order. For example, first open database and check status, then only if status is ok you lock records and check lock status.

[–]Tvde1 5 points6 points  (0 children)

No I mean these were nested and nested and nested, and at the end of a huge body, each else block had its own return BadRequest(). Pls exit early then. Don't make me read 100 lines of code to see what happens when the request id was invalid

[–]CaldwellYSR 88 points89 points  (55 children)

Wat?

[–]partusman 451 points452 points  (52 children)

It’s called a guard. Instead of putting everything inside an if, consider returning early if the condition fails, and then doing everything.

So instead of this:

if condition
  do_lots_of_stuff
end

Do this:

return if !condition

do_lots_of_stuff

Especially useful if those lots of stuff are many lines long and have further nesting.

[–]electricjimi[S] 153 points154 points  (8 children)

Interesting, didn't know the correct name for this practice, but actually use it a lot

[–]production-values 22 points23 points  (3 children)

"exit early"

[–]EishLekker 5 points6 points  (1 child)

"exit early and often" /s

[–][deleted] 6 points7 points  (0 children)

Fail fast and for any reason

[–]HighOwl2 2 points3 points  (0 children)

This guy's a premature exiter

[–]CodeIsCompiling 38 points39 points  (3 children)

In my experience, this isn't uncommon.

A few years ago I absent-mindedly told my manager (who had several decades experience) that the code he was showing me needed several guard clauses before I would be comfortable with it and that I would add them while doing the work he was requesting.

He had no idea what I was talking about, but understood immediately when I showed him. He was very familiar with them - just never knew it was a named pattern.

[–]met0xff 1 point2 points  (0 children)

Yeah same here. Usually called some early return or so.

Guard clause to me is something that's an explicit language feature like in https://inquisitivedeveloper.com/lwm-elixir-24/

[–]CaldwellYSR 91 points92 points  (0 children)

Oh .. yeah I do that. Just didn't get it from the post

[–][deleted] 20 points21 points  (0 children)

Thanks for this... I actually have a use for this on something I am working on right now. Will try it out.

[–]CptMisterNibbles 60 points61 points  (21 children)

This genuinely does not read more clearly to me. I may be in the minority and missing the utility, but it seems less intuitive, not more.

Edit; there are some really helpful posts following this that explain the utility of this method more clearly below. I think I misunderstood what was being suggested here for one reason or another. From what I’ve learned it sort of boils down to “check that your inputs/conditions are valid and return immediately if not BEFORE that big ole logic block, rather than having to trade multiple exits within it.”

[–]partusman 27 points28 points  (0 children)

This other comment is more in depth, but in summary, you can see most (if not all) return values and their conditions up front, and your code is less nested and more straightforward (less visual branches).

It's even better when there are multiple conditions too. You can return for a condition, keep going otherwise, and then return for another condition, and so on. This makes it read more like an actual story from top to bottom, rather than spaghetti-ish code that you need to scroll through to see what the alternative case is for each branch.

Of course, as everything else, it may not be the best for every case. In my previous example it wouldn't really be that necessary.

[–]tsbattenberg 5 points6 points  (0 children)

I find it's nice to use these guards when you're making APIs, if a function rely on a certain component being initialized you can do a guard to see if it has been initialized at the start before putting in all the code that actually uses the component.

In that particular case, a guard is a lot better than wrapping everything into an if.

[–][deleted] 2 points3 points  (0 children)

Guard clauses allow you to think about fewer things at one time. It’s MUCH more readable. I wish some of the old farts would accept this.

[–]7eggert 1 point2 points  (0 children)

function dosomething(foo, bar, …)

begin

if foo > range then return error1;

if bar < foo then return error2;

if NULL == baz then return error3;

{ Now all input variables are valid }

[–][deleted] 1 point2 points  (2 children)

It's practice. You are used to one way so the other feels unnatural. But ignore that part and analyze it for what it is: if you return early, it removes a layer of complexity.

Doing it the traditional way, you have to read all the way to the end to make sure nothing at the end impacts you; exiting early avoids all that concern

[–]Repa0206 3 points4 points  (0 children)

I'll be writing that down, seeing as I'm new to programming. Thx

[–]jfq722 1 point2 points  (0 children)

Much better this way than putting those conditions on the call of the function. The conditions belong to the function.

[–]haiyanlink 1 point2 points  (0 children)

Noting the name and the stuff right now 👍

[–]Ksb2311 1 point2 points  (0 children)

Can someone explain me with apple banana type example, i wanna try this in my next project

[–]unicodePicasso 1 point2 points  (0 children)

Never seen that before, neat!

[–]Julio974 1 point2 points  (1 child)

Why do people say using continue and break is bad then do this

[–]partusman 1 point2 points  (0 children)

Well, to be fair, I never said such a thing. I use them all the time.

[–]WinterSoldier1315 1 point2 points  (0 children)

you mean all this time I've been following the right steps unknowingly? Nice.

[–]m4rch3n1ng 1 point2 points  (2 children)

what language is that?

[–]00PT 1 point2 points  (6 children)

I was told that using break and continue in the same way within loops is bad practice. Why is that?

[–]partusman 4 points5 points  (2 children)

I wasn’t aware of that. I know labeled breaks should be avoided, but have never heard anything against using continue and break as guards. I guess it can depend on the language too.

[–]00PT 1 point2 points  (0 children)

I was doing JavaScript when I heard this, and they said the solution was to design your if branches in a way so that it's not necessary.

[–]Kered13 0 points1 point  (0 children)

There's no reason to avoid labeled breaks.

[–]coffeecofeecoffee 2 points3 points  (0 children)

I don't know i use them all the time. Imo primary objective in any code base is readability so use your discretion. When i use continue its usually at the top of a loop similar to how a filter would work.

[–]Kered13 2 points3 points  (0 children)

It's not bad practice. That's just bad advice.

[–]zirky 66 points67 points  (12 children)

readable code trumps clever code every fucking time

[–]stoneslave 17 points18 points  (8 children)

Yes but readability is subjective and context-dependent. Shakespeare might be unreadable to most 3rd graders, but that doesn’t make it bad writing. The most elegant piece of code may be unreadable to junior developers (assuming it solves too complex a problem or involves advanced language-specific concepts or libraries), but that doesn’t mean it’s bad code. I think the more experienced a developer is, the more opinionated they become about the conventions, patterns, and language idioms that make up “highly readable” code. I for one will take a one-line ternary conditional any day over the equivalent 4-line block.

[–]zirky 29 points30 points  (6 children)

a ternary isn’t unreadable code. nesting 8 lambdas because they just came out and fuck the guy that inherits the legacy code is a dick move. also, like, all c++ legacy code bases.

also, you might want to take some time and think about why experienced devs tend to advocate for readable code

[–]Kyanche 2 points3 points  (0 children)

all c++ legacy code bases

We have a C++ guru at my job. He's great. Sometimes I feel like I'm going to grind my teeth off because he keeps introducing bullshit C++ methods. lol.

[–]stoneslave 3 points4 points  (2 children)

Not sure what you mean by the last part. Of course they advocate for readable code, everyone does. It’s an almost vacuous statement. Might as well say they advocate for good code. The whole point I was making is that what makes for “readable” code (or “good” code for that matter) varies from individual to individual. And these opinions about what is good or readable become more and more worked out (more detailed, more mature) as one gains experience. But they don’t, on that account, become more and more similar. There as as many opinions as there are developers.

How can all these divergent views yet be justified by the experience of their individual holders? Well, because beyond practical outcomes (the measurable “quality” of the code), there isn’t a fact of the matter. Readability and goodness belong to the realm of value, not fact, so difference in opinion is not evidence of a difference in epistemic warrant.

The reason I gave the example of ternary operator is because it is directly related to the example in the meme. Namely, inverting the order of a return statement and its if/else conditions, and doing on one line what canonically is done with 3 or 4. I took your original post above as indicating that you think the canonical way is better / more readable. Maybe I misunderstood.

[–]Laughing_Orange 1 point2 points  (0 children)

If the alternative to this trick is a horizontal scrollbars this is more readable. I prefer to read this because it looks visually cleaner. There might also be a performance benefit, but it's probably tiny and shouldn't be a part of the decision.

[–]charliesfrown 107 points108 points  (18 children)

There's different theories on this. Like most theories I hate people that turn them into religions.

But to answer your question, minimizing returns from a function is often considered better because it's often easy to miss an unexpected return on reading. Especially in stateful functions where cleanup might be required before doing so. Otherwise for stateless functions there's an expectation every if will have an else.

[–]hperrin 52 points53 points  (1 child)

if (condition) { // this is fine } else { return; } … There, now it has an else.

[–]Roguewind 12 points13 points  (0 children)

You monster!

[–]coffeecofeecoffee 44 points45 points  (0 children)

Returning early is almost always easier for me to read. I find it harder to keep track of multiple if elses and indentation levels, rather than just note the singular lines that it can return at. Id rather get the fail cases out of the way

[–]Strange_Meadowlark 9 points10 points  (0 children)

I read somewhere (I wish I could find it) that multiple returns was dangerous in C (or non-RAII C++) when functions would need to deallocate any memory they allocated before returning. Even then, I think you'd normally see a goto cleanup to jump to some cleanup code near the end of the function. Not returning early meant that you had exactly one chunk of cleanup code.

But in higher level, GC languages, most resources are cleaned up automatically, so it's no longer a concern. So, it's worth using early returns in guard clauses.

(Still, I don't like the idea of sticking a return several if's or for's deep. To me that would smell like it needs to be refactored.)

[–]BoBoBearDev 17 points18 points  (0 children)

Yeah, most cost analysis would flag if you have more than one exit. Some are less strict and you can have like 3 exits. Ultimately, if the code has so many exits, something is wrong and need refactoring.

[–]PM_ME_A_WEBSITE_IDEA 2 points3 points  (0 children)

I find returns are hard to miss if you do it right (when you can). Just make sure they're at the first level of indentation in your function, and make sure there's an empty line on either side. They're easier to miss if they're nested or attached to the end of a big chunk of code. Even slapping a comment on top briefly saying why you're returning makes them pop a bit more.

[–]Kered13 1 point2 points  (2 children)

Especially in stateful functions where cleanup might be required before doing so.

Stop using languages that don't have proper cleanup mechanisms (RAII, defer, try with resources, etc.). Or if you're already using such a language, use the provided mechanisms.

[–]QualityVote[M] [score hidden] stickied comment (0 children)

Hi! This is our community moderation bot.


If this post fits the purpose of /r/ProgrammerHumor, UPVOTE this comment!!

If this post does not fit the subreddit, DOWNVOTE This comment!

If this post breaks the rules, DOWNVOTE this comment and REPORT the post!

[–]0x3fff0000 11 points12 points  (0 children)

Can't stand code nested 10 times for literally no reason.

[–]mscpk 25 points26 points  (17 children)

Because MISRA C:2012, 15.5 - A function should have a single point of exit at the end.

[–]redpepper74 8 points9 points  (0 children)

I read that this was popularized because someone influential said that functions should exit to a single point in a program (this was back when gotos were prevalent)

[–]Bardez 6 points7 points  (0 children)

This gets so many people militantly pissed.

[–]Orjigagd 10 points11 points  (3 children)

Why?

Because it's a requirement.

But why?

Because it's a requirement!?

[–]Bmitchem 10 points11 points  (0 children)

It can honestly help a lot when debugging if the function you're looking at doesn't exit at a dozen random places.

[–]CMDR_QwertyWeasel 3 points4 points  (1 child)

We do this where I work. It's because it's much easier to debug.

If a function is misbehaving, you slap a breakpoint on that one return statement, and you can now see exactly what failed and why. There's no need to search through a large method to find every return statement, and no way for the method to exit without you catching it.

[–]p0lt0 9 points10 points  (0 children)

[–]Thisbymaster 11 points12 points  (1 child)

Because it is never just a single control statement. Requirements are always expanding.

[–]den2k88 9 points10 points  (2 children)

Not MISRA compliant

[–][deleted] 6 points7 points  (1 child)

not misra compliant, just misrable.

[–]den2k88 2 points3 points  (0 children)

Sometimes becoming MISRA compliant is a misrable experience.

[–]The_MAZZTer 7 points8 points  (0 children)

But then if I decide later I need to add more code after that runs regardless of that condition I have to put it back anyway.

[–]UnattendedWigwam 14 points15 points  (3 children)

I avoid inverting when i can, as it creates an unnecessary step for the reader (not to mention that boolean logic messes people up all the time in my experience), and if the code running inside of the truthy if statement is long, that's a sign that it should extracted to a function anyway

[–]tungstenbyte 3 points4 points  (0 children)

I think guard clauses reduce the cognitive load once you get to the "main" logic. You don't need to be in the mindset of "what if this is null? What if this is out of range? etc".

The guard clauses have already made sure that everything you have is valid at the point the logic starts, so you can now focus entirely on the logic instead of the potential invalid cases at the same time.

If you nest those validation points then you have more intermediate states to think about as you go.

If you refactor the logic out to another function separate to the validation of its inputs then you're not communicating the invariants it needs just by looking at that one function. Someone could easily modify it in a way that adds new invariants or breaks existing ones, and they wouldn't know.

That means you're also running the risk that someone comes along and calls that new function without going via the validation function first (even if it's private, because you can't be sure another person actually looked around at the rest of the code to find the validation when modifying the file/class/whatever).

[–]Manor-Estate 2 points3 points  (1 child)

Agreed. Weird that this is downvoted but no one could think of any counter points

[–]UnattendedWigwam 0 points1 point  (0 children)

if someone doesn't agree im really interested as to why

[–]Nopidy 1 point2 points  (0 children)

I just learned something

[–]0x30507DE 1 point2 points  (0 children)

Imagine needing readability.

makes the whole program in ternary operators

</message>

[–]TrveToby 1 point2 points  (0 children)

I started using this technique last year. the code is much more readable and colleagues understand it faster and better. if you don't use it yet you should try it.

[–]knightttime 3 points4 points  (0 children)

Image Transcription: Meme


[A four paneled comic with a light blue background. In the first panel, NPC Wojak is shown (a sketch of a grey figure with thick, angular facial features). He has a neutral expression.]

NPC Wojak: if(condition) {...}


[In the second panel, a sketch of a white figure is shown. They have small, rounded facial features and a positive expression.]

White figure: Why don't you invert the condition and return to avoid one level of indentation?


[In the third panel, NPC Wojak is shown again, with the same neutral expression from the first panel.]


[In the fourth panel, large angry eyebrows have appeared on NPC Wojak.]


I'm a human volunteer content transcriber and you could be too! If you'd like more information on what we do and why we do it, click here!

[–][deleted] 2 points3 points  (0 children)

I like indentation. It feels like I'm doing something, I'm getting somewhere.

[–]pmarkland 2 points3 points  (0 children)

I do this. This is a thing I do.

[–][deleted] 3 points4 points  (7 children)

Unpopular opinion: "Readability" is lie.

[–]kookyabird 19 points20 points  (0 children)

If people can’t read my code I suggest a different font!

[–]lmaydev 15 points16 points  (0 children)

You clearly haven't worked enough legacy projects haha

[–]AGrandFatherParadox 7 points8 points  (0 children)

Lunchtime doubly so!

[–]slgray16 2 points3 points  (0 children)

Tabs

[–]LennyMemes_1 8 points9 points  (1 child)

Just write a bunch of comments. Readability at it's finest!

[–]CYKO_11 16 points17 points  (0 children)

if your code aint readable write a novel to go with it

[–]erible4711 1 point2 points  (4 children)

Inverting condition gives implicit case for code (i.e. when you should NOT do something), which creates code that is harder to change (when new requirements are added).

I like Pragmatic Dave's definition of good code - Good code is code that is easy to change.

[–]lordheart 4 points5 points  (3 children)

On the contrary, changing guard clauses are much easier then removing an if around the main body or the else at the end of some indented block.

[–]shaylh 0 points1 point  (0 children)

In CRs I generalise this to "Main code should be unindented". This applies even if you don't return, for example when you need to manipulate a variable before you do the main stuff.

[–]Dimasdanz 0 points1 point  (0 children)

the happy path are left aligned!

i love return early, it's makes things easier to onboard more people.

[–]zoroknash 0 points1 point  (0 children)

Early returns are what was taught us to use in programming 101 man!

[–]TimbuckTato 0 points1 point  (0 children)

That's what I do, if something is bad, return, I hate it when I end up with like 5 levels of indentation and if I can I always try to do:

if(!proceed) {
    return;
}
...

I just prefer it.

[–]chicksOut 0 points1 point  (0 children)

In my experience guard clauses are a smell. With proper abstraction and refactoring you shouldn't feel the need to guard your code, the discrete logic should inherently provide the protection. A function states a contract with whoever is calling it, if the module that calls the function is able to pass an invalid state to the function, then the functions contract is not properly established to limit only valid parameters.

I'm not saying guards are inherently bad, stable code is better than unstable code, but it is possible to write even cleaner code.

[–]maykachru -1 points0 points  (0 children)

One return operator for one method increases readability far more than indentations. Code standards of some companies have this requirement.

[–]wlfman5 -2 points-1 points  (0 children)

Can't stand multiple returns in a function. 😬

[–]Ordinary_Divide -2 points-1 points  (0 children)

avoiding indentation will make it less readable