DEV Community

Ditching the "else" Statement

Michael Kovacevich on October 16, 2021

Are "else" statements really necessary? When first learning to program we are taught about "if" statements and "else" statements. If this condition...
Collapse
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ

Interestingly, when I was briefly on a Computer Science degree (that turned out to be a waste of time) - we were taught that early returns / guard clauses were considered very poor style, and that every function should have only one return statement

Collapse
 
eljayadobe profile image
Eljay-Adobe

That's one of the commandments from the structured programming era of programming. Apparently some professors are still living in that era.

Collapse
 
aminmansuri profile image
hidden_dude

Well it's interesting to explore WHY they stressed this.

In the Assembly language world having jumps all over the place was a real problem. In the grand scheme of evolution this was an important principle.

Of course higher level languages made this point moot (in my opinion). And in fact, returning early often saves you from having to deal with flags which are really a horrible programming style.

Collapse
 
jonrandy profile image
Jon Randy ๐ŸŽ–๏ธ

When I had that class would have been around '95

Thread Thread
 
eljayadobe profile image
Eljay-Adobe

That'd be about right. 1950s structured programming approaches, which were refined and formalized in the 1960s, being taught in 1995.

There are languages, like COBOL, where the language itself doesn't allow you to violate the one return statement. Fortunately, JavaScript is not COBOL.

Collapse
 
mkovace profile image
Michael Kovacevich

I have a CS degree and I was taught that as well...unfortunately most CS professors don't have much recent industry experience.

Returning early can be very dangerous if you aren't keeping your functions small. If your functions are more than 10-20 lines of code, I'd avoid multiple returns because you'll create a bug factory.

Collapse
 
jimstockwell profile image
Jim Stockwell

Yes, well said: when itโ€™s dangerous and when itโ€™s not.

Collapse
 
assunluis80 profile image
Luรญs Assunรงรฃo • Edited

Exactly! When I was a CS student, I remember the teachers stressing out about multiple return statements... It completely changes the internal organization of compilers.

Beside of that, I would write the first example as just:

return (value1 === value2); ๐Ÿ˜Ž

Collapse
 
mkovace profile image
Michael Kovacevich

Yea I pointed out that the function itself is useless, but it serves as a simple example.

As far as it's effects on the compiler, I'd say it very much depends on the language and the use case. Also in my 7 years in industry I've never had to take a minor compiler optimization like that into consideration.

Collapse
 
haaxor1689 profile image
Maroลก Beลฅko • Edited

I feel like you did not provide complex enough example to show of what a huge difference in code readability can early return make.

Let's say we have some complicated fetch that needs to first get some ticket and then use it in a 2nd request.

const fetchData = async (id?: string) => {
  if (id) {
    const ticketResponse = await fetch('api/ticket');
    if (ticketResponse.ok) {
      const response = await fetch (`api/data?t=${await ticketResponse.text()}`);
     if (response.ok) {
       return await response.json();
     } else {
       return 'Response fetch error';
     }
    } else {
      return 'Ticket fetch error';
    }
  } else {
    return 'No id';
  }
}
Enter fullscreen mode Exit fullscreen mode

Now this is a horrible code to read because for every if you need to look for corresponding else and you need to constantly jump between lines when trying to understand the code.

Why early return is so good is because with it, every time an error occurs that should end the function in earlier step, you can return from the function and not think about that branch of execution after.

const fetchData = async (id?: string) => {
  if (!id) {
    return 'No id';
  }

  const ticketResponse = await fetch('api/ticket');
  if (!ticketResponse.ok) {
    return 'Response fetch error';
  }

  const response = await fetch (`api/data?t=${await ticketResponse.text()}``);
  if (!response.ok)  {
    return 'Ticket fetch error';
  }

  return await response.json();
}
Enter fullscreen mode Exit fullscreen mode

And this is the main reason for early return.

  • No unnecessary indentation
  • When reading, you don't need to jump between lines to find the other execution branch
  • Any errors/cases that causes function to not execute all steps returns and you don't need to think about that case after that since it's handled
Collapse
 
peerreynders profile image
peerreynders

A ternary is essentially an "if/else" statement with less syntax, so we didn't really ditch the "else" statement!

Strictly speaking the conditional operator is an expression, not a statement like ifโ€ฆelse. Given that it's an expression it has to return a value which is why the "else" expression is mandatory. So in this case "else" is a feature not a defect because it forces you to deal with either outcome explicitly โ€” similar to exhaustiveness checking in TypeScript's discriminated unions.

  • (if) statements (with or without else) are the hallmark of Place-Oriented Programming
  • (conditional) expressions are part of Value-Oriented Programming.

In Value-Oriented Programming you always have to deal with "else" even if it's undefined.

Collapse
 
phlash profile image
Phil Ashby

I found a decent thread on stack exchange where single entry, single exit (SESE) is discussed, the top answer provides a nice history lesson (it was assembly & FORTRAN that required the statement on SESE from Dijkstra as these allow a function to have multiple entry points, and to return to different locations - gotos everywhere!), the follow on answer brings us up to date with issues around resource management in non-garbage collected languages (eg: C/C++ although there are techniques to fix this such as guard objects in C++).

softwareengineering.stackexchange....

Collapse
 
stiby profile image
stiby

The article is an example of the action of refactoring, I'd recommend reading Martin Fowlers Refactoring book which talks about the more advanced patterns you're starting to find which can't be automated.

When working as a team having well understood practices and principles like design patterns and refactoring patterns aids conversation, especially when reviewing code.

Collapse
 
mkovace profile image
Michael Kovacevich

Very familiar with Fowler and other authors in this space, good recommendation. Wanted to keep this article simple and accessible. Thinking I might dig a little deeper into my knowledge and experience next time.