Another programming related post here, finally. Today, I want to ramble about the “Null Object Pattern”.
I’m sure we’ve all seen it, and those of us who program have had to debug them- Null Pointer Exceptions/Errors. This occurs when an attempt is made to access an object, and the object has not been allocated- for example:
1 2 |
String stringobject; MessageBox(stringobject); |
Would cause an exception since stringobject is never allocated.
In general, these errors aren’t the most difficult to trace except in very exceptional circumstances- What is difficult to find is how they were set to null or why they were never initialized. Even so, a good number of folks have decided that null is inherently bad because of this and have come up with the “Null Object” pattern. To demonstrate, let’s say we have an iAnimal interface:
1 2 3 4 5 6 7 |
public interface iAnimal { String getName(); String getDescription(); void Sleep(); void TapDance(); } |
This defines getName and getDescription methods that all Animals will support, and of course Sleep and TapDance() methods (All animals can tapdance). Now we might have a class that implements this interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class Possum:iAnimal { public String getName() { return "Possum";} public String getDescription() { return @"The Possum is a diligent pretender who is a master of pretending to be dead. They also like shiny things and funny hats." } public void Sleep() { //the possum sleeps. Console.WriteLine("Possum is Sleeping"); } public void TapDance() { Console.WriteLine("Possum is tapdancing"); } } |
So far so good. Now let’s assume we have another Animal…. Let’s say, a Bear:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class Bear:iAnimal { public String getName() { return "Bear";} public String getDescription() { return @"The Bear is a powerful beast who will kill anything that get's in it's way, especially emo's, he can't stand them."; } public void Sleep() { //the bear sleeps. Console.WriteLine("Bear is Sleeping"); } public void TapDance() { Console.WriteLine("Bear is tapdancing"); } } |
So, we have a Possum, and a Bear, and they are both Animals. Let’s say we create a function that accepts a String name of an animal and returns the iAnimal interface for it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public iAnimal CreateAnimal(String animalname) { switch(animalname.ToUpper()) { case "POSSUM": return new Possum(); case "BEAR" return new Bear(); default: return null; } } |
This function accepts either Possum or Bear as a string and returns the appropriate constructed object. if you pass in Flamingo you will get null, since there is no flamingo animal that the routine knows about.
Apparently, however, nulls are bad. You should never ever use them. The “Null Object” Pattern instead proposes that an alternate interface implementation be made to explicitly represent the “null” version of an object, for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class NullAnimal:iAnimal { public String getName() { return "";} public String getDescription() { return ""; } public void Sleep() { } public void TapDance() { } } |
The idea here is that instead of getting a NullPointerException when you try to access a method or property of a null object, you instead get to trace backwards through lord knows how many steps to find out why your table is printing out blank animal names for your flamingo stock. My point is, It’s not a pattern, it’s an Anti-pattern. The whole idea of the Null-Object pattern isn’t to prevent bugs but to prevent NullPointer Exceptions- these two do not go hand in hand. Instead of receiving a error during development about a null pointer problem, now you are having to deal with it in the field, trying to discover why the class is perfectly valid but returning empty strings. So now instead of checking for null you’re checking to see if your object is a NullAnimal, and you’re back where you damn well started. Instead of fixing the problem and trying to prevent null pointer issues, the Null Object Anti-Pattern is trying to hide it behind a special hand-wavy “null” class that provides default implementations of the interface in question. It might be useful in cases where the service MUST stay up and never crash, but most of those have error trapping and log errors like NullPointerExceptions and they are usually sensitive to the output data, so the fact that the output is now completely wrong is as unacceptable, if not more so than, a crash.
Have something to say about this post? Comment!
One thought on “The Null Object Pattern”
Hi ,
Interesting article, any way i am for null pattern , i guess it is a very good idea to have a “default” object which simulate the null one for a category like “animals” in this case.
Few months ago i remember that i had a bug in hibernate code which comes exactly from this problem , the object was not allocated , it was null so properties could not be set on it (even if they were the default ones, the null ones form application business logic) and hibernate needed an instance of that object (even it was created with default values, “null” object for that category) any way not a null object , because it crashed.
Nice article !
Regards ,
Shv