Primitive Obsession Example # 1 – KeyValuePair

My last post described how removing cases of “Primitive Obsession” is one of the best ways to improve the readability of your code. Replacing primitives with domain specific types helps reveal the intention of the code, which helps others to read, maintain, and use the code we write.

This post will be the first in a series of examples illustrating the primitive obsession code smell. In each post, I will provide a “before” code sample where primitives are used, and then an “after” sample, where the usage of a primitive type is replaced with a domain specific type.

The first example will illustrate using a .NET built-in type, the KeyValuePair.

Disclaimer # 1: It is perfectly acceptable and appropriate to use this type in some cases. However, the type is often overused and can make code less readable. My intention with this post is for you to compare the “before” and “after” versions to see which approach is more readable for your situation.

Now, on to our example…

“Before”- code using the built-in generic type, KeyValuePair<TKey, TValue>:

class Program
{
    static void Main()
    {
        var list = new List<KeyValuePair>();

        list.Add(new KeyValuePair("Chris Melinn", "FAKE123"));
        list.Add(new KeyValuePair("Lisa Simpson", "ABC456"));
        list.Add(new KeyValuePair("Waylan Smithers", "XYZ789"));

        // Outputs (as strings):
        // Chris Melinn, 'FAKE123'
        // Lisa Simpson, 'ABC456'
        // Waylan Smithers, 'XYZ789'
        foreach (var item in list)
        {
            var message = string.Format("{0} , '{1}'",
                        item.Key,
                        item.Value);

            Console.WriteLine(message);
        }
    }
}

Even in this simple example, it can be hard to tell what data is captured by the List of KeyValuePairs. Each KeyValuePair contains a Key of type string, and a Value also of type string. In a real application, hopefully, we would also have better variable names to help us determine what these objects contain. However, in this case, I have intentionally left generic variable names (such as item and list) to highlight the loss of meaning by using the primitive type.

After inspecting the data values in the sample, we could probably guess that our Key’s are people’s names. However, we might not be able to guess what our Value’s hold.


This example will assume that our code intends to print out the company’s computer inventory, with a list of machines issued to various staff members. In other words, in our example, the Key is the employee name and the Value is the machine serial number. Unfortunately, the primitive type does not capture that information. However, we will see this is easy information to convey when we refactor to a domain specific type.


Also, notice that, in this example, our type is created and used within the same block of code. In a real application, it is much more likely that another class would create the list (e.g. by reading from a database), and then return the values it to seperate class to consume the data.  In such a case, we would only see an interface or method such as:

public List<KeyValuePair<string, string>> GetEmployeeMachines()

Even with a well-named method, the developer will probably need to navigate to the class and method and view the source code (if possible) to confirm that the keys and values are what she expects them to be (not to mention, code signatures like these are fairly ugly and unpleasant).

Now, let’s refactor our original sample to remove the primitive KeyValuePair type and replace it with a domain-specific type. It would look something like the following (affected/modified lines are highlighted):

“After”- KeyValuePair<TKey, TValue> replaced with a domain specific type, EmployeeMachine:

class Program
{
    static void Main()
    {
        var list = new List();

        list.Add(new EmployeeMachine("Chris Melinn", "FAKE123"));
        list.Add(new EmployeeMachine("Lisa Simpson", "ABC456"));
        list.Add(new EmployeeMachine("Waylan Smithers", "XYZ789"));

        // Outputs (as strings):
        // Chris Melinn, 'FAKE123'
        // Lisa Simpson, 'ABC456'
        // Waylan Smithers, 'XYZ789'
        foreach (var item in list)
        {
            var message = string.Format("{0} , '{1}'",
                        item.EmployeeName,
                        item.MachineSerialNumber);

             Console.WriteLine(message);
        }
    }
}

class EmployeeMachine
{
    public string EmployeeName { get; private set; }
    public string MachineSerialNumber { get; private set; }

    public EmployeeMachine(string employeeName, 
                           string machineSerialNumber)
    {
        EmployeeName = employeeName;
        MachineSerialNumber = machineSerialNumber;
    }
}

The final result is more intention revealing and better conveys what data is captured in the EmployeeMachine class. Even with other generic, poorly named variables still left in the code (such as item and list), the reader can still understand what the code is doing without navigating and inspecting other classes.

Most importantly, I believe this refactoring is one of the easy “little things” you can do to increase the satisfaction of others who read, maintain, and use your code.


As always, I would love to hear from readers — especially if you have any personal experiences (or even code examples!) to share.

About these ads

One thought on “Primitive Obsession Example # 1 – KeyValuePair

  1. You might as well ditch the properties and use public, immutable fields instead, since this is to replace a simple key/value pair or tuple.

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