Hi everyone! I just want your opinions/thoughts on how to use if-else statements to make it more readable and maintainable or what are the best practices on using if-else statements. So let's start!
First
Nested if statements
if(!isEmpty(object))
{
if(IsString(object.number))
log("Is a String");
else if(IsNumber(object.number))
log("Is a number");
else
log("Is a special character");
}
or you can have it like this:
var bool = !isEmpty(object);
if(bool && IsString(object.number))
{
log("Is a String");
}
else if(bool && IsNumber(object.number))
{
log("Is a number");
}
else if(bool)
{
log("Is a special character");
}
Which do you think is better? Which one is easy to maintain and read? And what will happen if these IF statements get bigger?
Second
Ternary operator vs if-else-if statements
var tempVar = 0;
if(number == 1)
tempVar = 1;
else if(number == 2)
tempvar = 2;
else
tempvar = 3;
or this one
var tempVar = ((number == 1)? 1: (number == 2)? 2:3);
Which one is better if we are talking about maintainability?
Top comments (8)
I personally would use the ternary operator over an if statement when I had a structure like this
in which the equivalent to condition, firstExpression and secondExpression are rather simplistic expressions, e.g. constants, already calculated values or the evaluation of a function which is free from any side effects.
If I cannot refactor all of those expressions in a readable manner so that the resulting one-liner
does not exceed a certain column width, I would go for the if statement.
Also, if I would advise to abstain from nesting a ternary statement into one or both of the expressions. Even if hidden within a function, I would prefer to have the flow of control visible.
When there is really complex logic, it does not go away by obscurity.
Also, it would not be the first time, that I encountered, in which a lots of complex boolean logic is actually a simple polymorphic dispatch trying to come out of hiding.
For the first one, I would write it like this (if
return
ing was an option)If you stated having more than just the check for a string and a number, I would change this a
switch
statement (leave the firstif
that checks if it's empty, and make the rest a switch)For the second one, I would use a
switch
statement.My thoughts line up with this, for the most part.
"...and what will happen if these IF statements get bigger?"
One of the best pieces of feedback I got early in my career was to extract boolean expressions into functions when they become too large (typically more than one || or &&)
So if i started with:
I'd just snatch that whole boolean expression and extract it into something like:
This way the if statement is easily human readable.
In the first instance you read "If the object is empty, and the objects' value is a number and the objects' value is greater than one, then..."
In the second instance you read "If the object value is a number that's greater than one, then..."
Yeah. Boolean functions are great. It makes your code more readable and usable. And also it removes duplicates.
To First: Definetly the first one, because think about this case:
You could easily miss that bool isn't relevant in the first else-if statement.
To second: I would only take the ternary operator if it's just an replacement for a single if-else. I find nested ternary operators really hard to read and understand.
Oh sorry. The second if should have a bool condition.
That missing
bool
is exactly the reason to use a short-circuit return at the top (like in Nathan's note above), or just leaving the enclosingif
statement as it is in your original code.You hit the nail on the head when you asked about what happens when these
if
statements get bigger.That growth happens in stages. First, you generally do what Leighton suggests, and refactor the boolean checks into separate functions. At some point that starts to get unwieldy, and you refactor the chain of if/if-else statements into a chain of objects. (See the Chain of Responsibility pattern)
Judging when to do that refactoring comes with time and experience. I personally do it before the current arrangement is causing trouble. (I tend to be an "ounce of prevention" kind of guy.) Two things make that refactoring much easier:
Here's an example of how I might refactor your above
if/else
chain into something like the Chain of Responsibility pattern:That code is horrific overkill for the statement you started with. But I hope it illustrates the pattern, and gives you some idea of how the code can be refactored as it grows and becomes more complex.
I go with ternary operator when ever i can