DEV Community

loading...
Cover image for Write better code and be a better programmer by NEVER USING ELSE statements

Write better code and be a better programmer by NEVER USING ELSE statements

Douglas Parsons on November 10, 2020

I've been a professional programmer for the last several years. During this time I've risen rapidly through the ranks. I started as an intern, but ...
pic
Editor guide
Collapse
lonelymoon profile image
Hung Luong

I don't find the else worth targeting for the sake of readability. In fact, I welcome else as an explicit sign of "this or that" logic.

Guard clauses are fine. Nested conditionals are another problem entirely.But I don't think breaking a simple function with 3 parameters into at least a combinations of small function with a long chain of get by this and by that is anymore readable.

Collapse
drmdodd profile image
DrMDodd

It does however make you think about reusability and keeping consistency in code, in the getCharities example there, is something that could be reused elsewhere.

Collapse
lonelymoon profile image
Hung Luong

Sorry, but I don't see why reusability is relevant here - when it was suggested to create multiple 'versions' of getCharities with different combinations of parameters to avoid branching. One could even argue that it is the exact opposite of reusability: duplication.

Unless we have wildly different logic for getting by country or tier - in which case it isn't even about branching as they would be two different functions in the first place, what we would most likely have is this:

getCharitiesByCampaignAndCountry -> return getCharities(country, campaign, defaultTier)

Why make the reader jump an extra hoop just to get to the actual logic? And even if we were to force reusability on this, what is more reusable: getCharities or getCharitiesByCampaignAndCountry?

I know the example are meant to be simple, sometimes contrived, but this is precisely why I don't see why eliminating else helps in any way with readability.

Collapse
ani03sha profile image
Anirudh Sharma

@dglsparsons , excellent points. However, the code examples are a little difficult to read as all of the code is in the same line. Better readability can be achieved if it is something like below.

function doSomething() { 
    if (!something.OK()) { 
        // return or throw error 
    } 
   return something.Do()
}
Enter fullscreen mode Exit fullscreen mode
Collapse
dglsparsons profile image
Douglas Parsons Author

Hey - thanks for pointing this out. I'm not sure what's happened there.

I've fixed it now, so hopefully its much easier to read!

Collapse
graystrider profile image
GrayStrider

New line before return please :3

Collapse
entomy profile image
Patrick Kelly

While I agree with many of these points, and definitely find excessive cases of indentation in more novice-written code, this reads far more like "do as I say because I do it this way". You even start this with gloating that fits right with that motivation. Do you have studies on readability and how this change impacts that? While I suspect it does increase it, the wording of your article goes against your intentions.

Collapse
dglsparsons profile image
Douglas Parsons Author

Hi. Thanks for the feedback. That's not my intent at all, but I'm sorry it's come across that way. It's more intended to be - this is what works in my experience but I appreciate your perspective.

I'll bear this in mind in future :)

Collapse
entomy profile image
Patrick Kelly

I didn't think it was, hence saying I agree with your point. I just saw an easy way others can discredit your message and I don't think it's a message that should be discredited. I'm glad hostility didn't come through in text, because my intentions were only constructive.

Collapse
kant2002 profile image
Andrii Kurdiumov

You can look at how people talk when explaining something. I apply same technique and find it very useful. My motivation for this technique and some other comes from psychology and some linguistics. My coworkers whom I mentor think this is valuable technique, but maybe they do not know better. I cannot find studies regarding applicability of the technique in the real world even if I look for it deliberately. If you know what entity can do such kind of research I’m more then happy to start search again to prove or disprove statements of an article.

My anecdotal evidence is that code written in such way easier for novices to follow, since this kind of code can be easier to reading out loud and it would appear more natural.

Also there usually when express business logic there two kind of code intermixed, guards and shortcuts which require early exit to simplify logic and actual business logic where this rules less strictly applicable.

Why early exits and shortcut processing important? Try to remember how rare cases handled by business persons(can be engineers from other fields). Most people concentrate on core process and for other conditions usually throw simple shortcuts and suggestions which solve problem from their perspective. Such style of code just reflect how business people usually talk, just in slightly more formal way

Collapse
gnsp profile image
Ganesh Prasad

I have been avoiding else blocks for quite some time now. But I have never been able to clearly explain the 'why'. For some reason the code felt cleaner without the else blocks. This article explains the 'why' part beautifully.

Collapse
mcsee profile image
Maxi Contieri

Wow !

Nice article!

I think we should avoid ELSE and also IFS

I like the extract you made on your function. I don't know why you call them helper. Who are they helping ?

Thank you for your article

Collapse
dglsparsons profile image
Douglas Parsons Author

Hi, thanks for reading - I'm glad you enjoyed the article. I'll definitely give yours a read too :).

You're right about calling them helper functions - I think it's a kind of industry standard term (or at least it is here), for separating out pieces of logic into plain functions. As for who they help... I'm not sure either. Probably us developers :D

Collapse
mcsee profile image
Maxi Contieri

Yes. I'm aware of that

But I think we are wrong. Calling something a 'Helper' is a code smell of a real world entity we are too lazy to find.

Here are some reasons not to use that name.

Thread Thread
dglsparsons profile image
Douglas Parsons Author

Arguing with standards or convention is a difficult line to take though.
e.g. why are most keyboards in a QWERTY layout? - it's an outdated convention from when typewriters would jam, but that doesn't mean keyboard or laptop manufacturers should deviate.

I've not come across a different terminology for a helper function personally. Calling it just a function could suffice but doesn't make a succinct point. As long as it's widely understood, I think it's okay - coming up with a different term could just cause more confusion.

Thread Thread
mcsee profile image
Maxi Contieri • Edited

Agreed with the standard part

I'm not suggesting replacing Helper with another standard.
I'm suggesting to change every helper to an intention revealing name according to the domain

in your case I think charitiesByCampaignAndCountry(campaign, country) is a very good name related to domain. But it is not a helper :)

Thread Thread
dglsparsons profile image
Douglas Parsons Author

I'm absolutely agreed with the names of the functions. Although I'd argue that as a concept, the function is still a helper 😜 (insofar as it's separating out the logical act of getting charities from the specific invocation of it).

Collapse
chadj2 profile image
Chad Juliano

Congrats on publicizing this idea! I led integration teams for years and I tried to explain to them why nested if/else statements negatively impact the ability for other people to read and maintain code.

Code is always easier to deal with when its flow is kept as linear as possible and the happy path is clear. I think most people I spoke with never got this concept and it is good to see this.

Collapse
polomora profile image
Paul Moore

Interesting concepts about code readability, but I respfully agree.
I think that putting the else statement on its own line greatly improves the "line of sight" readability:
if( condition ) {
// statements
}
else {
// statements
}

Also, what about loops? They also break the same "line of sight" readability. What about switch statements? What about continue and break statements inside loops and switch statements? What about raising exceptions?

I think that helper functions also worsen the readability. For a programmer taking over or reviewing somebody else's code, helper functions definitely interupt the readability of the code.

Collapse
jcoelho profile image
José Coelho

Interesting point! I do try to avoid else statements but only to keep my code short.
I think the word NEVER is too strong, sometimes ‘else’ does help readability.

Inverting the if statements is a good technique but most of the time it hurts readability, you need to pause and adjust your thought to the negative statement.

Anyways good article, great spark for discussion

Collapse
rhyous profile image
Jared A Barneck

I kicked 'else' to the curb over ten years ago. Best thing I ever did. As a dev lead, I teach those I mentor that it is similar to 'goto' and just doesn't have a place in modern object-oriented languages (C#, Java, python, typescript, javascript). I tried for a long time to use find a valid use of 'else' and 'goto' and every time I thought I had one, I realized there was a better way. Using either is always a code smell.

The author missed discussing one of the best reasons for not having an 'else' statement. Cyclomatic Complexity decreases. Give Cyclomatic Complexity a google or bing search and read up on it. Using 'else' always increases cyclomatic complexity and always makes unit testing and code coverage harder to obtain.

Collapse
psanchez1982 profile image
Patricio Sanchez Alvial

So your problem is identation?

if(condition){
...
}
else{ // you can put else here
...
}

Collapse
dglsparsons profile image
Douglas Parsons Author

Hey. Thanks for taking the time to read the article and sharing your thoughts.

My issue isn't with the indentation of the else keyword, but more that the happy-path code, and error-handling code are both indented within the if {} else {} statement - it makes them harder to distinguish from a quick scan.

Collapse
hasii2011 profile image
Humberto A Sanchez II

I am not sure I would recommend this technique when it creates negative logic.

Collapse
dglsparsons profile image
Douglas Parsons Author

How do you mean 'negative logic' ?

Collapse
hasii2011 profile image
Humberto A Sanchez II

The code showed this:

function doSomething() {
if (something.OK()) {
return something.Do()
}
}

It was changed to:

function doSomething() {
if (!something.OK()) {
// return or throw error
}
return something.Do()
}

My experience has been that using a "not" in front of a conditional requires a mental adjustment to process the "negative" condition. I think I also read this on many books that talk about "code smells"

Thread Thread
dglsparsons profile image
Douglas Parsons Author

I think it depends on the properties/methods you have. I agree with your point that putting 'not' in front of a conditional can require a mental adjustment, but that's usually when you're properties are negative or poorly named.

For example - if I had a something.notOK() method, I wouldn't want to negate this - as !something.notOK() doesn't read very nicely.

That's an extreme example, but it's why naming is super important (especially for booleans).

Another example could be flagging users as inactive - the logical thing to do is to add a boolean property isInactive. This isn't as obviously terrible, but inverting this can be confusing - not isInactive... so active.

I'd argue the code smell there is the names / properties, rather than inverting the if / else statements though.

Great point though <3

Collapse
sctgcs profile image
Simon Tillson

He means inverted logic, not negative logic. In boolean terms, they're equivalent.

Collapse
linaran profile image
Deni

Imagine someone rejecting a PR over an else statement.

Collapse
sctgcs profile image
Simon Tillson • Edited

I'm sorry, but this is wrong, and I'm not going to be kind about it.

I remember years ago when people started saying 'never use goto in C'.
The real reason for that was the provability of source code. With GOTOs littered all over, it's impossible to prove the output of a program. Without them, it is possible.
For safety-critical software, like flight controllers and medical devices, that's damned important.

Is this the reason people gave when shouting at the top of their lungs 'if anyone in this team uses GOTO, they're out the door!' ? No. It is not.

At the time, coders put up all sorts of other arguments about style, readability, maintainability and even occasionally, simple personal preference. These are all fair reasons, and there was never any justification for littering code with GOTOs, especially conditional ones! In many systems, it was even essential to use GOTO in some places. But I digress...

Your argument for avoiding ELSE is hollow. Source code style and layout is not hindered by ELSE at all. If used correctly, with decent coding style, it looks rather nice and obvious. Avoiding it often makes functions longer or hides their logic, when a clearly stated ELSE case is very straightforward. Of course we don't want 10 levels of indented IF..ELSE..IF.. but that's obvious, isn't it? No reason to ban the ELSE word.

In the real world, we've got more important things to concentrate on, and I don't think you will find the ELSE statement disappearing from any language anytime soon!

If anyone wants to try writing all their code without ELSE, go for it.
Just don't make a religion out of it, ok?

Collapse
jhelberg profile image
Joost Helberg

Hear, hear! Great post and certainly something to follow up on. Good ro cite Knuth also, literate programming needs more support as well.

Collapse
oleksiirybin profile image
oleksii-rybin

Usually, when I read the code, I don't read it like a book - all the lines one after another, instead, I read it following the logic path I'm currently interested in, from one logical block to another logical block, and it doesn't matter whether it's a "happy path" or not (it's up to me to decide, depending on the task at hand). So, reading through if/else statements don't create any issues for me, I just look at the condition and immediately proceed to "if" or "else" body. But what frustrates me - is complex "if" conditions and early returns. They both make it more difficult to only read through the code you need while skipping through the parts which are irrelevant to your current goal. First, I have to use the extra time to process the "inverted condition" and then go through the whole function making sure there are no early returns that will unexpectedly interrupt the flow I'm currently interested in, so as a result - I have to read much more lines (basically, all of them) and put more effort to get through the code.

Long story short: I'm not convinced. I still think using if/else statements and a single return at the end of a function is better for readability and stability of the code. Besides, if you're still lacking the context, I assume, any modern IDE lets you just click on the closing parentheses of any statement to quickly remind you what was the "if" statement at the beginning of it.

Collapse
2xw profile image
Wim Wouters

I was not aware of it until I read your article: I use all the techniques you bring forward. So I have no other option than to agree 100% with your point of view on ELSE :)
To me it feels natural to invert the IF statements and exit early for example.

Collapse
jwp profile image
John Peters

And in 2005 this article affirmed what you are saying using the Visitor pattern.

Collapse
dglsparsons profile image
Douglas Parsons Author

Hey, that's an interesting article. Thanks for sharing that.

Personally, I'm not convinced inheritance (and arguably over-abstraction) provides more readable code - but there is definitely something to be said for reframing the problem to remove any special cases.

Collapse
brandiware profile image
brandiware

OK folks. Readability IS a sign of code quality - for sure. HOWEVER, that does not mean it is necessary to drop useful elements of any language. You can't assert "never use a knive!" simply because misuse of knives is dangerous and can be BLOODY.
It is interesting to note, how little the examples in this post are commented !

ALTERNATIVELY, consider focussing on more and proper commenting:

// Process the passed argument, ... the result of the ... calculation ... , ... if it is useful
if myVariable != nil {
//DoSomeUsefulStuff()
}

Now judge by yourself how well the else part reads if commented (of course with some context of the preceeding IF logic)

// Drop out of the function / procedure if the passed argument, ... the result of the ... calculation ... , ... is NOT useful
} else {
return “”
}

My personal summary on code readability: Do comment;

Collapse
v613 profile image
Ceban Dumitru

I'm not agree with you.
Same weak argument can be applied to a lot of clause.

Collapse
dglsparsons profile image
Douglas Parsons Author

Hey, thanks for reading. Is there some area, in particular, where you feel my argument falls short? I'm struggling to think of other places you could apply the same argument.

Collapse
rivantsov profile image
Roman Ivantsov

the quote - is not by D.Knuth, it is Abelman & Sussman, SICP, preface. look it up

Collapse
lofibytes profile image
Jillian S. Estrella (she/her)

I fully agree.

This is part of our style guide; which all of our devs are expected to adhere to.

Collapse
dezfowler profile image
Derek Fowler

Completely agree with this. I also prefer to write code this way and always suggest it to others as I find it produces a far simpler and more readable result.

Collapse
stcinematicapp profile image
Studio Cinematic

Oh wow, I can't believe what people write when they're bored.

Else is a very logical construct, borrowed from real life: "If they have eggs, buy 10. Otherwise, buy some extra tomatoes". This is a perfectly viable sentence, and it's extremely easy to read.

What you end up suggesting is "don't write code that would flow logically, just invert whatever, so that you avoid using else".

I have no idea what crappy code you've had to deal with, but this advice you give is horrendous.

Collapse
dglsparsons profile image
Douglas Parsons Author

Else being borrowed from real life is an interesting point - remember that the language we use every day is often incredibly ambiguous and driven hugely by context.

My wife said: "Please go to the store and buy a carton of milk and if they have eggs, get six." I came back with 6 cartons of milk She said, "why in the hell did you buy six cartons of milk"

"They had eggs"

The rules we follow in programming aren't the same as in natural language too.

When programming, you often have to deal with vastly complex systems (compared to a very simple sentence). As a result, I'd argue removing as much ambiguity, and as much context as possible helps readability massively.

Collapse
stcinematicapp profile image
Studio Cinematic

Look, I really get what you're trying to do/say (and I was aware of the joke) but it's simply not true. In fact, to me, this yells "I really don't have enough experience, and yeah I've written some code, so here's what I think".

I've been programming for 23 years, and "else" is a very useful construct. In fact, it's more than a "must".

Thread Thread
f6adt profile image
f6ADt • Edited

if/else:

function foo1(value: string | undefined) {
    if (!value) {
        // ... multiline processing ...
        throw Error()
    } else {
        ...
    }
}
Enter fullscreen mode Exit fullscreen mode

if with short-circuit:

function foo2(value: string | undefined) {
    if (!value) {
        // ... multiline processing ...
        throw Error()
    }
    ... happy path
}
Enter fullscreen mode Exit fullscreen mode

In what way is the first alternative a "must"? These snippets use TypeScript as an example - the compiler will even narrow value to string in the line after the if statement for you, leveraging control flow analysis (2nd snippet). Happy path stands out without further indention, arguably more readable. You might even count the used characters to be objective.

Thread Thread
stcinematicapp profile image
Studio Cinematic

By "must", I meant something a language should have, not that you need to use it all the time.
If after years of programming you don't see the value of "else", you may want to advance to management.

Thread Thread
dglsparsons profile image
Douglas Parsons Author

So, to answer your own question... why 'should' a language have an 'else' statement? What's the use case that makes it mandatory?

Thread Thread
stcinematicapp profile image
Studio Cinematic

Seriously, you really need to advance to management.

Thread Thread
f6adt profile image
f6ADt • Edited

Well, else is just one tool in the kit - whatever fits readability best. I personally don't exclude native language features categorically.

Expression-based functional programming languages only know if/else as ternary operator. In statement-containing languages as JavaScript, this article has a good point. Replacing else by short-circuits can improve readability in surprisingly many cases.

Instead of blowing out hot air ala "I can't believe what people write when they're bored.", "this advice you give is horrendous.", "this yells "I really don't have enough experience'" or the good old "I've been programming for <insert number here> years", I would recommend a bit more open-mindness.

Thread Thread
stcinematicapp profile image
Studio Cinematic

About "else" is just one tool in the kit - I wholeheartedly agree. I never said "always use the 'else' construct". However, to understand my grievance with this article, please look at the title.

Thread Thread
bernardwiesner profile image
Bernard Wiesner

Things you say like "I have been programming for 23 years" does not give you more credibility. Some people stay stuck and just do the same old thing without advancing, even for decades.

I agree 'else' has some use cases, but it makes your code much easier to read after you get used to not using 'else'. It also helps dealing with complex logic and reasoning about it, not having to deal with multi level nesting.

You should give it a shot after 23 years and try to stop using else. If after a week you still really dont like it you can always go back.

Thread Thread
stcinematicapp profile image
Studio Cinematic

You simply don't get it - saying "else" has some use cases - where do you people come up with this stuff. You really think I'm gonna give up using "else" based on someone's opinion? No thanks. I simply go with "else is a tool in the programmer's box, I use it when it makes sense". I don't deal in absolutes.

But yeah, feel free to stop using else, and then maybe after 5 years, re-read your code AND try to maintain it. Then we'll talk.

Collapse
kant2002 profile image
Andrii Kurdiumov

To answer question which you ask Cinematic.

So, to answer your own question... why 'should' a language have an 'else' statement? What's the use case that makes it mandatory?
Enter fullscreen mode Exit fullscreen mode

You most likely need else to express computations which has 2 and only 2 options. These should be probably small computations hidden in their own function.

These situations very often arise when you express business rules for example. And written in if/else fashion these business rules can be discussed with business persons without to teaching them new abstractions.

Collapse
parkerproject profile image
Parker

I second to that!

Collapse
opwernby profile image
Dan Sutton

This is such nonsense. Your examples are fine, because they're frighteningly simple - but even they break every rule of programming. If you want a function to be readable - and, more importantly, easy to debug, have only ONE point of return in it. Having return statements all over the place, with no Else, is ridiculous once you get past rudimentary levels of complexity. Go and read some Dijkstra.

Collapse
ifieldhouse profile image
Ian Fieldhouse

"have only one point of return in it" is terrible advice. A great counterexample are guard clauses: they remove indentation and make code cleaner, making the flow of code easier to follow. Forcing you to have 1 return statement per function wil inevitable make your functions bloated.
If you are talking about the Dijkstra's Single Exit principle, then you are mostly misinterpreting him on a problem that doesn't exist anymore: when functions could return to multiple different places.

Collapse
opwernby profile image
Dan Sutton

Never mind: it's not as terrible as "don't use 'else' statements".

Collapse
moopet profile image
Ben Sinclair

That's not a particularly constructive reply.

The point of the article is sound - try not to have branching paths inside a function. Perhaps a better solution in a language that supports it it to use guard clauses that throw exceptions if they don't follow the golden path rather than returning some kind of error state. But that's not always possible depending what you're coding in.

Collapse
opwernby profile image
Dan Sutton

No it isn't. This is the sort of thing programmers with a few years' experience think is clever, but it's not: it's just another way of swimming while hog-tied and then saying, "Look what I can do". I mean - come on: do you really think throwing exceptions and returning error states is more readable than using "else"?

Thread Thread
moopet profile image
Ben Sinclair

It depends, but oftentimes yes, because an "else" is a sign that your function is doing more than one thing, and a lot of people's programming philosophy revolves around making functions only do one thing.

Thread Thread
opwernby profile image
Dan Sutton

I know - again: good for really simplistic stuff, but in the real world, if you make every function do only one thing, you have to have so many of them that your code becomes spaghetti. Besides, avoiding an else in one function simply means you have to move it to another, or use a case instead, which is a bunch of glorified else statements: if the program needs to decide a thing, it's going to need to decide it somewhere.