Null Object and Optional
Null Object and Optional are both ways to avoid nulls. In the following post we will compare these two approaches to see when one or the other is more suitable.
Null Object
Null Object pattern is nice as it hides away the special case of not having a value for something. So ideally we should be able to avoid all ifs for null checks. This works nicely when we can replace normal behavior with a noop implementation. However, it does not work so well when we need to access some data on the object.
For example, we have a Customer class like this:
class Customer {
static final Customer NULL = new Customer() {
Instant registrationDate() {
return null
}
}
Instant registrationDate() {...}
}
Customer.NULL
allows us to avoid nulls when there is no Customer
. However, when we need to get the registration date we are back in the null land.
One solution is to turn this from plain getter into something that has more behavior. If the question we want to ask from Customer
is: “Did you register before date X?” we can just add a method like registeredBefore(Instant)
. It may seem like simple cosmetics. However, this can be a nice strategy how to introduce behavior into a class that originally looked like a plain struct.
Optional antipatterns
What if we still need the registered date value? For example, to format the date value as a String for our JSON response.
One way how to avoid null checks is wrapping the result in an Optional
:
Optional.ofNullable(
customer.registrationDate()
).map(
dateTimeFormatter::format
).orElse(null)
Although I have used this style quite a lot it is not very elegant. In fact this is not any better than doing plain “ifs” for nulls. We still need to be alert that some values may be null everywhere in our codebase.
Another antipattern I have used is adding hasValue()
method to Null Object. This again defeats the purpose of Null Object pattern and should not be used.
Null Object with Optional
For the scenarios like above returning Optional
makes more sense than forcing client code to do that. Otherwise we have just replaced the “if” with slightly fancier code but achieved nothing else.
So Optional and Null Object can nicely complement each other. Using Null Object for more complex value objects and have query methods return Optional where no other sensible value can be used.
P.S. Interested to join us? We’re hiring. Check out our open Engineering roles.