DEV Community

Cover image for Code Smell 145 - Short Circuit Hack

Code Smell 145 - Short Circuit Hack

Maxi Contieri on June 30, 2022

Don't use boolean evaluation as a readability shortcut TL;DR: Don't use Boolean comparison for side effect functions. Problems Read...
Collapse
 
ingosteinke profile image
Ingo Steinke, web developer

What about optional chaining? Which of course only works with functions designed to be chained, like user?.isValid()?.logUserIn();

Collapse
 
moopet profile image
Ben Sinclair

I'd use that for finding a deep value but not performing an action:

if (user?.foo?.bar) {
  user.login();
  // or...
  logUserIn(user);
  // or whatever
}
Enter fullscreen mode Exit fullscreen mode

Also, the implication in your example is that isValid() returns a user object when that's not obvious - it looks like it should be a boolean.

Collapse
 
feliciousity profile image
Felicia Ann Kelley

It has to be a boolean, boolean is how the data is first made.

Thread Thread
 
kentaro_tanaka_5b2893f1d1 profile image
Kentaro Tanaka

The condition essentially evaluates to a boolean value, determining whether the nested property user.foo.bar exists and is truthy.

I am also engineer. Can we discuss more details?

Collapse
 
mcsee profile image
Maxi Contieri • Edited

Null is the worst code smell

And optional chaining, IMHO hids this antipattern.
I've written a smell on optional chaining. I will publish it in the following weeks

hackernoon.com/null-the-billion-do...

And optional chaining is another code smell

Collapse
 
larsejaas profile image
Lars Ejaas

But we are not always writing the data or code with null ourselves.

One example: Auto-generated types made with GraphQL Code Generator.
We still need to be able to handle null.
Null does indeed make sense if you do not know if data will return empty.

Thread Thread
 
mcsee profile image
Maxi Contieri

Of course
In case null is beyond your own control you need to deal with it

That is why it is the billion dollar mistake

We must be mature enough to avoid creating NEW nulls

Thread Thread
 
larsejaas profile image
Lars Ejaas

Yeah, that makes sense 😄

Collapse
 
bwca profile image
Volodymyr Yepishev

In my humble opinion user?.isValid()?.logUserIn() reads like a human sentence that makes sense, compared to multiline typeof blocks. Looks Smells good to me :)

Collapse
 
rgails profile image
Ryan Gails

My big issue with this is debugging it. Did we not log in because we have no user, because the user isn't valid, or because isValid returned null (which seems like something you'd want to handle in a particular way IMO)? A single line getting the job done is great until you're ripping through 20 lines of chained methods trying to figure out where things went wrong.

I agree with Ben that it's fine to get deep values with though. Especially if you really just care about whether or not you could get to the value you were looking for.

Collapse
 
eljayadobe profile image
Eljay-Adobe

When I've asked about optional chaining in C++, the push back I've gotten has been that it's a code smell because optional chaining means high coupling and intimate knowledge of the private parts.

So, for better or worse, in C++ we'll still have this...

if (user && user->isValid())
    user->isValid()->logUserIn();
Enter fullscreen mode Exit fullscreen mode
Collapse
 
omarbenmegdoul profile image
Omar Benmegdoul • Edited

Why is this a problem specifically before a side-effect?

Something like myFunc?.() will force people to pause. On the other hand short-circuits are a common pattern when setting default values or optionally rendering React components. People are used to reading them in other contexts, often with function calls on the right, so why do they become less readable in this one?