Meaningful Null and Other Principles

The discussion around using Null is a long one.
I wrote before about “Why Optional is better than Null”, but there is more to discuss regarding using Null as a way of expressing meaning.

If you are doing OO programming, you should not be using Null as you drink coffee in the morning.

In that other post on this subject, I focussed more on the common case where Null is used to express failing computation.
Another way of using Null is by making it a way of expressing meaning.
If you are doing that, stop it. There are proper, better ways of doing it.

Request Example

Let’s take a look at this example: You want your users to send a request to another user, who either approves or rejects it.
I have seen such cases being coded like this:

What is wrong here? The problem really is that the Boolean attribute hasBeenApproved, by being null, holds meaning and business logic.

Furthermore, note that the setDecision method gets a primitive boolean since the responder can either approve or decline, not ignore it. Again, such logic is mapped in a hidden, implicit and weak manner.

Now, imagine that the request could be ignored… It would require a new boolean attribute (wasIgnored) to be added, which would only check that specific case… ugly!

By last but not least, this object is not shy. Even as an outsider you easily guess how it works inside, which is not good as that causes unwanted coupling, not only around types but also around an implementation.

Tell, Don’t Ask: rather than asking an object for data and acting on that data, we should instead tell an object what to do (Martin Fowler)

Doing it better

It is true that following the way that is shown above does work. “But it works” is not good enough. And I wouldn’t be happy to maintain such code after three or four new requirements have arrived and turned it into cooked spaghetti.

In order to avoid breaking those principles listed above, I would refactor the previous approach into something like this:

Conclusion

This improved version is not great yet.
The more statuses are introduced, the bigger Request will become. And if Request needs to include more data such as date, author, etc, this class no longer will respect the Single-Responsibility Principle.
Furthermore, one can change the status of the Request, which may not be desired.