DEV Community

Adam McGurk
Adam McGurk

Posted on

Why I'm phasing out ternary statements

I'm in a little bit of a bind. Very early on in my software development career, I learned about these things called ternary statements, and I thought they were the coolest thing ever. I started using them everywhere...but now, I'm just having different thoughts. Let's take a step back for a minute though.

What are ternary statements?

Ternary statements are (put simply) shortcut if statements that look like this:

const val = "test";
const showTest = val == "test" ? "The value was a test value" : "The value was not a test value";
Enter fullscreen mode Exit fullscreen mode

(Go to this MDN article to learn more about ternary operators: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator)

Spoken in plain english that code is translated to:
IF val is equal to the value of "test"
THEN set the variable showTest to the value of "The value was a test value"
ELSE set the variable showTest to the value of "The value was not a test value"

What's the alternative??

To me, early on in my career, this seemed like an absolute godsend. The alternative code looks like this:

const val = "test";
let showTest;
if (val == "test") {
    showTest = "The value was a test value";
} else {
    showTest = "The value was not a test value";
}
Enter fullscreen mode Exit fullscreen mode

And if you hated more lines of code like I did early on, this seems like a no brainer. A two line solution verses a seven line solution is really no question.

So what's the problem?

Remember how in the beginning I referenced that I was in a bind...well here's the bind.

In the application that I have built (and now work on maintaining for the company that I work for) I used ternary statements EVERYWHERE. I used it for absolutely everything that I could. Less lines of code, right? Well I've realized that the only thing that cares about lines of code in your app is this website right here:

https://linesofcode.app

And besides that, going after less lines of code isn't always the best. In fact, I run into two problems now going back to the application and trying to refactor the ternary statements a little bit.

  • The mental overhead it takes to make a change in the logic.

Ternary operators only support one action for each block of the if. So in the code above, maybe all I wanted to do in the beginning was set the showTest variable to a string...but what if now I also want to fire off a function if val does equal test? I have to go back, remember what it was doing, try and remember why I thought there would be no other actions necessary, and then refactor it to look like the second example I've posted up anyways.

  • The distinct lack of code readability

Code like this that does so much in so few lines of code really loses it's luster when it comes to readability. It may scan better, but it also does provide a mental block when it comes to readability that the other example does not.

So what?

All in all, I will probably still use ternary operators...even after everything I said. Why? Because there is definitely a time and a place for them, just like with everything. What we have learned here where I work though, is that time and place isn't littered through the codebase, just trying to cut a 127 line file down to a 122 line file.

What are your thoughts on ternary operators?

Top comments (39)

Collapse
 
riccardomessineo profile image
Riccardo Messineo

I actually think they are very useful to make your code concise and easier to read.
The problems arise if you abuse of them - as always.

Ternaries (imho of course) should be used only to assign values

a = (b == c) ? 'ok' : 'ko'

Avoid:

  • ternaries in ternaries
  • logic in ternaries
a ? b : (c ? d : f)
a ? doThis() : doThat()
Collapse
 
mcgurkadam profile image
Adam McGurk

I definitely agree that we need to avoid ternaries in ternaries (I've seen that in wild....just why????) and also logic in ternaries...

And I agree that the time to use them is when we're assigning value...and only then. And there is definitely a time and a place for them!

Thanks for reading!!!

Collapse
 
riccardomessineo profile image
Riccardo Messineo

Thank you for sharing!

I really appreciate that readability is becoming more important than having a fewer lines of code, as you suggested.

We need to understand that we are mainly readers of code, and only then writers.

Thread Thread
 
mcgurkadam profile image
Adam McGurk

Totally agree!!! We are definitely readers first, creators second, writers third.

Collapse
 
rsuttles58 profile image
Rob Suttles

Just one other consideration in this discussion might be performance. Are ternaries anymore or any less performant than standard if/else statements? I'm asking this as a junior that does not know the answer. ha

Collapse
 
mcgurkadam profile image
Adam McGurk

That's a great question, and a really important one to be asking in the context of refactoring!

I spun up a quick perf test:
jsperf.com/testing-ternary-for-dev...

And it looks like the results are negligible. The first time I ran it, the ternary was faster, the second time I ran it the non ternary was faster.

Feel free to run it yourself!!

Thanks for reading!

Collapse
 
riccardomessineo profile image
Riccardo Messineo

If your Junior, I would suggest you to focus on readability. Above all.
We live in "Giga" times where in 99% of contexts it doesn't matter if you use a byte more or less (or a digest cycle, or a MB in RAM, or whatever).
For sake of clarity, I'm not saying to waste resources, but in general give more importance to readability (fewer bugs, quicker refactoring, more code reusability, and so on...).

To satisfy your genuine curiosity... this sort of instructions are both written in "high level" code that somehow will be translated in "low level" code.
I think (not sure) that they'll be translated in the same low-level instructions and have the same performances.

Collapse
 
mcgurkadam profile image
Adam McGurk

Yeah, the perf test I showed up top showed not much of a difference between the two!

Collapse
 
joeattardi profile image
Joe Attardi

That sounds like premature optimization IMHO, in the vast majority of cases it probably doesn't matter in terms of human perceived performance. I say probably because there's always an exception to every rule :)

Collapse
 
mcgurkadam profile image
Adam McGurk

Yeah that's probably true, this block of code is probably too small to make any perf change have a non-negligible impact.

Great insight and thanks for reading!

Thread Thread
 
fennecdjay profile image
JΓ©rΓ©mie Astor

Maybe (probably) I'm wrong, but this would impact performance if it was called a HUGE number of times?


Yet I think in this case, for C at least, this would compile to the same assembly.

Thread Thread
 
joeattardi profile image
Joe Attardi

I mentioned "premature" optimization. If this was called a huge number of times, and it did impact performance, then it would be time to optimize. But I would be willing to bet that for most use cases, it doesn't really matter.

Collapse
 
holywar20 profile image
Bryan Winter • Edited

I have a controversial opinion on this ... I'm not sure this is something worth really considering in 99.9% of use cases.

This can easily lead one to premature optimization. Most code executes rarely, and consumes fractions of a fraction of resources. Optimizing a millionth of a second benefit on code that executes say once per session is probably not a good use of your cognitive resources.

In fact, I'd argue that even if IF or Tenary was 100x more efficient than the other ( and it doesn't appear to be ), that it's generally bad to write code 'optimally performant' code.

Optimal performance can easily be done by building applications entirely in assembly and without using frameworks or high level languages at all. But the reason we write almost nothing in assembly is because the biggest barrier to getting a functioning application is the human writing it. Generally if a coder is writing an IF statement, your doing a high-level check, which compared to all the billions of things a computer does a second, isn't all that much time, and you would need to write a billion lines of code to get a few seconds of extra performance across all your applications built over your lifetime.

Optimize for readability first - add performance improvements later after you have had a chance to actually profile the code and figure out where your bottlenecks are.

Collapse
 
sargalias profile image
Spyros Argalias

Personally I wouldn't use if / else statements for assignment. At least not very often:

  • If we are assigning multiple things inside the if / else statement, then we may lose track of one of them. It's less clear what's going on at first glance.
  • The declaration can be moved much further away, making things less clear.
  • We cannot use const, which gives us a guarantee of immutability (relatively speaking).

Having said that, I don't really remember having to conditionally assign multiple things...

However if I felt it was best, I would definitely replace ternary statements with if / else statements in other cases. Code readability and maintainability are extremely important. If you and your team believe that using if / else statements is best for that, then that's a very important consideration.

Collapse
 
anssip profile image
Anssi Piirainen

Completely agree with this. I always use const and resort to a mutable variable only if I cannot find a way around it. Variables that can be mutated add mental load and make the program harder to follow.

Collapse
 
mcgurkadam profile image
Adam McGurk

That’s definitely fair!!

Thanks for reading!

Collapse
 
mcgurkadam profile image
Adam McGurk

I definitely agree with you, I love using const, and if/elses take it away!

Thanks for reading!!

Collapse
 
pinotattari profile image
Riccardo Bernardini • Edited

Usually in this kind of things I have a pragmatic, almost obvious, approach: ternary operator is a tool that has its pros and cons, it has contexts where it is useful and contexts where you can use it, but it is quite a stretch...

It is true, however, that C-style ternary operator lacks somehow readability.

In Ada we have a kind of ternary operator too, but its syntax is (IMHO) much more readable

   X := (if Test then Value_True else Value_False);

We have case too (switch for you C people)

Hours := (case D is
               when Mon .. Thurs => 8,
               when Fri => 6,
               when Sat | Sun => 0);

The (...) around the if and the case are mandatory.

I find it useful in simple contexts where a classical if ... then ... else would look redundant. It is fundamental in defining inline functions (I think it was the reason for introducing it)

  function Modulus(x : float) return Float
  is (if X >= 0.0 then X else -X);

and also in some pre/post condition. Suppose you have a function Foo that returns 0.0 when its argument is negative and a value larger than the input otherwise. You can write

  function Foo(X :Float) return Float
  with Post => (if X <0 then Foo'Result = 0.0 else Foo'Result > X);

Also the implication A => B is nicely expressed with the ternary

   (if A then B)
Collapse
 
mcgurkadam profile image
Adam McGurk

I definitely agree that there is a time and a place for everything! I’ll still use ternary operators, just not as frequently!!

Thanks for the in depth breakdown, and thanks for reading!!!

Collapse
 
scrabill profile image
Shannon Crabill

Ternary operators were amazing when I first learned about them.

I agree that there is a time and place for them. For a simple concept (someone mentioned assigning values or triggering a this or that scenario) they are great. But, beyond a short line of code, they do get messy and hard to read, even if its less code.

Is it really better code if is take my slow, human brain more time to figure it out before I can make changes?

Collapse
 
mcgurkadam profile image
Adam McGurk

I totally think that no, if my brain has to think too much to make a change, I did something wrong!!

And that’s what I’ve been running into a lot lately, decisions I’ve made to have less lines, or to do something faster, I’m definitely regretting

Collapse
 
scrabill profile image
Shannon Crabill

Too much thinking is also why I avoid using while loops. πŸ€·πŸ½β€β™€οΈ

Thread Thread
 
mcgurkadam profile image
Adam McGurk • Edited

Yes!!!

I think I’ve only written like 5 while loops in my whole career!!

Thanks so much for reading!!

Thread Thread
 
scrabill profile image
Shannon Crabill

I've yet to use one outside of practice assignments that say to use a while loop.

if/else or for loops for the win. I'll use a simple ternary, as a treat.

Thread Thread
 
mcgurkadam profile image
Adam McGurk

Foreach is what I always try and reach for (no pun intended)πŸ˜†πŸ˜†

Collapse
 
fennecdjay profile image
JΓ©rΓ©mie Astor

I think we forgot the use for return statement:

//! return i or 0 if i is negative
static inline int full_rect(int i) {
  return i > 0 ? i : 0;
}

Also, since c99, one can write:

//! return i or 0 if i is negative
static inline int full_rect(int i) {
  return i > 0 ?: 0;
}

Which I love and also put in Gwion πŸ˜„

 
mcgurkadam profile image
Adam McGurk

YES! I think I got into this mindset of "let me use this because it's cool and I want to use it." That cyclical thinking isn't really conducive to good problem solving, because you may force yourself to use a tool that wouldn't be the best.

Thanks for reading!!

Collapse
 
xanderyzwich profile image
Corey McCarty

I would like to add that not all ternaries are equal. Python's context is much easier to understand imho

is_nice = True
state = "nice" if is_nice else "not nice"
Collapse
 
mcgurkadam profile image
Adam McGurk

Interesting!! Taking away the β€œ?” And the β€œ:” of the ternary operators and replacing them with words. I think I may like that!!

Thanks for reading!!

Collapse
 
fennecdjay profile image
JΓ©rΓ©mie Astor

Order is altered thought:
In C you would write:

bool is_nice = true;
const char *state = is_nice ? "nice" : "not nice";

not

bool is_nice = true;
const char *state = "nice" if is_nice else "not nice";
Collapse
 
bugsysailor profile image
Bugsy Sailor

For most of my coding career I've been a solo coder, meaning I have all the freedom in the world to make the decisions I want on practices for my own websites, etc. In all that time, I have never thought, "Gosh, I wish I was using ternary operators right now!" I like the expanded logic, it was always much easier for me to look over my code in a quick glance.

Collapse
 
mcgurkadam profile image
Adam McGurk

That’s fair, it was never really a conscious decision for me either...I just read about it one day and thought it had this visual elegance...and it just sort of happenedπŸ˜‚πŸ˜‚πŸ˜‚πŸ˜‚

Thank you for reading!!

Collapse
 
costinmanda profile image
Costin Manda • Edited

I think your frustration comes from cases where you neatly define a variable using a ternary operator and then you have to do something for one of the branches of the condition. It feels like duplicating code if you add a new if afterwards and it looks ugly if you turn the ternary into an if/else block and then add the action in one of the branches. I feel you.

However, I think that if we put readability first, then checking a condition twice is the least of our problems. I would much prefer:

var backgroundColor = IsTransparent()
  ? Color.Transparent
  : this.defaultBackgroundColor;
if (!IsTransparent()) {
  DrawSomething();
}

than the alternative:

Color backgroundColor;
if (IsTransparent()) {
  backgroundColor = Color.Transparent;
} else {
  backgroundColor = this.defaultBackgroundColor;
  DrawSomething();
}

One block defines a value, the other is executing an action. I think we should be allowed to use the hammer of our choice for each individual nail.