Null Objects

Nothing is something

- Sandi Metz1

Null objects surface hidden assumptions making code easier to reason about and to change. Consider the number 0. Initially a mathematical placeholder, 0 was imbued with meaning allowing all numbers to be used in new ways.

By working with numbers as they approach zero, calculus was born without which we wouldn't have physics, engineering, and many aspects of economics and finance.

-Nils-Bertil Wallin2

Takeaway 0: Applications have abstractions like 0 that reveal themselves through the absence of code.

Consider a lab that may or may not have an experiment running.

lab.try(:experiment)                       # is:  
lab && lab.experiment                      # is:  
lab.nil? ? '' : lab.experiment             # is:  
lab == nil ? '' : lab.experiment           # is:  
lab.is_a?(NilClass) ? '' : lab.experiment  # is:

# which ultimately is:
if lab.is_a?(NilClass)  
  ''
else  
  lab.experiment
end  

Its easy to forget that each of these expressions is a conditional and that conditionals are implicit type checks.

Takeaway 1: Type checking hampers the full power of objects.

Rabbits of OOP - Conditionals

if (object type is NilClass)  
  # Caller supplied behavior
else  
  # Caller sends message to collaborator
end  

if burdens the caller with knowledge of what behavior to provide when the object is a NilClass. Callers should know only what message to send to whom. As callers multiply, this burden can overwhelm applications like a herd of rabbits. Instead of fostering the local rabbit population, use a null object to isolate and provide the behavior.

Takeaway 2: Behavior supplied by a caller is a hidden null object.

Close

The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be.

- Alan Kay3

Our programs are easier to maintain, reuse, and extend when we rely on message passing. A recognition that conditionals are a subtle form of type checking and that callers should not supply default behavior surface the need for an object that can stand-in in the absence of a real object. Next time you write a conditional or reach for try! consider if there is a null object that could better serve your needs.

Photo By NASA/GSFC/METI/ERSDAC/JAROS, and U.S./Japan ASTER Science Team [Public domain], via Wikimedia Commons

Show Comments