Our code is more robust and legible. But we hide NULL under the rug
TL;DR: Avoid Nulls and undefined. If you avoid them you will never need Optionals.
Problems
Nulls
Solutions
Remove nulls
Deal with undefined
Context
Optional Chaining, Optionals, Coalescence, and many other solutions help us deal with the infamous nulls.
There's no need to use them once our code is mature, robust, and without nulls.
Sample Code
Wrong
const user = {
name: 'Hacker'
};
if (user?.credentials?.notExpired) {
user.login();
}
user.functionDefinedOrNot?.();
// Seems compact but it is hacky and has lots
// of potential NULLs and Undefined
Right
function login() {}
const user = {
name: 'Hacker',
credentials: { expired: false }
};
if (!user.credentials.expired) {
login();
}
// Also compact
// User is a real user or a polymorphic NullUser
// Credentials are always defined.
// Can be an instance of InvalidCredentials
// Assuming we eliminated nulls from our code
if (user.functionDefinedOrNot !== undefined) {
functionDefinedOrNot();
}
// This is also wrong.
// Explicit undefined checks are yet another code smell
Detection
[X] Automatic
This is a Language Feature.
We can detect it and remove it.
Tags
- Null
Conclusion
Many developers feel safe polluting the code with null dealing.
In fact, this is safes than not treating NULLs at all.
Nullish Values, Truthy and Falsy are also code smells.
We need to aim higher and make cleaner code.
The good: remove all nulls from your code
The bad: use optional chaining
The ugly: not treating nulls at all
Relations
Code Smell 145 - Short Circuit Hack
Maxi Contieri ・ Jun 30 '22
Code Smell 69 - Big Bang (JavaScript Ridiculous Castings)
Maxi Contieri ・ May 4 '21
More Info
Null: The Billion dollar mistake
Maxi Contieri ・ Nov 18 '20
How to Get Rid of Annoying IFs Forever
Maxi Contieri ・ Nov 9 '20
Credits
Photo by engin akyurt on Unsplash
He who fights with monsters might take care lest he thereby become a monster. And if you gaze for long into an abyss, the abyss gazes also into you.
Nietzsche
Software Engineering Great Quotes
Maxi Contieri ・ Dec 28 '20
This article is part of the CodeSmell Series.
Top comments (21)
1 I have no strong evidence it takes more memory.
Memory is expendable. Readability and maintainability aren't
It seems we are dealing with 'Premature Optimization'.
I also think 'undefined' are yet another code smell.
I will also very happy if juniors stop using nulls since we are no longer in the 50s.
But I wil DO take your advice and add a disclaimer these articles are opinions and write it down
I am also reading your articles!
I'm a beginner and am using
null
andundefined
in my current project, and I'd love to hear why they are bad. 🤔For example we have an
Order
object, and it has a property calledfinishedAt
with typeDate
. What should I return if the order is not finished? I'm usingnull
in this case.if the order is not finished you shouldnt ask for the date. it makes no sense in real world
An exception should follow fail fast principle
An unfinished order is signified with
.finishedAt = undefined
. If you make this property throw an exception, you are violating:dev.to/mcsee/code-smell-73-excepti...
Well, what about
number | null
cases? Let's say you're checking pizza price in an app and for an unknown reason, backend cannot find a value for the price and sendsnull
, how would we eliminatenull
in this case? What would backend then have to send to the frontend if not anull
? 0? :)You mean number | number cases?
Nulls don't exist on real world
if backend cannot find a value it should an exception. Which is exactly what happen in real world
Backend should inform with exceptions. Nulls are schizofrenics. Exceptions are specific and handleable
I completly disagree here. Not about null being bad, but about exceptions as a replacement for null.
Null is not always conveying an error, you should take a step back when writing theses.
Null and undefined is often used for indicating optional values. Optional is not an error. And that is why a lot of language and libraries are supporting two kind of result types :
And you can declare both like this in typescript :
and
But those are not javascript native features, and then can have an impact on performance. If performance matters, using undefined and checking for it should be acceptable.
My own veteran opinion.
Hi Veteran
I am also a veteran and saw too many systems failing for the infamous null
The man who invented it regretted in public
Here is the whole story:
Null: The Billion dollar mistake
Maxi Contieri ・ Nov 18 '20 ・ 6 min read
And IMHO and experience. Performance (and premature optimization) are much less important than reliability and readability.
Performance was important on the 50s where nobody needed to maintain code.
I perfectly know about this. But you should also know that in javascript, null or undefined to not lead to the same kind of errors. Since this can't lead to undefined behaviour and arbitrary code execution that
C
has.Null or undefined in javascript lead to unchecked results and application
Panic
.Panics
are there to prevent exploits. So it will not lead to a CVE and an exploit unless you have a functionnal happy path that leads to an exploit. Which is not the same.To prevent the later, I recommend everyone to use Typescript and strictNullChecks by default to allow your static code analysis to detect these kind of defects.
In my opinion it's better than using runtime exceptions everywhere. Exceptions are hard to follow, they can't be statically analysed, they can lead to the same kind of issues if not checked, aka a system Panic.
"To prevent the later, I recommend everyone to use Typescript and strictNullChecks by default to allow your static code analysis to detect these kind of defects" awesome
And to clarify my point. That i think your article about
Null : The billion dollar mistake
misses to highlight.What was bad with NULL is design it in such a way that it can lead to undefined behaviour and arbitrary code execution. What was also bad was not adding a basic static analysis tools to detect when NULL is unchecked.
And to expand on what kind of issue unchecked NULL can lead to in javascript :
Panic
The main issue is with the first one. Since the second one will lead to a Fail Fast without any exploit possible.
So the first one is tricky, and is not just tied to NULL. Indeed, functionnal error (not handling all uses cases) can also be common on every langages, even those without NULL.
The solution to theses types of errors are nowadays to use a strict static analysis tools. And i repeat, these errors are not just tied to NULL.
Every modern langages now come with a static code analyzer embeded, I have given typescript example, but since i use a lot Rust langage, i can also say that it comes with one of the best static analysis tool out there (borrow checker, memory lifetime checking, etc are so wonderfull tools for static code analysis).
no. an unfinished order has an status unfinished or it is directly unfinished.
Asking for its data is an Exceptional case. Therefore is not an exception for Expected Case
What is your date of death?
How would you answer it?
undefined? null ? 1970-01-01 ?
No. you should say: 'You cannot ask me this. I am still alive!!'
I'll give your approach a try and maybe come back with some arguments to your article :)
Hi
I am not saying undefined is better than null.
They are bad and introduce lots of IFs.
undefined is not a good alternative to null
We should avoid both
It is not User responsibilty to know if its dead or Alive.
Not everything is an attribute
Code Smell 35 - State as Properties
Maxi Contieri ・ Nov 27 '20 ・ 1 min read
Optional Arguments are 'easy' and 'buggy'. so you type hint but you skip type hinting.
I would not use a library that throws an exception.. unless I am making a mistake
Thank you for your advice! I was too particular about keeping a fixed structure of the response data, thinking it would benefit in the long run. Now I know what I should do!
Ok. That's your opinion.
I am not going to change it
Maybe write another smell about "optional" properties
Imho work with user as class seems a little bit wierd. Behind of optional chaning usability is the outer data structure deep checking with sort code, I did not means as hack.
Lemme illustrate why the
undefined
doesn't look as a good alternative tonull
for me so far:in typescript returned type of
foo
will be inferred asvoid
(though the absence of value isundefined
), which means assigningvoid
toundefined
is a type error.What's worse is you can go ahead and write:
So
undefined
is assignable tovoid
andundefined
, butvoid
is not assignable toundefined
. But they are bothundefined
, that's even more confusing than havingnull
imo :)I see your point, but defining something as
undefined
explicitly when you need optional value does not look too attractive.Besides if you encounter a field which is undefined, there is no telling if it was intentionally set to
undefined
or was lost somewhere along the way. That'd make you check both for key and value presence to understand if the value is empty, unlike withnull
, which would require only one check, or with Maxi's default/empty value approach.