Entry 11, Day 24
I’ve promised you episode on database, but I’ve lied. Okay, not exactly. Database was my plan, but I haven’t managed to play with the tools before leaving Wrocław for my short vacation. I’ve left behind my dev machine so let’s leave tools too for a week or two. But I’m not leaving you, dear reader.
Until now, I was mainly writing about enterprise stuff connected with my project. There are however many other topics I’d like to touch in this blog. One of them is Object Oriented Design. So today, for starters, since at the beginning there was nothing, I’m going to tell you about the Null Object, behavioural Design Pattern.
The definition says:
In object-oriented computer programming, a Null Object is an object with defined neutral (“null”) behaviour. Example:
Why bother? Because using Null Objects protects you from Null Pointer Exceptions and lets you get rid of ever-present null check logic in the code. So, instead of using null Animal references, you want to use NullAnimal objects. It will not throw NPE in your face, you don’t have to check if it’s there. It will just gracefully do nothing if interacted with. This is the classic – dedicated Null Object class, now let’s move to other, not so obvious usage.
Say you have some kind of state in the form of an enum. But sometimes the state is not present, or somehow unknown. You may use null for that, but you may also add an additional value – “UNKNOWN”, “NONE”, “SHIT_HAPPEND” or something like this. Usually cleaner and safer than null reference.
Third idea, if your object contains a collection, initialize it. Don’t rely on it being delivered via setter later. It is likely that the setter won’t be called, “because of reasons”. But if you put an empty collection at object creation, you are safe to iterate over it later, unless somebody explicitly sets null there, which is rather unlikely (you may also hide the setter itself if you like). There are situations where such practice turns out to be bad however. Be aware that empty collection has some size. It depends on system and VM implementation, but you can count from 40 bytes on ArrayList to around 70 on HashSet. Not much, but I had a case where graph node had several empty collections and when node numbers went into millions, there were corpses of virtual machines lying everywhere.
Finally, there is a nice class in Google Guava, the Optional<T>. It’s an immutable wrapper that can contain another object or null. It can return this object, or null or some default value. It can tell if there actually is an object, or not. It’s good, because you explicitly say that it’s okay to have null value here. The value is optional, as the class name says. Let’s see how it looks like in practice:
That’s about it. There are some issues to consider though. For example – Null Objects shouldn’t change their neutral behaviour. If they do, they actually belong to State Pattern. Null Objects may be special case of Strategy Pattern, representing strategy that well… does nothing.
There are also some caveats in Null Objects. Sometimes clean logic and lack of exceptions may hide erroneous program execution. So, for example, if you expect collection not to be empty, you should do some check before simply iterating over it zero times and move on in silence.
Project-wise, well… I’m proud owner of booksentry.org domain now, where you will find the application’s production environment in the future.
In the next episode, we will talk about SOLID code. Stay tuned.