Ternaries make code difficult to read and maintain.

Clean code is code that is easy to understand, easy to review and easy to change.

Ternaries, especially as one line functions, are rarely any of these things.

Let’s write a function that returns whether an integer is positive or negative. This can be simply and quickly written as is:

const positiveOrNegative = x => (x > 0 ? 'positive' : 'negative');

However, when testing the code, a test fails, the function returns ‘negative’ when the value is 0 but it should return an empty string (according to a spec that was not read to the end 🙄).

The new code is now:

function positiveOrNegative(x) {
if (x > 0) {
return 'positive';
} else if (x < 0) {
return 'negative';
}
return '';
}

Problem solved, the unit tests pass and the bug is fixed. However, when opening a pull request, here is what the diff looks like:

The entire function has been removed and replaced! For the code reviewers, this means making sure that not only does the new behavior works as intended, but also implies that the existing behavior is still in place and there is no regression. Luckily we can trust our unit tests, but now imagine that the logic is much more complicated than this one line, and the unit tests only offer partial coverage or doesn’t exist at all. This makes the reviewers work much more difficult.

Now let’s imagine that the original code was not written using a ternary:

function positiveOrNegative(x) {
if (x > 0) {
return 'positive';
}
return 'negative';
}

When fixing the code, the diff in the pull request would now look like this:

It is now much easier to understand the intent of the change, instead of an if/else we now have an if/elseif.

Obviously the goal is not to have a pretty diff, but this is a good visual illustration of why ternaries are not a good idea when the logic might evolve beyond a binary choice: if a new condition needs to be added, the code churn and likelihood of regression increase and maintainability decreases.

As an aside, why did the function go from being an arrow function to a regular function? That’s a personal preference that I recommend. I prefer using regular functions at the top of modules because they’re less likely to be mistake for a variable declarations.

Previously Paris and Geneva, currently New York. Can also be found at https://dev.to/arnaud

Previously Paris and Geneva, currently New York. Can also be found at https://dev.to/arnaud