DEV Community

Cover image for If/else or just if?

If/else or just if?

Tyler Warnock on February 05, 2019

Today in a code review we had a statement like this: Statement A if (typeof val === 'string') { return 'A' } else if (val === nu...
Collapse
 
somedood profile image
Basti Ortiz • Edited

I prefer the second syntax because it acts like a "guard" against further execution, so to speak. The first syntax just encourages more nesting and levels of indentations. To me, it is more readable to have a "guard" condition than to have if-else blocks.

Collapse
 
tyrw profile image
Tyler Warnock

I hadn't encountered the term "guard" for this but I like it a lot 👌

Collapse
 
somedood profile image
Basti Ortiz

I can't take the credit for it. 😉

Collapse
 
immathanr profile image
Mathan raj

I call it the Short-circuit or (Fast-fail)[en.m.wikipedia.org/wiki/Fail-fast]. It will help you just worry about less things if it's not followed by else

Collapse
 
dexterstpierre profile image
Dexter St-Pierre

I have the same train of thought with it! A senior developer at a previous job introduced it to me

Collapse
 
pedrohba1 profile image
Pedro Bufulin

The first time I heard the term "guard" was in haskell. Is it any related?

Collapse
 
somedood profile image
Basti Ortiz

I'm quite surprised actually. Given the imperative nature of if statements, I wouldn't expect Haskell (of all languages) to be the origin of that term.

Thread Thread
 
fennecdjay profile image
Jérémie Astor

Haskell (among other functional languages, I guess) has guards for pattern matching

sign x |  x >  0        =   1
       |  x == 0        =   0
       |  x <  0        =  -1
Collapse
 
sunnysingh profile image
Sunny Singh

I always go with Statement B. This is known as "early returns" and helps with confusing success/error cases. Take for example:

function createPost(post) {
  // Earliest potential error if no post is provided.
  if (!post) return false;

  // Ensure correct data type.
  if (typeof post !== 'object') return false;

  // Ensure required data is provided.
  if (!post.title || !post.body) return false;

  // We're all good at this point. Assume it's safe to create the post!
  const isPostCreated = create(post);

  return isPostCreated;
}
Enter fullscreen mode Exit fullscreen mode

It's nice to know for sure that the end of the function where we're saving the post to the database will not error out due to bad data, since we already verified those cases earlier.

Collapse
 
scooby359 profile image
Chris

I like this style more - it looks clearer to me, and from the point of working through the logic, I like that the returns just end the function.

If a block just set a value and returned it later, there's a chance it could be reassigned in another buggy block, so I think there's less risk in this style too.

Collapse
 
tyrw profile image
Tyler Warnock

This looks great to me. I'd be happy even without the comments as it feels pretty self-documenting.

Collapse
 
sunnysingh profile image
Sunny Singh

I added the comments just for the sake of the example, but they should definitely be removed for a real app.

Collapse
 
antogarand profile image
Antony Garand

I prefer the first approach, it's ensures all cases are covered, and is more extensible IMO.

I also prefer a single return per function, excluding sometimes null / wrong validations, as this code tends to be easier to read and debug. In your example, I would use the first method, but assign the return value to a variable, and return it after the statements.

This made me thing of this post on hackernews: Please do not attempt to simplify this code

Kubernetes controller source

  1. Every 'if' statement has a matching 'else' (exception: simple error checks for a client API call)
  2. Things that may seem obvious are commented explicitly

We call this style 'space shuttle style'. Space shuttle style is meant to
ensure that every branch and condition is considered and accounted for -
the same way code is written at NASA for applications like the space
shuttle.

Collapse
 
sunnysingh profile image
Sunny Singh

TIL about "space shuttle style", very interesting.

I'm not sure if the Kubernetes controller source is meant to be used as an example though. Otherwise there would be no comment to warn people from simplifying the code.

Collapse
 
tyrw profile image
Tyler Warnock

Can you elaborate on the "cases are covered" point? In my mind both snippets covered all cases, but I'm open to hearing otherwise.

Collapse
 
antogarand profile image
Antony Garand

In this case, both examples are the exact same of course.

This is somewhat related to a single return statement in a function, but the syntax of an if/else if/else is more explicit than the various conditions are related to each other.

With few if statements each statement is independent from the others (unless you return in the previous cases, like in your example), therefore more than one of them can be triggered.

Overall, while there aren't many arguments for any of these approach in your specific scenario, I feel like it's a better practice to have a single style of conditions for your whole codebase. As the first approach is more flexible, I strongly prefer using it everywhere!

Thread Thread
 
sunnysingh profile image
Sunny Singh

Consistency is definitely most important. I just did a search through an API that I built recently, and I only have 3 else statements which I can probably refactor out. So, I think it's definitely possible to go all-in on early returns.

Collapse
 
simbo1905 profile image
Simon Massey • Edited

In other languages such as Scala and Rust there is a "match" statement and a compiler that looks at the types can tell you if all cases are matched. In Scala you can compose/chain together sets of partial methods that match a set of related cases and the compiler will tell you if the combination will do an exhaustive match. So what the Kubernetes example you post is pointing out is that the devs are having to work around a missing feature in the language they are using. Once you have used a language that has an exhaustive match you never want to go back. This is because it is very much easier to write code that you know won't just fall through to some wrong default case when someone adds a new type of input.

Collapse
 
wuz profile image
Conlin Durbin

I prefer B, if only because it is a one to one mapping of cases to output - when reading the function it says:

When function is called
If val is a string, then return 'A'
If val is null or undefined, then return 'B'
Return val otherwise
Enter fullscreen mode Exit fullscreen mode

This is a much more human way of thinking about the possibilities. I don't tend to think in terms of if/else conditions in the real world and I don't feel like much business logic works that way either. Option B is also easier to extend - if later you need to add an "if val is a number, return val.toString" or the like, then that is easy and you can add it wherever it makes sense in your code.

Slightly unrelated, but I also really perfer this style to switch statements. They have a place, but most times they should probably be multiple if statements.

Collapse
 
tyrw profile image
Tyler Warnock

@wuz Well said, and I totally agree on the switch statements piece. I'm not sure I've ever been satisfied with the look/readability of a switch statement in JS!

Collapse
 
coachmatt_io profile image
Matt

I don't prefer one over the other, but what I do prefer is a single return statement, so you can make more assumptions about the code (eg: should get to the end of the function if there's no error)

let result

if (typeof val === 'string') {
    result = 'A'
} else if (val === null || val === undefined) {
    result = 'B'
} else {
    result = val
}

return result
Collapse
 
maixuanhan profile image
Han Mai

IMO, the single return comes from C coding guidelines where it may help developers easier to trace the complex code and prevent them from forgetting release any resources which need finalizing (like freeing heap). For this point, C++ projects usually don't adopt this guideline since it has its own stack-unwinding thing.

For Javascript, I prefer the statement B for more readable code. Save everyone's effort.

Collapse
 
fhusquinet profile image
Florian Husquinet

I find it more confusing to return a variable in a return unless it is really basic (like changing the message of a JSON response depending the data given).

Early returns make it sure you don't even up with mutating the response somewhere later in the code. It also make more readable (imo) because not everything is nested.

Collapse
 
simbo1905 profile image
Simon Massey

A lot of people would recommend using const by default. A variable that can be many things is cognitive overhead and results in bugs down the line.

Collapse
 
farble1670 profile image
Jeffrey Blattman • Edited

I prefer the "return early" syntax. It puts a line in the code where if you pass it, you know some assertion holds. The code above doesn't really illustrate that, but for example:

if (flag1) {
  return;
}
// Anything that follows, regardless of if / else nesting
// I know that flag1 is false.

As opposed to:

if (flag1) {
  return;
} else {
  // some stuff
}
// Some more stuff. Is flag1 false?

In the second example, imagine some ugly nesting. For each block of code you need to think "am I in a level where I've tested flag1?"

Collapse
 
tyrw profile image
Tyler Warnock

@farble1670 so do you prefer a hybrid of first and second? Something like:

if (typeof val === 'string') {
    return 'A'
}
if (val === null || val === undefined) {
    return 'B'
}
return val
Collapse
 
gypsydave5 profile image
David Wickes • Edited

Another option (for those who favour expressions over statements) can be built out of JavaScript's ternary operator:

return (typeof val === 'string') ? 'A'
     : (val === null || val === undefined) ? 'B'
     : val

Quite a popular pattern.

Collapse
 
tarialfaro profile image
Tari R. Alfaro

Ternary operators are really nice for simple and small statements, but I definitely wouldn't recommend them for anything complex. Makes things to hard to read for me. The same could be said for other developers.

Collapse
 
byrro profile image
Renato Byrro

That's not easy to read at all in my opinion...

Collapse
 
qm3ster profile image
Mihail Malo • Edited

If we know the branches will have return, then B, plain if, aka early return is better.

We don't need to keep the context of whose else we are in anymore most of the time.

Even refactoring it is easier, both in terms of just editing the code and the resulting git diff.

However, if we don't have return...

let val
// ...
if (typeof val === 'string') {
    val = 'A'
} else if (val === null || val === undefined) {
    val = 'B'
} else {
    val = /* do something here lol */ val
}
// ...
use(val)

...then there are two options for me.

1. Extract into function

function testVal(val){
  if (typeof val === 'string') return 'A'
  if (val == null) return 'B'
  return val
}
// elsewhere...
let val
// ...
val = testVal(val)
// ...
use(val)

2. Use a conditional expression

let val
// ...
val =   
  typeof val === 'string'
  ? 'A'
  : val == null
    ? 'B'
    : val
// ...
use(val)

It just depends on the complexity, relevance, and size

What's particularly good about both?
They end up only assigning val once, so after some further refactoring we may end up with the superior const binding!

F.A.Q:

Is early return at odds with functional programming?
Should we strive to use conditional expressions at every size?

No. Used correctly, return is just guards in a match expression. You could see it as advanced pattern matching that is missing from JS syntax.
(Early throw, on the other hand, is usually a hack we have to use for lack of static types.)

Collapse
 
nektro profile image
Meghan (she/her)

The second one. Every time. For the early returns reason mentioned earlier. Since you're doing a return, the else is an anti-pattern.

Also this thread terrifies me for all the code that exists out there and solidifies everything about xkcd.com/2030/

Collapse
 
simbo1905 profile image
Simon Massey • Edited

Totally! "else" at the end of an if/else chain is a trap awaiting someone changing the input then making a mistake in the if/else such that the new input falls into the old else that does the wrong thing. Scala has "match" and the compiler gives an error if you don't match everything that can come in. Putting in a wildcard match at the end, which is equivalent of a last 'else' in JS, reads as "okay I don't recognise this input so I am going to ignore it". That screams anti-pattern as being both inefficient and inexact.

Collapse
 
tarialfaro profile image
Tari R. Alfaro • Edited

Which ever route is the easiest to read(usually it's the second one) is the one I pick. Less code is more.

I've worked with both a lot, and I find the second one is often better for my cognitive load. If you need if/else/elseif perhaps to many things are going on at once.

It depends on what kind of logic is needed, and which one reduces the amount of code and improves the readability.

Collapse
 
ryansmith profile image
Ryan Smith • Edited

I prefer Statement A since it is more familiar, more explicit, and groups the possible outcomes. Almost every programmer has seen and used option A. It doesn't require changing the structure to make an update, if something needs to be added before the return statements, it is easy and predictable.

The second statement seems like brevity for the sake of brevity to me. It is shorter, but I'd argue that it is not concise because it does not present the information clearly (at least to me). On Statement B, the formatting would trigger a red flag for me. I'd likely have to take a second or third look just to make sure I know what the intention of the code was. I don't like single line if-statements because all it takes is accidental reformatting without adding braces to cause issues that are easy to miss. Some will argue that their editor does this all for them so maintainability is not an issue, but when working on a team I don't think that is a safe assumption. I'm sure someone could also argue efficiency gains of option B (smaller JS file), but that seems like overkill for minimal gain.

Collapse
 
moopet profile image
Ben Sinclair

I think the second example is muddying the water by combining the pattern (failing early) with a style choice (single-line, braceless ifs).

I prefer Statement B, or would if it was written like this:

if (typeof val === 'string') {
  return 'A';
}

if (val === null || val === undefined) {
  return 'B';
}

return val;

I like this because it reduces nesting and acts as a barrier to people over-complicating a function. I mean that if the function ends up having to re-use a negated form of one of the earlier conditions or have a separate set of nested ifs after the guard conditions, then it's a big smelly smell and should be moved to its own function instead.

Also, if you think about it in terms of human experience, it's how we work. If you're tending a patch of garden, you don't think about what category of flower you're looking at and cross-reference it in a book if it's obviously a weed.

Collapse
 
madhadron profile image
Fred Ross

I use both in two different situations. I use the first form at the top of a function when I'm doing assertions about parameters. Think of it as poor man's type checking or contracts in languages that don't have them, e.g.,

def f(a, b):
    if not instanceof(a, int):
        raise ValueError('a must be an int')
    if a < 0:
        raise ValueError('a must be nonnegative')
    ...

I use the second form in the primary body of code unless I am forced to do otherwise. The lazy reason is that I write in both imperative and functional languages, and in functional languages all ifs must have an else statement, so by always having an else, I have one less thing to keep track of between languages.

The more philosophical reason is that using the else block makes it very clear what the branch is in the execution path. The precondition and postcondition for both branches should be the same and the effects required to bridge that gap are all confined to those blocks. I have come to value this kind of locality more and more over the years.

Collapse
 
orenovadia profile image
orenovadia

If you find yourself doing this often, check this out: pypi.org/project/icontract/

Collapse
 
harveydanger profile image
HarveyDanger • Edited

I reckon that it all depends on what is your target.

Return statements, of course, you can easily use approach 2 or ternary operation. However, if you do any operations on a particular block, rather than return, if-else if -else construction guarantees that if an expression is evaluated to true, other blocks would not be executed, hence -> save your precious runtime. Thus, it would be only visible on a high-demanding calculation blocks.

Collapse
 
jacksonelfers profile image
Jackson Elfers

First one. Brackets are consistent I feel and easier to assess. I've heard the argument about one return per function although then you're potentially creating a local variable to manage state. What's truly important is that your developers can effectively read it, after all the computer obviously doesn't care.

Collapse
 
chiangs profile image
Stephen Chiang • Edited

Wouldn't you put the null and undefined check first to have a quick return?

if (!val) return B;
return (typeof val === 'string') 
    ? A
    : val;

Of course, you could go back to the more explicit null and undefined check if you think you might get other falsy values that don't fall into that condition like 0, empty string, false, and NaN.

But to answer the question, I prefer just 'if' whenever possible.

Collapse
 
jasperhorn profile image
JasperHorn • Edited

I wouldn't do sample B as written because of the lack of braces for the if, which I'd always add (as well as spreading it out over more lines).

With that change, though, it's something that I do wonder about myself from time to time. With the exact sample given (where the else is just another return statement), I would usually go with sample A because the if-else-chain (which has a known mental model for me) nicely describes what happens. However, when the "else" portion is much larger (i.e. it's the "real implementation" after the corner cases have been taken care of) I'd probably go with something like sample B because it limits the levels of indentation that don't add information.

Ultimately, though, I'm not entirely consistent in this.

Collapse
 
danielw profile image
Daniel Waller (he/him)

As long as every branch returns then the 2nd version is fine with me.
(Although I'd still use brackets instead of guard clauses because of personal preference regarding readability)

It becomes a problem when the if does not return and gets more complex than a simple one liner.
I.e.

if (env.DEBUG) {
    Logger.log(/* message */);
}
// Rest of logic here

would obviously be okay, but


let var1;
let var2;
let var3;

if (/* Some condition */) {
    // Many lines
    // of code
    // that affect 
    // the state of 
    // the variables
}

// Rest of logic
// working on the 
// variables unconditionally,
// here

return result;

would not be okay, because it makes it really hard to reason about the output of the function and the logical flow of your data can't be parsed at a glance.

Collapse
 
dechamp profile image
DeChamp

definitely the just "if" boat here as much as possible, although I avoid single line and practice the bracket method.

Collapse
 
tyrw profile image
Tyler Warnock

@dechamp something like:

if (typeof val === 'string') {
    return 'A'
}
if (val === null || val === undefined) {
    return 'B'
}
return val

?

Collapse
 
dechamp profile image
DeChamp

yup! that is the good stuff right there!

And based off your example I would do this...

check for no value first, save the code from type checking if it's not set.

if (!val) {
   return 'B';
}

if (typeof val === 'string') {
   return 'A';
}

return val;
Thread Thread
 
tyrw profile image
Tyler Warnock

What if val is 0 or false? 😉

Thread Thread
 
dechamp profile image
DeChamp

You have a good point, but are you expecting your system to act like that? It's very rare you need to actually be checking for that, but if you do suspect it then definitely go for the finite checking.

But then again, I love using the "joi" package for my type checking.

Thread Thread
 
tyrw profile image
Tyler Warnock

Normally no, but in this case yes. It's a bare-bones project and the code is constructing a DB query from a set of known inputs, so null and undefined get treated as null, strings get quotes around them, and everything else is passed through.

Collapse
 
timkilian profile image
Tim Kilian

It depends on the case, but I would probably pick a mixed case like this:

if (typeof val === 'string') {
return 'A';
}
if (!val) {
return 'B';
}
return val;

The main reason is because blocks are in my opinion better to see and less confusing. I also try to avoid the tenary operator, but it really depends on the case. Sometimes it's just perfect. There is no need to write an else in this case. The else if wouldn't improve any performance, and for me it's better to have no else case at all.

Collapse
 
banditelol profile image
Aditya Rachman Putra

Hello, I prefer the second one, because in the past when I was reviewing my peer's code I was faced with the first style a lot and it put toll in my mind to process the meaning.

But I used to like the first one because it puts my mind at ease when writing it, knowing the else part is covered explicitly. But some time after when I need to read it again, to be honest, its not a nice experience.

Collapse
 
dvddpl profile image
Davide de Paolis

I'd definitely go for early returns.
less indentation, the logical steps are easier to follow, less code to read when you navigate through breakpoints while debugging.
also easier to further refactor if the single if statements get too long or complicated -> just move them to another function, which by the way would be unit-testable too.

Collapse
 
noahlaux profile image
Noah Laux

In favor of not having a if/else block if I can avoid it.

return typeof val === 'string' && 'A' ||
     val === null || val === undefined && 'B' || val;

or to be a little more descriptive

const isString = typeof val === 'string';
const isEmpty = val === null || val === undefined;

return isString && 'A' || isEmpty && 'B' || val;
Collapse
 
jaakidup profile image
Jaaki

This is a classic versus modern debate.
Classics are classics because they stood the test of time, in which case statement A is preferred.
If any calculation were needed after the if and before the return, you would need Statement A in any ways, so isn't it more consistent?

I'm totally over trying to get code into super compact pieces after seeing a 140 line program shoved into a one liner in a coding competition :D Took me 140 hours to figure out what it does!

Collapse
 
darusx profile image
Fabián Montero

At the beginning of my career I used to use the if-else syntax. Now I see just if syntax more readable

Collapse
 
maixuanhan profile image
Han Mai • Edited

For easier readable, I prefer Statement B.
You know? This remind me the break statement comes after a return in switch...case. For such the case, I support break should come after finish every case branch. Just for safe 🙂

Collapse
 
thejaredwilcurt profile image
The Jared Wilcurt • Edited

There isn't much value in the else since the first conditional results in a return, however having it aids in readability in this case by grouping these two similar conditions. but having a final return outside of a condition is a best practice to ensure you don't mistakenly return undefined. The trailing else should be removed if it is just a return statement.

function (value) {
  if (typeof(value) === 'string') {
    return 'A';
  } else if (value === null || value === undefined) {
    return 'B';
  }
  return value;
}

Though in many cases, a map works better than a bunch of if/else's.

function (state) {
  const states = {
    indiana: 24,
    ohio: 36,
    florida: 19
  };

  return states[state] || 0;
}

Using the mapped approach eliminates any need for switch statements.

Also, don't abbreviate your code, there is no benefit gained from shaving off a few characters. Let the uglifier worry about that. Your goal should always be readability above all else until something is noticeably slow.

Collapse
 
nmhillusion profile image
nmhillusion

I think the original way is clear and more readable.

Collapse
 
devhammed profile image
Hammed Oyedele

I prefer just if with early returns as it reduces nesting conditions.

Collapse
 
betkowski profile image
Betkowski • Edited

I always try to save as much space as I can, so I guess it's the choice B for me.

spaceSaving ? if : if/else;
Collapse
 
plaoo profile image
Paolo Monni

If else of course!

Collapse
 
biros profile image
Boris Jamot ✊ /

I prefer the second approach, but with curly braces.

Generally speaking, I return ASAP like you did to avoid nested code and big if/else statements.

Collapse
 
ozeta profile image
Marco Carrozzo • Edited

If present then Stick to codebase convention
Else prefer readbility of the method

😬

Collapse
 
tyrw profile image
Tyler Warnock

Well which one is more "readable"? 🤔😎

Collapse
 
ozeta profile image
Marco Carrozzo

As our phylosophy teacher used to say: we are debating about angels gender... Anyway I think I stick more for the first one. I work in Java and there is a plenty of other situation to use one-liners.

Collapse
 
dmerejkowsky profile image
Dimitri Merejkowsky

I talked about that in one of my articles, using Python instead.

What I found out is that there's not just one good answer for these types of questions.

Feel free to read the comments there to, I found all of them pretty interesting, and they can apply to JavaScript to :)

Collapse
 
ravavyr profile image
Ravavyr

I see a ton of comments on this thread and i read through about half.
I don't see anyone making a case for method A.

I prefer method A because conditionals rarely do just one thing inside them like these comments would have you think.

eg.
if(something){
//one line here
}else if(anotherthing){
//one line here
}

If this were always the case, then having just if statements after each other is simple and easy to read and maintain.

More often than not it's "//50 lines here" in between the conditions, and if you're not using squigglies (brackets) then your code quickly becomes unreadable. You won't know what conditional you're inside of even with indentation.

And yea, someone's gonna go "You should never have 50 lines inside a conditional!"
Ok, so you'd have a conditional that calls a method that calls another 5 extracted methods in other files right? because THAT solves the problem, when it really just makes your code more convoluted and harder to follow.

Also, does it really hurt so much to just write "else" in front of an if statement? So you always KNOW that this is A. not the only condition, and B. not the last condition either.

In the long term it's never good to minimize your code like that. You always end up with someone going in to add something to the conditional and because they added a second line it now breaks because of a lack of squigglies. The code executes the second line always because it's not "inside" the if statement.

It's just better practice to always wrap things so they're maintainable in the long term.

My 2 cents.

Collapse
 
apisurfer profile image
Luka Vidaković

Statement B in general, because of indentation and context, even though you need to be careful about conditional cases. It's generally easier to follow through. IT REQUIRES MUCH LESS COGNITIVE LOAD because you don't need to think about all the cases that might have happened before or might happen afterwards if the specific condition is true or false. It's mostly used when you want to quickly check for a very bad usage of a function. Parameters that might break your logic. In that case you'd have 1-2-3 if clauses that check for bad params and immediately return/throw error. Alternative to that is to let the bad param checking leak to ALL of you NESTED conditional cases and make your code very hard to read. In that case you need to check for valid params inside of nested code and it's quite possible that similar code will occur a couple of times in the same function, which is crazy.
If you at any point end up thinking that it's not enough, that you need to take care of a bunch of complex cases, your function needs to be broken down to a smaller and composable functions that each do 1 thing and then revise all of the surrounding logic.

Collapse
 
simbo1905 profile image
Simon Massey • Edited

I vote for a mixed style: return early if there is an obvious default case (a guard) then use an if/else for some set of related cases. My reasoning is below.

I first ran into this waaaay too long ago in a code review with someone who said "a method should have one exit point" whereas i was liking the "exit early" or "guard" approach. I argued "but if you use early returns you don't have the cognitive overhead of needing to reading the whole method". Yet to them "single return" was The One True Way so we agreed to differ. My guideline for what to do when two devs disagree on a purely stylist matter is that the code remains as-is. I actually cannot remember whether it was my code or their code that was under review.

Unfortunately early returns is often a rotten code smell of "couldn't be bothered to refactor to add a new feature". In that anti-pattern you have a God Object / God Function and to add new features you add a fresh block at the top of the enormous "doAnything" method to detect your new scenario, call your new feature logic in another file, then return early. Then "ta da!" you never have to refactor the God code or change its unit tests (which are incomplete) nor manually test anything other than your new feature case. This leads to an immediate Broken Glass model where the next dev copies that approach. Pretty soon you have a thousand line method that keeps on growing with every new feature added. Regrettably large OO code bases that have seen any team turnover tend to default to this sort of thing remarkably fast.

If you tempted to return early in more than a single obvious default case then perhaps you should break up the class or method into different units that can be composed where each unit has an if/else set for some closely related cases. You then end up with smaller functions or classes that handle a tight set of cases. Then you can take a mixed approach. Try to only return early if there is a really common default case. Why? Because during debugging you don't want someone to have to read the whole code if there is a very common case. The more early returns you put in the more the code is asking to be broken up. The more complex the if/else starts the more you should break it up into different units that handle a more narrow set of cases.

Collapse
 
molecula451 profile image
Paul

I do like the if/else case. Where sometimes when you are actually reading the codes it gives a better insight on the app and just like piece of orchestration or a music it makes sense (it rythms). It does sound and it is a good coding practice.

Collapse
 
fluffy profile image
fluffy

The second approach is nice if and only if all of your branches result in a return; however, it's not great if you're trying to do something else with the result of evaluating the conditions.

Collapse
 
lysofdev profile image
Esteban Hernández

I'd use the second for simple conditions and as 'guards', mentioned below. The more verbose if/else if/else would be used for more verbose conditions.

Collapse
 
kelp404 profile image
Kelp

Statement B

Collapse
 
krusenas profile image
Karolis

don't forget the switch! :) quite often it's a lot cleaner solution than multiple if/else statements

 
simbo1905 profile image
Simon Massey

interesting that modern languages are putting in generators and "yield" that have multiple exits that save the stack and then reenter into a new position with the saved stack.

Collapse
 
byrro profile image
Renato Byrro

I find this version even more difficult to read...

Collapse
 
wolverineks profile image
Kevin Sullivan

Why is val not already typed? It could be anything?!? I'd rather look into avoiding either of these situations and make sure the type of val is already known.

Collapse
 
audente profile image
Juan

My vote goes for option B.
Since I learned the Swift guards I prefer that style.

Collapse
 
elabftw profile image
eLabFTW

I'd keep the curly braces but remove the last "else" because it's useless.

Collapse
 
dechamp profile image
DeChamp

Hey checkout my new post, inspired by your post. dev.to/dechamp/clean-up-your-code-...

Collapse
 
leob profile image
leob • Edited

I'd never code A, always B, no doubt about it. Since the 'return' statement ends execution there and then, IMO the 'else' clauses don't make sense at all.

Easy one I would say.

Collapse
 
svedova profile image
Savas Vedova

In Golang if the if statement is returning, the linter will complain about the else statement. In short,

if statement == true {
  return 
}

// This is the else statement
Collapse
 
likhitapatra profile image
Likhita

I either user Ternary operator or the statement A type of syntax. But after reading this thread definitely will stick to statement B or ternary operator depending on the situation.

Collapse
 
sebbdk profile image
Sebastian Vargr

I tend to use a small map, or a ternary in these situations.

If’s without brackets breaks the bracket consistency for me, and ‘if else’ can be hard to read.

Collapse
 
heithemmoumni profile image
Heithem Moumni

I prefer the second, It's clean and readable :D

Collapse
 
mateiadrielrafael profile image
Matei Adriel

I usually go for the if + else if and no else at the end

Collapse
 
patricnox profile image
PatricNox

Is the if and elseif statement about same scenario?

Yes.

Is the if and elseif statements not about same scenario OR is taking up more than 10 lines?

Switch case.

Collapse
 
fyodorio profile image
Fyodor

Ternary operator

Collapse
 
tyrw profile image
Tyler Warnock

Great points!