Duplicate Code? Introduce Null Object

Posted on Monday, September 13, 2010

5


One of the most significant code smells is having duplicate code. There are primarily 2 forms of code duplications

  • Explicit – These are the ones where there is blatant copy paste of the code. Methods are repeated within classes and it is easy for the CPD tool of PMD to figure out that lines are copied thus leaving us red faced.
  • Subtle – This is the more dangerous form of duplication in which, though differences appear at a syntactical level, however, the structure and the processing steps are quite the same.

One such form of subtle duplication is checking for null. You would have surely encountered a case like this, which we had in our application


public void upgradeTheDepartment(UserDepartment department){
	User headOfDepartment = getHeadOfDepartment(department);
	if ( headOfDepartment != null)
		{
		        SalaryStructure structure = headOfDepartment.getSalaryStructure();
		}
	…
	…
}

If you notice, in this case, the UserDepartment has a 1 to 0..1 relationship with the User.

In this simplistic code you would see that we check for user being not null and then on the basis of that do some useful work. Having this null check at one or two places is not an issue. However, it becomes an issue when you need to have this check at several places. This checking for null is a subtle form of code duplication which you should like to avoid. Such a duplication works against simple changes, such as fixes or improvements, and is in violation of the DRY principle.

How do we avoid this?

Wouldn’t it be easy if the code could read like


public void upgradeTheDepartment(UserDepartment department){
	User headOfDepartment = getHeadOfDepartment(department);
        SalaryStructure structure = headOfDepartment.getSalaryStructure();
	…
	…
}

Well, at least it looks easy to read without the null check everytime. But wouldn’t this code throw a NPE when the headOfDepartment does not exist.

Introduce the Null Object.

Provide something for nothing: A class that conforms to the interface required of the object reference, implementing all of its methods to do nothing or to return suitable default values. So in our case, we would create a Null User for head of department and always assign it to the department. Hence, whenever the department is created it would have code like this


public class UserDepartment
{
        public UserDepartment()
        {
                this.setHeadOfDepartment(new NullUser());
        }

Introducing a NULL OBJECT simplifies the client’s code by eliminating superfluous and repeated conditionals that are not part of a method’s core logic. Selection and variation are expressed through polymorphism and inheritance rather than procedural condition testing.

Ideally, you would like to introduce the Null Object as an implementation of the interface so that the variation can be easily expressed through polymorphism. In our example with the NullUser headOfDepartment, a call to the salary structure would return a blank salary structure.

The object relationship moves from being optional to mandatory, making the use of the relationship more uniform. If you notice that with implementation, there exists a mandatory relationship between the UserDepartment and User Objects.

Hence remember,

IF an object reference could potentially be null and this reference must be checked before every use and the result of a null check is to do nothing or assign a suitable default value THEN it is better to provide a class derived from the object reference’s type and implement all its methods to do nothing or provide default results and use an instance of this class whenever the object reference would have been null. This would not only help in removing the superfluous Null Checks but would also keep you away from the ever-increasing NPEs.

We write clean code. Even though we might be focussed on complex Enterprise Java and Cloud Computing, Inphina truly believes that great software is simple and clean.

Advertisements
Posted in: Agile, Architecture, Java