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 πŸ˜”

Solutions πŸ˜ƒ

  1. Avoid Null.
  2. Use the NullObject pattern to avoid ifs.
  3. 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 🏷️

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 🏁

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