Code Smells 4 – Primitive Obsession

Primitive Obsession is the act of passing around primitive values (ints, strings etc.) in your application, rather than a domain specific object. This makes your code less understandable as it removes some of the domain context. Object Oriented Design is about mapping domain concepts to objects. By allowing domain concepts to slip through as these general types, we sacrifice some of our expressivity without gaining anything in return.

Why is Primitive Obsession a bad thing?

Primitive Obsession is a bad thing for a number of reasons:

1. Representation and Expressivity

My age can be represented as an int. My current bank balance can be represented as a double. My postcode can be represented as a String. Are they an int/double/string? No. Does an int have any concept of “Legal drinking age”, or a String any concept of an invalid postcode format? No. Whilst these primitives are a nice, simple representation of a domain concept, they are not a domain object and cannot function as such.

2. Violation of Single Responsibility Principle

An object should do one thing and do it well.

Say I want to determine whether a postcode is valid. I may implement a method somewhere as follows:

public static boolean isValid( String postcode ) {
  ..
}

However, whatever class this goes in, it is almost certainly not this class’ responsibility to determine if a postcode is valid. However, by defining a Postcode class as follows:

public class Postcode {

  private String postcode;

  public boolean isValid( ) {
    ..
  }

}

we keep this method correctly within the object that is responsible for postcodes, upholding the Single Responsibility Principle.

3. Lack of extensibility

Say we want to add processing to our application regarding ages. With an int, you can’t add an isLegalDrinkingAge() method if you decide you need it later. Sure, you can add calculations all over your application, and then you end up in a horrible mess of duplication and dead code.

Wouldn’t it be much nicer to have one, single location to determine all the functionality related to ages? So stop using an int, and start using an Age!

4. No Inheritance Relationships

UK Postcode and US Zipcode are both mail sorting codes. They have different precisions, but share many similar traits (Both need to determine if their current state is “valid”, for example).

Representing both as strings means we need an isValidUS and an isValidUK method. Using classes and inheritance, we can use a standard MailSortCode interface and stop worrying about exactly what type of code we’re trying to represent

So why don’t we use them all the time?

Mostly, because it feels silly. An Age is an int is an Age right? If we say so, then its true. Given that assumption, it seems ridiculous to write:

public class Age {

  int value;

  public Age( int value ) {
    this.value = value;
  }

  public int getValue() {
    return this.value;
  }

}

instead of:

int age;

However, considering the issues with expressivity, extendability and inheritance above, planning ahead like this may save you a lot of headaches in the long run!

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s