Null object pattern and sealed classes
Tags: designpatterns, kotlin, nullobjectpattern, sealedclasses
Published: 2020-04-26 18:23:16

---
title: Null object pattern and sealed classes
published: true
date: 2020-04-26 18:21:35 UTC
tags: design patterns,kotlin,null object pattern,sealed classes
canonical_url: https://le0nidas.gr/2020/04/26/null-object-pattern-and-sealed-classes/
---

In a recent code review one of my colleagues was concerned that part of the code I wrote might cause us problems because of the null object pattern I chose to use.

The code was something like this:

{% gist https://gist.github.com/le0nidas/528b493b1611311a4ddd6ea0979280f6 %}

and my colleague was referring to the `Nobody` usage.

That got me thinking. Can this usage of sealed classes be considered as an implementation of the null object pattern? Also, why is the usage of this design pattern a bad thing?

### Null object pattern ([wikipedia](https://en.wikipedia.org/wiki/Null_object_pattern))

So, what is this pattern? This pattern is one way to solve the

> we don’t want a method to return a null value and force ourselves to check it before usage
 
*(my definition :P)*

Ok, it might be better to have an example:

Lets say that we have a service that returns the workout we did in a particular date. Each workout has the duration of the exercise and if we did not workout on the given date the service returns null _(we’ll pretend for a moment that Kotlin does not have null safety or those great extensions like map, sum etc)_:

{% gist https://gist.github.com/le0nidas/3335a17047b8cbea4ebaeb9a3f1bd2d5 %}

By introducing a `null object`, for those days that we did not workout, we can remove the null checks and have a more readable code:

{% gist https://gist.github.com/le0nidas/7e2d974cfbfe648a5f393eec3bf4dfd2 %}

### Why is this a bad design?

From the example we could easily conclude that this pattern is quite helpful. Right?

Well, as everything in our industry: it depends! When we need a way to have some default values so that our calculations won’t crash and burn then it is a good choice. But if we use it in ways that we hide things we might end up in false successes.

For example, lets assume that we have a storage interface and a factory function that returns the proper storage implementation depending on a given value:

{% gist https://gist.github.com/le0nidas/d4e9b7d775e9e984cab3bbc624616203 %}

If something is not configured well we might end up using, through out our entire project, the `NullStorage`thinking that we have saved everything when in reality we lost our data!

In case you missed it there is a space in the _cloud-type_ so no matter how many times we ask for the _“cloud”-storage_ we will get the _null-storage_ back. Silly example with a silly mistake but imagine what could go wrong in real projects!

### So, back to the code that started all this

#### First thing is first:

**_Q:_** _Is this usage of sealed classes an implementation of the null object pattern?_

**A:** No. The `Nobody` object is just a representation of a valid state for the `AssignedTo` concept and does not provide any default values or hides any method usage.

**Q:** _Can sealed classes be used for implementing the null object pattern?_

**A:** Yes. Sealed classes can help us in having many values for one concept but the fact that we can use full fledged classes, that can also inherit a bunch of things, is quite powerful and can be easily misused. I don’t see anything stopping us from implementing the _storage-example_ using sealed classes so we just need to think things carefully.

#### And now the twist:

As is, the code does not implement the design pattern but with a small change we can make it not only to implement it but to do it badly too! We’ll just move the name property to the parent and have `Nobody` provide an empty value:

{% gist https://gist.github.com/le0nidas/1d4ef8196b10bb321bda9194958a749f %}

**Q:** _Why is this bad? It does not hide anything, it provides a default value and to be honest we just need to pass “nobody”, instead of an empty string, to the super constructor._

**A:** Well, this time it depends on where we use the pattern and not how. If this code is part of our core layer then we are allowing this layer to decide on presentation issues! It should be the presentation layer that will check what value the `assignedTo` has and print “nobody”!

Our previous implementation of `AssignedTo` was forcing us to make the distinction between all of its values so we did not have much of a choice but to let the `print` function decide.

### In conclusion

Think twice before using the null object pattern and, if you are in a team, try to put code reviews as part of your work flow. It is always good to have a fresh pair of eyes look at your code and even better to have a few people to discuss (and argue) about your choices.

Trying to explain something will make you understand it better!