X

Learn the Null Object

design patterns

Today, I thought I would mention the Null Object design pattern, its an object that provides intelligent do nothing behavior, hiding the details from its collaborators.

So what does this mean??? Before I tell you what it means, lets see an example of how often you might be seeing code that is checking for null.

Let say we have a Person object, that is implementing an abstract or interface IPerson and there is a repository somewhere that finds the person for us.

//repository code
public IPerson Find(int id)
{
    if(db.UserExist(id))
       return db.GetPerson(id);

    return null;
}
//repository code end

//main code
var person = repository.Find(999);
PrintPerson(person);

public void PrintPerson(IPerson p)
{
   Console.WriteLine(person.Firstname);
   Console.WriteLine(person.Lastname);
}

What happens when we don’t find the person, since the Find method above returns null, we end up with NullReferenceException thrown, because we are calling person.Firstname in the PrintPerson method.

So in order to fix the code we write if statements around it like so

if(person != null)
 PrintPerson(person);
else
   DoSomethingElse();

And we keep writing code with the if statement over and over, every time we want to find we need to check the if(person != null). That is just too painful in my opinion.

So how do we fix it. We use the NullObject, and here is how it looks like in UML.

Null Object

Basically we create another class that implements the interface or abstract class and all its methods and properties implementations does nothing, an example below

public interface IPerson
{
	string Firstname { get; set;}
	string Lastname { get; set; }
	void DoSomething();
	int CalculateSalary();
}
	
public class NullPerson: IPerson
{
    public string Firstname { get; set; }
	
    public string Lastname { get; set; }
		
    public void DoSomething() { }
		
    public int CalculateSalary() { return 0; }
	
}

As you can see the NullPerson has no implementation code in the DoSomething method and it returns 0 for CalculateSalary.
Back in the repository code we will have to return NullPerson rather than null when we can’t find the person.

public IPerson Find(int id)
{
    if(db.UserExist(id)
       return db.GetPerson(id);

    return new NullPerson();
}

From here onwards you can eliminate most of your person != null code. Since whatever method or property you call on it, it would never fail and never return you a NullReferenceException.

You could do something like

var person = repository.Find(999);
PrintPerson(person);

person.DoSomething();
var salary = person.CalcuateSalary();
//etc etc

Our code would not be littered, and we could start writing code that is more elegant that does not contain those nasty if (x == null) statements all over the place. Do remember we might have to implement more NullObjects for other classes that we will be using rather than mishmash of null and NullObject, which would make it ugly.

This pattern helps us realize that we sometimes don’t really want to know if the Get or Find method returns null or not we just want to do something like

var person = repository.Find(999);
person.CallWebService();
var call = person.MakeAPhoneCall();
//since MakeAPhoneCall returns a NullCall this would keep passing
call.Dial(123);
//etc etc

One may also say that there might be cases where you want to an error message, then we can use this way to solve the issue

if(repository.PersonExist(999))
   //Found person
else
   //error message to screen

The NullObject is a very simple idea and once you start using it, you would truly get hooked on it and see the power of something so simple. We then start not caring about those if statements and an added benefit is that our code would be much cleaner and easier to read for others.

Taswar Bhatti:
Related Post