NULL Object – Part 2


So, continuing our look at NULL Object – let’s look at a more complicated example.

Here’s our Employee object again – this time I’ve added a method to calculate the employee’s payslip:

/// <summary>
/// Generates the payslip for this employee.
/// </summary>
/// <returns>TRUE on successful generation of the payslip.</returns>
public bool GeneratePayslip ()
{
    bool GeneratedPayslipSuccessfully = false;

    // Call the payroll system to print out an payslip for this employee id and set GeneratedPayslipSuccessfully accordingly
    // e.g. PayrollSystem.GeneratePayslip (this.Id);

    return GeneratedPayslipSuccessfully;
}

Now, imagine this running using our existing NullObject pattern-aware client code:

// Print a payslip for Employee 123
var MyEmployeeObject = Employee.GetEmployeeFromDb (123);
bool WasSuccessful = MyEmployeeObject.GeneratePayslip ();
if (!WasSuccessful)
    System.Console.WriteLine ("An error occurred whilst generating the payslip for employee {0}.", MyEmployeeObject.Id);

Our code won’t crash per se, but we’ll be making a real call to some payroll system with an invalid employee id – who knows what will happen? Or what if this call blocked the application whilst we waited for a result etc. etc.. Ideally, we don’t want this call to happen if the employee object is the “null” version – but we still want the method there so that the client code doesn’t need to worry about it.

Here are a few options to solve this problem: –

One way is to set a property on the Employee object to say “am I the null employee”, and the front end can check this. But that’s going against the whole Null Object pattern, so let’s discount this option right away.

Another way is to amend our GeneratePayslip method like and to check for whether this Employee is the null one:

/// <summary>
/// Generates the payslip for this employee.
/// </summary>
/// <returns>TRUE on successful generation of the payslip.</returns>
public bool GeneratePayslip ()
{
    // Always return true for the null employee
    if (this == NullEmployee)
        return true;

    bool GeneratedPayslipSuccessfully = false;

    // Call the payroll system to print out an payslip for this employee id and set GeneratedPayslipSuccessfully accordingly
    // e.g. PayrollSystem.GeneratePayslip (this.Id);

    return GeneratedPayslipSuccessfully;
}

This works – we will never call the real payslip system for a null employee – but again – to me – it seems “wrong” i.e. once again we’ve got a sort of “null check” somewhere within our code. Granted, it’s just in the one place i.e. the employee object itself, but we’ll have to do this check on every method that the Employee exposes etc. – this just seems “wrong” to me.

Here’s another option which is slightly more complex but (IMHO) is the most elegant solution:

First, we make GeneratePayslip method virtual, and then we make a new class which inherits from Employee. This class will represent our Null Employee.

internal class NullEmployee : Employee
{
    internal NullEmployee ()
    {
        Name = "No employee found.";
        Department = "Not set";
    }

    public override bool GeneratePayslip ()
    {
        return true;
    }
}

Notice how we are first setting the default values for the Name and Department in the constructor – so that the base Employee class will no longer have to set them as it did in the earlier example.

Secondly, the GeneratePayslip method is now overridden so that it always returns true for the null employee.

Thirdly, I’ve set the class as Internal so that client assemblies using this Employee class will never know about the NullEmployee object – as far as they are concerned it’s just a regular Employee object, they won’t see it in intellisense, they can’t generate one themselves etc.

Now our base Employee class looks as follows:

public class Employee
{
    public static Employee GetEmployeeFromDb (int employeeId)
    {
        Employee Output = null;

        // Do some code here to retrieve the employee - if none is found, leave Output as null

        // If no employee was found, return the default "null" employee
        if (Output == null)
            Output = new NullEmployee();

        return Output;
    }

    public int Id { get; private set;}
    public string Name { get; private set; }
    public string Department { get; private set; }

    /// <summary>
    /// Generates the payslip for this employee.
    /// </summary>
    /// <returns>TRUE on successful generation of the payslip.</returns>
    public virtual bool GeneratePayslip ()
    {
        bool GeneratedPayslipSuccessfully = false;

        // Call the payroll system to print out an payslip for this employee id and set GeneratedPayslipSuccessfully accordingly
        // e.g. PayrollSystem.GeneratePayslip (this.Id);

        return GeneratedPayslipSuccessfully;
    }

Firstly, I’ve removed the static NullEmployee object. We could theoretically keep it but it’s probably not required now since all the “business logic” of defining the content of a null employee is in that object’s constructor now.

Secondly, the GeneratePayslip method knows nothing about whether it’s a null employee or not since this method will now always be run for “proper” employees; the null version will do nothing.

Finally, the front end still does not care about whether the Employee object is null or not. It can print out the employee’s details and even try to generate a payslip – it won’t give null reference exceptions, it won’t call external systems for “bad” employee data, and the client code doesn’t need to check if the employee is null.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s