Error Handling – Null Pointers vs. Null Object Pattern

error handlingnull

Attribution: This grew out of a related P.SE question

My background is in C / C++, but I have worked a fair amount in Java and am currently coding C#. Because of my C background, checking passed and returned pointers is second-hand, but I acknowledge it biases my point of view.

I recently saw mention of the Null Object Pattern where the idea is that an object is always returned. Normal case returns the expected, populated object and the error case returns empty object instead of a null pointer. The premise being that the calling function will always have some sort of object to access and therefore avoid null access memory violations.

  • So what are the pros / cons of a null check versus using the Null Object Pattern?

I can see cleaner calling code with the NOP, but I can also see where it would create hidden failures that don't otherwise get raised. I would rather have my application fail hard (aka an exception) while I'm developing it than have a silent mistake escape into the wild.

  • Can't the Null Object Pattern have similar problems as not performing a null check?

Many of the objects I have worked with hold objects or containers of their own. It seems like I would have to have a special case to guarantee all of the main object's containers had empty objects of their own. Seems like this could get ugly with multiple layers of nesting.

Best Answer

You wouldn't use a Null Object Pattern in places where null (or Null Object) is returned because there was a catastrophic failure. In those places I would continue to return null. In some cases, if there's no recovery, you might as well crash because at least the crash dump will indicate exactly where the problem occurred. In such cases when you add your own error handling, you are still going to kill the process (again, I said for cases where there's no recovery) but your error handling will mask very important information that a crash dump would've provided.

Null Object Pattern is more for places where there's a default behavior that could be taken in a case where object isn't found. For example consider the following:

User* pUser = GetUser( "Bob" );

if( pUser )
{
    pUser->SetAddress( "123 Fake St." );
}

If you use NOP, you would write:

GetUser( "Bob" )->SetAddress( "123 Fake St." );

Note that this code's behavior is "if Bob exists, I want to update his address". Obviously if your application requires Bob to be present, you don't want to silently succeed. But there are cases where this type of behavior would be appropriate. And in those cases, doesn't NOP produce a much cleaner and concise code?

In places where you really can't live without Bob, I would have GetUser() throw an application exception (i.e. not access violation or anything like that) that would be handled at a higher level and would report general operation failure. In this case, there's no need for NOP but there's also no need to explicitly check for NULL. IMO, those checks for NULL, only make the code bigger and take away from readability. Check for NULL is still the right design choice for some interfaces, but not nearly as many as some people tend to think.

Related Topic