Worst Error Detection Mechanism – Ever

November 5, 2009 § Leave a comment

When you don’t trust your code, something is wrong.

Take a look at this code:

   1: SomeClass* pSomeObject = GetInstance();
   2:  
   3: if(pSomeObject == NULL)
   4: {
   5:     DisplayErrorMessage();
   6:     return;
   7: }
   8:  
   9: pSomeObject->DoSomething();

I see this code this all the time.  I also admit to writing code like this (insert frown here).  You’re probably looking at it and thinking, there is nothing wrong with it.  Depending on the context you may be right.  Generally, this code just does not feel right to me.

Let me paraphrase the code:

   1: // Get me an object
   2:  
   3: // If the object is not what I wanted, inform about the error and leave
   4:  
   5: // Do something with the object

So the questions I have to ask are:

  1. Why does the code think it would receive an invalid object?
  2. If the code is concerned about invalid objects, why is this code only checking for a NULL?
  3. Why does the code need to know if the object is valid?

Here are some possible answers:

  1. The check is to ensure that certain code is not executed if the object is not capable.
  2. If the object reference is not NULL, it is reasonable to assume that the object is valid so no other check is needed.
  3. If the object is not valid, the code should not use it.

All are valid answers, but there is a better way.  One that streamlines your code and relieves it from the burden of validating what other code provides.  Take a look at the following:

   1: SomeClass* pSomeObject = GetInstance();
   2:  
   3: pSomeObject->DoSomething();

This code will still run without crashing even though I removed the NULL pointer check.  How?  You have probably guessed that the magic happens inside GetInstance.  Instead of GetInstance returning an potentially unusable instance, it guarantees a usable object everytime, even when one is not available.  Here is what it does:

   1: SomeClass* GetInstance() {
   2:  
   3:     if (pClass && pClass.IsValid()) {
   4:         return pClass;
   5:  
   6:     } else {
   7:         return pNullClass;
   8:     }
   9: }

SomeClass is a common interface for pClass and pNullClass.  This hides the concrete class from the code that is calling GetInstance.  pClass is the reference returned when the class has determined that it is ready to be exercised (i.e. IsValid()).  This increases the coverage on validating the object because its validation does not expose its internal state, but it can review everything it encapsulates.  GetInstance also checks if the pointer is NULL.  These checks only need to occur once, and no external code needs to worry about these validations, improving the cohesion of the code base.

Lastly, and this is where the magic happens, when pClass is not valid, a separate instance of a unique class is returned: pNullClass.  The purpose of this class is to do nothing, literally.  It exposes the same interface as pClass, but it has no functionality.  This way, if code calls a member of this class, there is no crash or invalid behaviour because the class is still valid.  If you really wanted to, you could log an error or notify the user of the problem when the class is constructed.

This is the “Null Object Pattern” in combination with a factory of some kind.  It is easy to implement and makes the kind of error handling mentioned earlier, easier to maintain.

There is some cost in taking this approach.  You have to create and maintain the Null Object.  Anytime the interface changes, this class must also change.  One more class you need to maintain in your code base.

In my opinion, the benefit outweighs the cost.  All code that calls the factory no longer has to worry if a valid object will be returned.  The dependency is removed, making that code easier to maintain.  It may be one more object, but it is easy to maintain, and simplifies the rest of your code base.

Bottom line.  Don’t push the responsibility of validating what you produce on those who need it.

Leave a comment

What’s this?

You are currently reading Worst Error Detection Mechanism – Ever at Journeyman.

meta