DEV Community

Cover image for Stop using if else
Rishav Jadon
Rishav Jadon

Posted on

Stop using if else

Recently, I had a take home assignment for a front end role, and I had to make a sort of Dashboard. I thought I did everything right, but I was rejected, partly on my carelessness, and also due to my code. I was using too many if/else statements everywhere! And I didn't know any better. But now I do, and I'm here to share that with you.

Most of us use if/else and switch statements whenever there is some conditional logic to handle. Although it might be a good idea to do that for one or two conditions here and there, using multiple if else statements chained together or big switch statements will make your code look very ugly, less readable and error prone.

function whoIsThis(character) {
    if (character.toLowerCase() === 'naruto') {
        return `Hokage`
    } else if (character.toLowerCase() === 'sasuke') {
        return `Konoha's Strongest Ninja`
    } else if (character.toLowerCase() === 'isshiki') {
        return `Otsutsuki being`
    } else if (character.toLowerCase() === 'boruto') {
        return `Naruto and Hinata's son`
    }
}
whoIsThis('')
Enter fullscreen mode Exit fullscreen mode

You see that we are repeating ourselves many times by writing multiple console.logs and if statements.

But there's an Object-Oriented way of doing this, and that is by using Objects.
Instead of writing if else blocks we just define an object which has the values we use in comparisons as keys, and the values we return as values of the objects, like so:

function whoIsThis(character) {
    const listOfCharacters = {
        'naruto': `Hokage`,
        'sasuke': `Konoha's Strongest Ninja`,
        'isshiki': `Otsutsuki being`,
        'boruto': `Naruto and Hinata's son`
    }

    return listOfCharacters[character] ?? `Please provide a valid character name`
}
Enter fullscreen mode Exit fullscreen mode

By using objects, we were able to make a sort of dictionary to look up to, and not use multiple if-else statements.

We can also make this better by using the Map object instead of using an object. Maps are different from normal objects:

  • They remember the original order of insertion
  • Unlike objects, we can use any type of data as key/value, not just strings, numbers and symbols.
function whoIsThis(character){
const mapOfCharacters = new Map([
['naruto', `Hokage`],
        ['sasuke', `Konoha's Strongest Ninja`],
        ['isshiki', `Otsutsuki being`],
        ['boruto', `Naruto and Hinata's son`]
])
return mapOfCharacters.get(character) ?? `Please provide a valid character name`
}
Enter fullscreen mode Exit fullscreen mode

Thanks for reading this short article, if you liked it, you can support my work at https://www.buymeacoffee.com/rishavjadon

Discussion (66)

Collapse
d3sox profile image
Nico

I agree with what @bubster said. You should rename it to "stop abusing".

Plus I did some benchmarking. It seems like if/else is always the slowest, using a Map makes only a negligible difference in Firefox, and an object is much faster in Chrome. Test for yourself: jsbench.me/jekur7m830/1

(I modified your code a little bit to keep things fair. You called toLowerCase for every branch in the first example and didn't use it in the latter two. I also moved the declaration of the object/Map out of the function, otherwise it would be created for every iteration)

When adding more calls like

whoIsThis('naruto')
whoIsThis('')
Enter fullscreen mode Exit fullscreen mode

to each test case if/else actually wins in Chrome which makes me think if Chrome somehow caches it.

Collapse
michaelcurrin profile image
Michael

At large scale a lookup by key is far more efficient. At small scale it is maybe small difference.

If you had extreme case of code of say 1000 branches of if else statements, at worst it takes 1000 attempts until the last one matches.

While looking up a value from an object/map by key is constant - only needed exactly one attempt to find the result.

Collapse
rjitsu profile image
Rishav Jadon Author

Oh my bad for not using toLowerCase in further examples! Thanks for the tip about moving the dictionary out of the function.

Collapse
bk profile image
BK ☕

You agreed with the tip, but the code example is still not updated. It's better to make the change, so beginners can learn from better examples.

Collapse
bk profile image
BK ☕

Btw, my other comment was referring to "Thanks for the tip about moving the dictionary out of the function."

Have a lovely day.

Collapse
phantas0s profile image
Matthieu Cneude

Ah! Sweet coding challenges. I still remember this CTO who wanted me to replace an if else statement using a strategy pattern... the code was 10 lines. How to introduce useless complexity 101.

using multiple if else statements chained together or big switch statements will make your code look very ugly, less readable and error prone.

Why? I mean if it's so ugly, less readable, and error prone, why so many programming language implement them?

Collapse
andreidascalu profile image
Andrei Dascalu

The first solution is NOT an object-oriented solution. You're using a JS "object" as a poor man's map of sorts but you're not using anything remotely OOP.

Collapse
phamn23 profile image
Nathan Pham

it's the equivalent of saying using JavaScript is already OOP because everything is an object 😂

Collapse
andreidascalu profile image
Andrei Dascalu

well ... not really. There's the so-called object notation in JS and the definition of an object as per OOP, which on a higher level is the data represented + methods (any methods, regardless whether you implement encapsulation or not). An "object" { "foo": "bar" }; might be called an object in JS notation, but no in OOP as it lacks methods and a definition (eg: a class of which the object should be an instance of).

Thread Thread
rjitsu profile image
Rishav Jadon Author

Well if you're going that deep, you should know that JavaScript is a prototype based object oriented language, rather than class based, but it still is object oriented, so technically yeah an object is js is an object in OOP

Thread Thread
andreidascalu profile image
Andrei Dascalu

As long as you also define methods on the prototype, yes. Object oriented isn't just "call stuff objects". The core of OOP is the communication between objects, regardless of how they are implemented. Encapsulation, inheritance/composition, etc. JS very much an OOP language, but if it's not an instantiated structure according to the definition, it's not an OOP object.

Collapse
manchicken profile image
Michael D. Stemle, Jr.

I love this post. It’s missing a bunch of details, such as how you can use functions instead of strings to match the items, and that this is a contemporary implementation of a “Command Pattern.”

Many of the responses aren’t terribly helpful, and some are a bit on the rude side. We should be more willing to entertain someone else’s ideas than to simply shoot them down as many comments on this post do.

Rishav, your idea could use more fleshing out, but I like where you’re going with this. I would very much like to see you continue on this thought, and address how this pattern can lead to a reduction in cyclomatic complexity and an overall increase in testability of the function implementing this pattern.

Collapse
rjitsu profile image
Rishav Jadon Author

Thanks Michael, yes the comments are filled with useless people just wanting attention. Still thinking about this and surely will provide a better version in the future!

Collapse
naveennamani profile image
naveennamani

This only works if you're comparing a single variable with known values. For other cases you've to use if/else

Collapse
rjitsu profile image
Rishav Jadon Author

Can you share any example where you cannot make use of this?

Collapse
naveennamani profile image
naveennamani
if(a===10) {
...
} else if(b===20) {
...
} else {
...
}
Enter fullscreen mode Exit fullscreen mode
Thread Thread
rjitsu profile image
Rishav Jadon Author

I meant a real example from code. Anyways, we need to write good code in order to not add conditionals like these.

Thread Thread
bubster profile image
TvO • Edited on

This is a perfectly fine example of real code lol.

Thread Thread
coolprofessor profile image
coolprofessor • Edited on

Here:

function signIn(user,password){
    if( user === 'bob'  && password === '' ){
         return true
    }else if( user === 'sally' && password === 'gitIsCool7#6' ){
         return true
    }else if( user === 'jerry' && password === 'hackme123' ){
         return true
    }
}

signIn('jerry','hackme123');
//will return ability to sign in (boolean)
Enter fullscreen mode Exit fullscreen mode

@naveennamani is right. There are ways to do things with an array, but it can sometimes get over complicated and unreadable.

Thread Thread
davidlazic profile image
David Lazic • Edited on

There are still elegant ways to handle that kind of requirement within the function:

  function signIn(user, password) {
    const ALLOWED_USERS = {
      'bob': '',
      'sally': 'gitIsCool7',
      'jerry': 'hackme123',
    };

    return ALLOWED_USERS[user] && ALLOWED_USERS[user] === password || 'Whateva'
  }
Enter fullscreen mode Exit fullscreen mode

And this translated to the initial a and b example becomes:

function example(key, value) {
  const CONFIG_LOOKUP = {
    'a': 10,
    'b': 20,
  };

  return CONFIG_LOOKUP[key] && CONFIG_LOOKUP[key] === value || 'Whateva';
}

Enter fullscreen mode Exit fullscreen mode
Thread Thread
coolprofessor profile image
coolprofessor

I see your point, but what if there is a property that is completely unrelated to the other variables? It would be pointless to do it for each one.

function signIn(user,password){
    if( user === 'bob'  && password === '' ){
         return true
    }else if(user === 'sally' && password === 'gitIsCool7#6' && itIsMorning){
         return true
    }else if(user === 'jerry' && password === 'hackme123' && SallyIsOffline){
         return true
    }
}

signIn('jerry','hackme123');
//will return ability to sign in (boolean)
Enter fullscreen mode Exit fullscreen mode
Thread Thread
davidlazic profile image
David Lazic • Edited on

With lookup maps approach you can drill down how much you wantt with minimal changes to the initial structure, so it would be something like this:

function isMorning () { ... }
function isSallyoffline () { ... }

function signIn(user, password) {
    const ALLOWED_USERS = {
      'bob': {
        pwd: '',
        isValid: () => true,
      },
      'sally': {
        pwd: 'gitIsCool7',
        isValid: () => isMorning,
      },
      'jerry': {
        pwd: 'hackme123',
        isValid: () => isSallyoffline,
      },
    };

    return ALLOWED_USERS[user] &&
           ALLOWED_USERS[user].pwd === password &&
           ALLOWED_USERS[user].isValid() ||
           'Whateva';
}
Enter fullscreen mode Exit fullscreen mode

Now you can go even further and have multiple validity checks for example:

function isMorning () { ... }
function isSallyoffline () { ... }

function signIn(user, password) {
    const ALLOWED_USERS = {
      'bob': {
        pwd: '',
        validation: [
          () => true,
        ],
      },
      'sally': {
        pwd: 'gitIsCool7',
        validation: [
          () => isMorning,
        ],
      },
      'jerry': {
        pwd: 'hackme123',
        validation: [
          () => isMorning,
          () => isSallyoffline,
        ],
      },
    };

    return ALLOWED_USERS[user] &&
               ALLOWED_USERS[user].pwd === password &&
               ALLOWED_USERS[user].validation.every(rule => rule()) ||
               'Whateva';
}
Enter fullscreen mode Exit fullscreen mode

And sorry for jumping in like so in the thread, I just know that plenty of people are for some reason struggling with this approach and I found this example intriguing. Also want to add that there is no practical way to completely avoid if/else statements, I use both approaches in my every day coding, it's just a matter of improving readability and removing code duplication.

If there's a simple 0 and 1 check, I see no reason to use a lookup map for that case, I'd just write down a simple if.

Thread Thread
rjitsu profile image
Rishav Jadon Author

This comment, and example is the best to explain the concept, thanks for this!

Thread Thread
naveennamani profile image
naveennamani

@davidlazic are you saying i should replace

a===10
Enter fullscreen mode Exit fullscreen mode


with

example('a', a)
Enter fullscreen mode Exit fullscreen mode


sure those are equivalent, but what above the functionality that i intended to run in the if condition, should I wrap them in anonymous functions and pass to another function. What about the else if condition? Should I call that like

if(example('b', b))

?
If all conditions has some common logic you can use mapping to bring the variability into the object and using the mapped values to execute the logic. But again, even if slight deviation is added (for example a console log in a single else if condition) then your common logic is not common anymore, and you have to add more hacks like anonymous functions as part of the mapping object and so on, as you just demonstrated in your example with validation functions.

The best practical example would be state management in redux, where switch case statements seems to be most efficient, readable and manageable, try implementing that with mapping.

Thread Thread
davidlazic profile image
David Lazic

Hey @naveennamani , appreciate the time you've taken to think about this. My comment was a reply, not a statement, where I simply described how a specific problem could be written in a different kind of way with an example. Like I wrote, I use if/else, switch and this kind of approach on every day basis, based on the situation. If a function is supplied with too much logic, there's probably something that's gonna go wrong and it could be split into separate pure parts.

Collapse
codemouse92 profile image
Jason C. McDonald • Edited on

It's okay to go looking for better solutions than just a chained if-else. On the other hand, many evils have been committed in pursuit of over-optimization, merely on the basis of the feeling that "real developers don't use if statements". Oh yes, we use them. Often. And liberally. And they work really, really well.

See also...

Collapse
bcowley1220 profile image
Brendan Cowley

You mean that developers have a tendency to overly-complicate simple problems by implementing 10 ton hammer solutions? Pshaw! Haha, for the rest of us "normies" simple, repeatable, digestible, straightforward solutions are always preferable to the "smart" solution.

Collapse
fjones profile image
FJones

Are we just going to skip over the fact that switch exists? Lookup maps have neat uses, sure, but declaring a best practice for something without mentioning the intended language construct for it is a bit silly.

Collapse
hsalem profile image
Hassan • Edited on

Good point, and thanks for sharing. But I think it only depends on the case you are working on. if/else can be easily abused as of any other tool. So I think we should really know our tools, and pick the right one for the job.

Thanks for sharing again, keep it up

Collapse
firozansari profile image
Firoz Ansari

You probably don't even need any else if you go with the bouncer design pattern.

function whoIsThis(character) {
    if (character.toLowerCase() === 'naruto') {
        return `Hokage`
    } 
    if (character.toLowerCase() === 'sasuke') {
        return `Konoha's Strongest Ninja`
    }    
    if (character.toLowerCase() === 'isshiki') {
        return `Otsutsuki being`
    } 
    if (character.toLowerCase() === 'boruto') {
        return `Naruto and Hinata's son`
    }
}
Enter fullscreen mode Exit fullscreen mode
Collapse
dikamilo profile image
dikamilo

I will still prefer switch here:

const whoIsThis = character => {
    switch(character.toLowerCase()) {
        case 'naruto':
            return `Hokage`
        case 'sasuke':
            return `Konoha's Strongest Ninja`
        case 'isshiki':
            return `Otsutsuki being`
        case 'isshborutoiki':
            return `Naruto and Hinata's son`
    }
}
Enter fullscreen mode Exit fullscreen mode

or object literals

const whoIsThis = character => ({
    'naruto': 'Hokage',
    'sasuke': 'Konoha\'s Strongest Ninja.',
    'isshiki': 'Otsutsuki being.',
    'isshborutoiki': 'Naruto and Hinata\'s son'
  })[character]
Enter fullscreen mode Exit fullscreen mode
Collapse
thecodingcrow profile image
thecodingcrow • Edited on

neat approach to improving readability (and apparently also efficiency), I like!

small suggestion from my point of view, you called the valid characters object listOfCharacters but I would rather go with validCharacters or sth similiar. Since the variable is technically not a list

Collapse
dominikbraun profile image
Dominik Braun • Edited on
  • Using an object doesn't mean that you're doing OOP.
  • else if and Map both work for your case, but they're not interchangeable in general - one is a control structure and the other one is a data structure.
  • else if is not inherently bad, it can be the most precise solution for some specific problems.
  • The only thing you should actually stop is posting articles talking about "absolute" truths.
Collapse
rjitsu profile image
Rishav Jadon Author
  • it's not just using an object, it's the context in which you use it, so there's no need to say this isn't OOP, yes I gave a small example but you can see there are examples in the comments supporting the idea.
  • of course they're not fully interchangeable but in certain cases they are.
  • No one said it's bad, it's just better to use other alternatives where everything is being repeated.
Collapse
michaelcurrin profile image
Michael

I suggest watching videos or looking at the blog of Uncle Bob, the Clean Coder. He also supports this view.

He suggests another solution - polymorphism. Not needed for a simple case of matching string results but if you had more complex logic it would be worth making classes which all implement the same method. And then you pass in a class instance to a function and it calls the method of the class - no need for if statement or keylookup.

It's possible too outside of classes - but probably requires type system from TypeScript and overloading function so you call a variation of a function depending what type you pass in.

Collapse
svasylenko profile image
Serhii Vasylenko

Despite the somewhere click-bait nature of the heading, I can’t help agreeing that a map sometimes looks like a better alternative for the “if/else” in terms of performance. Thanks for pointing on that!

Collapse
pachverb profile image
new/bird

good,jobs. This idea is very good. Dictionary way, okay. The usage scenario in this way is to switch between different branches according to the incoming value. At that time, if you don’t pass in a value, you need to switch to a different branch, how to do ?

Collapse
danielgomezrico profile image
Daniel Gomez

Can you share why would this be more readable/maintainable? I'm worried about you saying that this is "more readable and maintainable" without giving quality arguments about why that's true, that may let people believe that this is a must always.

I just went into a discussion about this topic, and some people argue that:

const condition = true

const value = {
   false: "first",
   true: "second
}[condition]
Enter fullscreen mode Exit fullscreen mode

Is better than a simple if like:

const value = condition? "first" : "second"
Enter fullscreen mode Exit fullscreen mode

This is an abuse/overuse of a language feature or structure which involves more concepts and more time on your brain in order to understand what is happening when you read it.

I also believe that this enlarge possible problems in devs minds like "Primitive types obsession" and "Declarative Dilussion", check:

WDYT?

Collapse
talr98 profile image
TalR98

I don't think replacing "if"/"else if"/"else" conditions with yours is the best.
There is reason we use these known conditions nowadays. It is easy to read. But you are right, it is not always easy to read. I would replace your so-called bad code (the first one of-course) with code which uses only "if" conditions. There is no need to use "else if" when the "if" ones would execute "return" statements.

Collapse
assunluis80 profile image
Luís Assunção • Edited on

Sorry, but I don't agree at least with your example. Why not a switch case?

Collapse
rjitsu profile image
Rishav Jadon Author

That would also be almost like if else.

Collapse
assunluis80 profile image
Luís Assunção

Almost how? Did you meseare the performance? Can you be more specific?

Collapse
planet_cbx profile image
Charlène Bonnardeaux

Thanks for the tips today at work I remember I’ve see your article and that’s save my code of a bunch of if/else. ;)

Collapse
rjitsu profile image
Rishav Jadon Author

I'm glad it helped, thank u :)

Collapse
ghvstcode profile image
Oluwatobi

Stop telling me what to do

Collapse
rjitsu profile image
Rishav Jadon Author

Stop telling me to stop telling you what to do.

Collapse
ghvstcode profile image
Oluwatobi

😂😂😂😂😂😂😂 This is a good one ! Nice article mate.

Collapse
jimstockwell profile image
Jim Stockwell

Your improved version really is a lot nicer. Thank you for sharing the lesson.

Collapse
rjitsu profile image
Rishav Jadon Author

Thanks a lot for reading!

Collapse
dannyengelman profile image
Danny Engelman

Interesting.. no one mentions the Minification proces, and how that optimizes your code.

Collapse
codenameone profile image
Shai Almog

The sample above doesn't need else since it returns... That's a pet peeve of mine...

Collapse
saroj8455 profile image
Saroj Padhan

Thank you

Collapse
bubster profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Info Comment hidden by post author - thread only accessible via permalink
TvO

There is a big difference between 'Stop using if/else' and 'abusing if/else'. Maybe you should do some more research.

Collapse
lehmannsystems profile image
Mike • Edited on

Yes this was clickbait :P

Collapse
piotrlewandowski profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Piotr Lewandowski

It's not clickbait, it's incoherent blabber made by inexperienced junior dev.
You can see it in the beginning of the second paragraph: "Most of us use if/else and switch statements whenever [..]" (who the hell is "us" and where does "most" comes from?)

Thread Thread
franciscomendes10866 profile image
Francisco Mendes • Edited on

"It's not clickbait, it's incoherent blabber made by inexperienced junior dev." @piotrlewandowski

All this for just one title...

In your bio you have "I specialize in building carefully crafted responsive and accessible projects". When your website only has a white background with blue text... On top of that your domain is .info when the information on the website is irrelevant.

Learn to give more respect to others, this is an amazing platform and I find it disrespectful to treat someone who is sharing their knowledge freely and voluntarily.

With all due respect to you for your opinion.

Thread Thread
rjitsu profile image
Rishav Jadon Author • Edited on

Thanks Francisco for saying that. I didn't want to give him any attention so it's nice someone actually said the right thing. I don't like to indulge in unnecessary arguments 😂

Thread Thread
piotrlewandowski profile image
Piotr Lewandowski

"I find it disrespectful to treat someone who is sharing their knowledge freely and voluntarily" - it's even more disrespectful when the knowledge you share is misleading and shows lack of experience. Just because you worked 3 months as a web dev and you have internet access doesn't mean you have to immediately start a blog. Plenty of bullshit articles here and everywhere in the net from people who has half of Todo tutorial as their experience. It's not just disrespectful, it's insulting. Insulting to those, who spend years and years on learning and gaining experience, and trying to share REAL and adequate knowledge. Maybe, just maybe, 3 months is not enough to pretend you know enough to teach other people, especially when you yourself still showing that you have a lot to learn. Because sharing no knowledge is better that sharing bad knowledge.

By the way: that "website which only has a white background with blue text" (at least I put some colours contrary to yours) pays my bills and help me live comfortable life (well, actually portfolio built over ~20 years which is available for clients upon asking), so, "with all due respect", but yeah, don't really care what YOU think about my dummy boilerplate personal website ;)

Thread Thread
rjitsu profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Rishav Jadon Author

Oh it's very disrespectful to you, is it?
Did my article hurt you? Why you so frustrated man? Considering your age, you should be playing with ur grandkids instead of commenting shitty things on some junior Dev's article. Now go back to doing whatever the hell u do n stop ruining my post.

Thread Thread
piotrlewandowski profile image
Piotr Lewandowski • Edited on

" stop ruining my post" - you ruined it yourself showing lack of understanding of what you write about (which is even more apparent in your replies to some of the comments". Accept criticism, learn from it, instead of pretending you know more than you do. Don't be example of Dunning–Kruger Effect diagram ;)
Also: if you don't like people criticising and commenting on your posts, there's an easy solution: don't publish ;)

Thread Thread
franciscomendes10866 profile image
Francisco Mendes

@piotrlewandowski
Seriously though, there are ways to be critical about something, however the approach you took (and obviously mine is not an example) I don't think it was the best.

But yes, I like to say "I'm just getting started" because no matter how much I know, every day I always end up learning new things.

rjitsu profile image
Rishav Jadon Author

"Lack of understanding". Learn English first @piotrlewandowski

Collapse
coolprofessor profile image
coolprofessor • Edited on

I agree with that statement. When people hear "Stop using if else", they think you mean this:

age = 27

if( age >= 18){
     alert("You are a legal adult!")
}
if( (age >=18) === false ){
     alert("You are not a legal adult")
}
Enter fullscreen mode Exit fullscreen mode

Although, I think that this article has a good point.

Collapse
dinhanhx profile image
Dinh Anh Vu

I agree with you. The title should be "stop abusing if/else" since the post merely show examples of overusing if/else statments.

Collapse
aguilera51284 profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Info Comment hidden by post author - thread only accessible via permalink
Arturo Aguilera

I am dissatisfied with this type of content :(

Collapse
rjitsu profile image
Info Comment hidden by post author - thread only accessible via permalink
Rishav Jadon Author

Bruh you can get satisfied with your hands for all I care

Some comments have been hidden by the post's author - find out more