Code Smell 305 - Null Infinity

Maxi ContieriMaxi Contieri
4 min read

TL;DR: Use Infinity instead of None when looking for minimums

Problems πŸ˜”

  • Accidental IFs
  • Wrong default
  • Bad polymorphism
  • Extra conditions
  • Hidden initialization
  • Wrong domain mapping
  • Misleading behavior
  • Unnecessary conditionals
  • Complex logic
  • Null checks
  • Error-prone code

Solutions πŸ˜ƒ

  1. Remove the Accidental IFs
  2. Use infinite value
  3. Remove None check
  4. Respect math semantics and consistency
  5. Apply the null object pattern
  6. Reduce boilerplate, simplifying your code
  7. Use float('inf') as base case for minimums ♾️
  8. Use float('-inf') as base case for maximums -♾️
  9. Remove conditional branches

Refactorings βš™οΈ

Context πŸ’¬

Problem 1:

You want to find the greatest number in a list.

You start with 0 and compare.

An amazing Null Object. No Accidental IFs involved. Clean code. πŸ‘Œ

Problem 2:

You want to find the lowest number in a list.

Most beginners start with None and check "if current is None or x < current".

You don’t need that.

You can start with float("inf") ♾️.

It behaves-as-a a number.

You can compare, sort, and minimize it.

This gives you simpler logic and polymorphic code.

The holy grail of behavior.

Sample Code πŸ“–

Wrong ❌

def find_minimum_price(products):
    min_price = None

    for product in products:
        if min_price is None:
            min_price = product.price
        elif product.price < min_price:
            min_price = product.price

    return min_price

def find_minimum_in_list(numbers):
    if not numbers:
        return None

    minimum = None
    for number in numbers:
        if minimum is None or number < minimum:
            minimum = number

    return minimum

# Usage leads to more None checks
prices = [10.5, 8.2, 15.0, 7.8]
min_price = find_minimum_in_list(prices)
if min_price is not None:
    print(f"Minimum price: ${min_price}")
else:
    print("No prices found")

Right πŸ‘‰

def find_minimum_price(products):
    min_price = float('inf')

    for product in products:
        if product.price < min_price:
            # This is an essential IF, you should not remove it
            min_price = product.price
            # No accidental IF here (if min_price is None:)

    return min_price if min_price != float('inf') else None

def find_minimum_in_list(numbers):
    minimum = float('inf')

    for number in numbers:
        if number < minimum:
            minimum = number

    return minimum if minimum != float('inf') else None

# Cleaner usage - polymorphic behavior
prices = [10.5, 8.2, 15.0, 7.8]
min_price = find_minimum_in_list(prices)
print(f"Minimum price: ${min_price}")

Detection πŸ”

[X] Semi-Automatic

You can grep your codebase for None inside loops.

If you check against None before comparing values, you probably smell it.

Look for if current is None or x < current.

Tags 🏷️

  • Null

Level πŸ”‹

[X] Beginner

Why the Bijection Is Important πŸ—ΊοΈ

In math, the identity element for finding a minimum is positive infinity. ♾️

When you use None, you break the MAPPER

None is not a number.

It does not behave as a number; it is not polymorphic with numbers.

it is evil Null disguised as *None.

You must then write special code to treat it.

That breaks the bijection between your code and math.

When you use float("inf"), you stay close to the real concept.

The code models the domain truthfully.

AI Generation πŸ€–

AI models that generate loops often use None as the starting point.

They may include unnecessary checks.

This typically occurs when the model attempts to mimic tutorials or is trained with bad code or overly simplified examples.

AI Detection 🧲

AI can easily detect and fix this issue when you provide clear instructions.

For example

Use Infinity for minimum search initialization

or

Apply the null object pattern for mathematical operations.

Try Them! πŸ› 

Remember: AI Assistants make lots of mistakes

Suggested Prompt: Use Infinity for minimum search initialization

Conclusion 🏁

Zero is not the default for everything.

When you want to find a minimum, you should start at infinity.

This clarifies your code, removes conditionals, and is a better bijection to math.

Stop treating None like a number.

Infinity is polymorphic and is the the null object for maximum math operations

Use it.

Relations πŸ‘©β€β€οΈβ€πŸ’‹β€πŸ‘¨

More Information πŸ“•

Disclaimer πŸ“˜

Code Smells are my opinion.

Credits πŸ™

Photo by Cris Baron on Unsplash


Code should model the problem, not the solution

Rich Hickey


This article is part of the CodeSmell Series.

0
Subscribe to my newsletter

Read articles from Maxi Contieri directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Maxi Contieri
Maxi Contieri

I’m a senior software engineer loving clean code, and declarative designs. S.O.L.I.D. and agile methodologies fan.