Don’t forget about value objects!

The other day I came across some code that looks something like this (class names changed to hide and the code simplified to protect the privacy of the developer 🙂 ):

public class Person {

  private String name;
  private String phoneNumber;
  ...
}
public class PhoneNumberUtil {

  public static String areaCode(String phoneNumber) {
    return phoneNumber.substring(0, 3);
  }
}

This code suffers from the code smell known as Primitive Obsession. Primitive obsession occurs when a primitive type is used to represent a domain concept. In this example, names and phone numbers, which are  important domain concepts, are represented strings. Whats more, the areaCode() method is implemented as a static method in a separate class, which is not particularly object-oriented.

While the code works, too much primitive obsession will seriously impact maintainability. There is no proper type checking. You could, for example, pass the phone number instead of a name. Another problem is that behavior, such as the areaCode() method, is no longer associated with the state, which results in procedural-style code.

The solution is to implement the name and phone number concepts with Value Objects. A value object, which is an idea from Domain-Driven Design, is a class that does not have an identity. Instead, it is simply a collection of values. Two value objects are equal and can be used interchangeably when their corresponding values are equal. Using value objects makes domain concepts explicit. It also provides a place to define methods for operating on those concepts.

Here is the code after applying the Replace Data Value with Object refactoring:

public class Person {

  private Name name;
  private PhoneNumber phoneNumber;
  ...
}
public class PhoneNumber {

 private String pn;

 public String getAreaCode() {
    return pn.substring(0, 3);
 }

 public boolean equals(Object o) { ... }

 public int hashCode() { ... }

...
}

In this new and improved code, the phone number concept is explicitly represented by a PhoneNumber value object class. Not only do we now have type checking but the area code behavior is now where it belongs: a getAreaCode() method in the PhoneNumber class.

Here is a presentation from 8 years ago that talks about eliminating code smells 🙂 .

 

This entry was posted in coding and tagged , , , . Bookmark the permalink.

1 Response to Don’t forget about value objects!

  1. Prasanna Bhat says:

    Good one. Indeed a nice practice

Leave a comment