Skip to content

Sometimes nothing is something. Or the null object pattern with a touch of the decorator pattern

Or why if clauses should die in a fire.

This post has been lingering, locked up in my drafts folder (which is not an actual folder, but all the cool kids say that, so bear with me on this) for some time.

Yesterday, I stumbled upon this talk by Sandi Metz, because, yes, sometimes I search Youtube looking for recordings of talks about OOD. I am a big fun on Sandi’s talks, and this one did not disappoint me, as usual. And it also gave me the push needed to publish this post

If clauses breed, and sometimes, nothing is something

I am not a big fan of if clauses. I know they are necessary, but I try to avoid them as much as possible, specially when they are type checks.

Type checks are bad

Period. There is always someone that will tell you that type checks might be necessary sometimes, but truth is they are one of the biggest and stinkiest code smells.

“What is a type check?” you might ask. Fair enough; this is a type check:

This is the quintessential example of why type checks are wrong, and you will find a thousand slightly different variations of it on the interwebs.

What’s wrong with that? Simple

Type checks are a sign of bad design

The previous code sample is the perfect example of how a type check is a symptom of a bad abstraction. A Fish and a Spider are both animals, so they both should implement an interface declaring a move() method. Clients of Fishes and Spiders would only be aware of that abstraction and call the move() method. Period.

There is a particularly bad type of the check

And that is the one that does not look like one. It is usually in disguise, pretending to be a null check.

Here is an elaborate example. Consider a Car class:

And a CarWarehouse class:

Now, clients of the CarWarehouse want to checkout cars by name:

The forEach method will crash, because it is trying to call getName on something that is null.

Fine, you might think, I will just filter the stream to remove the objects that are null:

But that’s just bad.

Type checks breed

Once you need to start filtering your results, once a client of a class A needs to start performing a type check on the values returned to it by that class, you are going to need to repeat those checks every single time you want to use that class A.

Why? Because you expect the values returned by A to be of at least two different types: null and whatever it should actually be returning.

So, how what can I avoid those type checks?

Making your classes meet the expectations they set. Simple as that.

Which, of course, happens to be not that simple. But seriously, if clients of your class are expecting a collection of entities that respond to a particular message (note the Smalltalk-speak), make sure that all the entities your class returns respond to that message. Again, simple as that.

In the previous example, what do I want exactly? I want all the objects returned by CarWarehouse to respond to getName. Then all I have to do is return a collection of objects that respond to getName. And if there is no object to return, then I will return something else that still responds to that message.

The Decorator pattern. Sort of.

Here come the big guns! Design patterns to the rescue! Not too long ago, I ranted about how design patterns are abused.

In this particular case, I m going to adapt one of the patterns in the catalog, the Decorator Pattern, to wrap my Car objects:

Notice how SafeCar extends Car. That allows me to do the following:

Which, as you can see, is basically creating a null object, sort of. Again, I am taking the liberty of adapting the pattern to my needs.

And now, clients of my CarWarehouse can conduct their business merrily:

Summary

What matters are not the tools you have, but how you use them. Over-abstraction is bad. Over-engineering is bad. Knowing the tools in your belt, knowing how to adapt them and how to let them work together to solve your needs is what matters.

Oh, and sometimes, you need something to help you deal with nothing.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *