Null Objects are great alternatives to The Billion Dollar Mistake. Sometimes we don't need them
TL;DR: Don't abuse patterns. Even NullObject.
Problems
Empty Classes
Namespace Polluting
Duplicated Behavior
Solutions
- Create Null Objects instantiating real-object classes.
Context
Null Object pattern is a great alternative to Nulls and IFs (Both are code smells).
The structure of the pattern tells us to create a hierarchy.
This is not really necessary, we need real objects to be polymorphic to null objects.
Inheritance is not a proper way to achieve polymorphism.
A simple solution is to create a real object behaving like a null one.
For example: '0' is the numbers' null object.
'' (or "") is String's null object
An empty collection is the collection's null object.
Sample Code
Wrong
abstract class Address {
public abstract String getCity();
public abstract String getState();
public abstract String getZipCode();
}
//Using inheritance for null objects is a mistake
//We should use interfaces (when available)
public class NullAddress extends Address {
public NullAddress() { }
public String getCity() {
return Constants.EMPTY_STRING;
}
public String getState() {
return Constants.EMPTY_STRING;
}
public String getZipCode() {
return Constants.EMPTY_STRING;
}
}
public class RealAddress extends Address {
private String zipCode;
private String city;
private String state;
public RealAddress(String city, String state, String zipCode) {
this.city = city;
this.state = state;
this.zipCode = zipCode;
}
public String getZipCode() {
return zipCode;
}
public String getCity() {
return city;
}
public String getState() {
return state;
}
}
Right
//There are just "addresses"
public class Address {
private String zipCode;
private String city;
private String state;
public Address(String city, String state, String zipCode) {
//Looks anemic :(
this.city = city;
this.state = state;
this.zipCode = zipCode;
}
public String zipCode() {
return zipCode;
}
public String city() {
return city;
}
public String state() {
return state;
}
}
Address nullAddress = new Address(Constants.EMPTY_STRING, Constants.EMPTY_STRING, Constants.EMPTY_STRING);
//we have our null object
//we should NOT assign it to a singleton, static or global
//It behaves like a null object. That's enough
//No premature optimizations
Detection
[X] Manual
This is a semantic smell.
Tags
- Null
Conclusion
Creating Null Object classes is sometimes overdesign.
We need to create a real object.
This real object should never be global, singleton, or static.
Too many smells to avoid.
Relations
More Info
Credits
Photo by Juan Davila on Unsplash
Thanks to Hernan Wilkinson for this idea on his course Diseño a la Gorra (in Spanish)
All models are wrong but some models are useful
George Box
This article is part of the CodeSmell Series.