Don't use boolean evaluation as a readability shortcut
TL;DR: Don't use Boolean comparison for side effect functions.
Problems
Read...
For further actions, you may consider blocking this person and/or reporting abuse
What about optional chaining? Which of course only works with functions designed to be chained, like
user?.isValid()?.logUserIn();
I'd use that for finding a deep value but not performing an action:
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.It has to be a boolean, boolean is how the data is first made.
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?
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
Code Smell 149 - Optional Chaining
Maxi Contieri ・ Jul 16 ・ 2 min read
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.
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
Yeah, that makes sense 😄
In my humble opinion
user?.isValid()?.logUserIn()
reads like a human sentence that makes sense, compared to multilinetypeof
blocks.LooksSmells good to me :)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.
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...
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?