Programmers use Null as different flags. It can hint at an absence, an undefined value, en error etc. Multiple semantics lead to coupling and defects.
TL;DR: Null is schizophrenic and does not exist in real-world. Its creator regretted and programmers around the world suffer from it. Don't be a part of it.
Problems π
- Coupling between callers and senders.
- If/Switch/Case Polluting.
- Null is not polymorphic with real objects. Hence,Β Null Pointer Exception
- Null does not exist on real-world. Thus, it violatesΒ Bijection Principle
Solutions π
- Avoid Null.
- Use theΒ NullObject patternΒ to avoid ifs.
- UseΒ Optionals.
https://hackernoon.com/null-the-billion-dollar-mistake-8t5z32d6?embedable=true
Refactorings βοΈ
https://hackernoon.com/code-refactoring-tips-no-015-remove-null?embedable=true
https://hackernoon.com/refactoring-029-how-to-replace-null-with-collection?embedable=true
https://hackernoon.com/refactoring-014-how-to-remove-if?embedable=true
Context π¬
When you use null, you encode multiple meanings into a single value.
Sometimes you want to represent an absence.
Sometimes you mean you have not loaded your objects yet.
Sometimes you mean error.
Callers must guess your intent and add conditionals to protect themselves.
You spread knowledge about internal states across your codebase.
Sample Code π
Wrong π«
class CartItem {
constructor(price) {
this.price = price;
}
}
class DiscountCoupon {
constructor(rate) {
this.rate = rate;
}
}
class Cart {
constructor(selecteditems, discountCoupon) {
this.items = selecteditems;
this.discountCoupon = discountCoupon;
}
subtotal() {
return this.items.reduce((previous, current) =>
previous + current.price, 0);
}
total() {
if (this.discountCoupon == null)
return this.subtotal();
else
return this.subtotal() * (1 - this.discountCoupon.rate);
}
}
cart = new Cart([
new CartItem(1),
new CartItem(2),
new CartItem(7)
], new DiscountCoupon(0.15)]);
// 10 - 1.5 = 8.5
cart = new Cart([
new CartItem(1),
new CartItem(2),
new CartItem(7)
], null);
// 10 - null = 10
Right π
class CartItem {
constructor(price) {
this.price = price;
}
}
class DiscountCoupon {
constructor(rate) {
this.rate = rate;
}
discount(subtotal) {
return subtotal * (1 - this.rate);
}
}
class NullCoupon {
discount(subtotal) {
return subtotal;
}
}
class Cart {
constructor(selecteditems, discountCoupon) {
this.items = selecteditems;
this.discountCoupon = discountCoupon;
}
subtotal() {
return this.items.reduce(
(previous, current) => previous + current.price, 0);
}
total() {
return this.discountCoupon.discount(this.subtotal());
}
}
cart = new Cart([
new CartItem(1),
new CartItem(2),
new CartItem(7)
], new DiscountCoupon(0.15));
// 10 - 1.5 = 8.5
cart = new Cart([
new CartItem(1),
new CartItem(2),
new CartItem(7)
], new NullCoupon());
// 10 - nullObject = 10
Detection π
Most Linters can flag null usages and warn you.
Exceptions π
You sometimes need to deal with null when you integrate with databases, legacy APIs, or external protocols.
You must contain null at the boundaries and convert it immediately into meaningful objects.
Tags π·οΈ
- Null
Level π
[x] Intermediate
Why the Bijection Is Important πΊοΈ
When you use null, you break theΒ bijectionΒ between your code and theΒ MAPPER.
Nothing in the mapper behaves like null.
Absence, emptiness, and failure mean different things.
When you collapse them into null, you force your program to guess reality and you invite defects.
AI Generation π€
AI generators often introduce this smell.
They default to null when they lack context or want to keep examples short and also because it is widespread (but harmful) industry default.
AI Detection π§²
You can instruct AI to remove nulls with simple rules.
When you ask for explicit domain objects and forbid nullable returns, generators usually fix the smell correctly.
Try Them! π
Remember: AI Assistants make lots of mistakes
Suggested Prompt: Rewrite this code to remove all null returns. Model absence explicitly using domain objects or collections. Do not add conditionals
Without Proper Instructions π΅
With Specific Instructions π©βπ«
Conclusion π
- Null is the billion-dollar mistake. Yet, most program languages support them and libraries suggest its usage.
Relations π©ββ€οΈβπβπ¨
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xviii
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxxii
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xix
https://hackernoon.com/how-to-get-rid-of-annoying-ifs-forever-zuh3zlo
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-viii-8mn3352
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxx
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xliii
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxxix
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxvi
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xlii
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxxii
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xx-we-have-reached-100
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-ix-7rr33ol
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-v-evj3zs9
More Information π
https://hackernoon.com/null-the-billion-dollar-mistake-8t5z32d6?embedable=true
Credits π
Photo byΒ Kurt CotoagaΒ onΒ Unsplash
I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
Tony Hoare
https://hackernoon.com/400-thought-provoking-software-engineering-quotes?embedable=true
This article is part of the CodeSmell Series.
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd?embedable=true
