Monday, May 08, 2006

Returning Null Objects

What does it 'mean' when a method call returns a Null object?


I believe you must define interfaces very carefully. Firstly, because once an interface is in use it is difficult to change later. Second, because every method name, parameter, output is part of the description of what the interface does. The interface 'expresses' a mental model to the developer using it. It explains how the library works, or presents a mental model that can be used to apply the library effectively. The interface tells the developer how the library 'works', so while the code only deals with inputs and outputs, we developers use interface I/O to fabricate an understanding of what's happening under the covers. It is therefore important to specify an interface carefully. So, with that in mind, I propose a few instances where it makes sense to return a Null object from a method.


Errors


If you are not using exceptions to relay errors, or unexpected system conditions, and you are instead setting a global or passed-in error structure, your method should return a Null object reference. You don't want the processing to continue as if nothing was wrong. In the case of an error, the application should proceed into recovery mode. Oh look, I got a Null, something bad must have happened. I can either check the error structure and avoid using the Null object, or I can ignore the error structure and get an Null Object exception (No! Bad programmer!).


Object not found


In many cases I have returned Null from a 'find' or 'get' method when it was unable to retrieve a requested object. While it is necessary to check the return value for Null in these cases, the implementation is simple. A Null object is sometimes even acceptable, as it forms an input to another method which allows a null parameter. I am still in favor of this use of Null object references. After all the database supports the concept of Null too.


Null Object Pattern


The Null Object Pattern entails essentially 'stubbing' out methods and creating an indistiguishable object from the real object. The client object can use the Null object as it would the real thing, and no unpleasant Null checks are required.
I believe the Null Object Pattern is only useful for stubbing out code, where the object's behavior is not important to the client object. Maybe I can stub out the application logging object for example. If I haven't configured my logging, the logging system returns a Null logging object that doesn't fail on the log call, but does nothing. I can't however, stub out the Math object from which I am expecting performance of important calculations. It seems that I would be at risk of introducing difficult to find bugs, I would rather get an 'object reference not set' exception than a series of zeroes displayed in a report.


Empty List or Null


If my method returns a list of objects, and there are no objects to return, it makes sense to me to return an empty list. See Tor Norbye's blog post on this. You certainly can't return either Null or empty list and ascribe the same meaning to both, they're two different things. Empty list is easy, no objects found. Null? That just means an error to me, like the object wasn't properly initialized or something.

No comments:

Post a Comment