Hey Fred, Can You Pass Me the HashMap

Kirk Pepperdine
97 Things
Published in
3 min readNov 22, 2019

Picture the scene, an old cramped office with several old wooden desks set back to back. Each desk equipped with an old black rotary phone and ashtrays dotted about. On one of the desks is a black HashMap that contains an ArrayList filled with customer data. Sam, needing to contact Acme Inc, scans the office looking for the HashMap. Eyes darting, he spots the HashMap and shouts out, hey Fred, can you please pass me the HashMap. Can you picture that… yup, I didn’t think so…

An important part of writing a program is the development of a vocabulary. Each word in that vocabulary should be an expression of something that is part of the domain we’re modeling. After all, it is this code expression of our model that others will have to read and understand. Consequently, our choice of vocabulary can either help or hinder one’s understanding of our code. Oddly enough the choice of vocabulary impacts much more than readability: the words we use affect how we think about the problem at hand, which, in turn, impacts the structure of our code, our choice of algorithms, how we shape our APIs, how well the system will fit purpose, how easy it is to be maintained and extended, and, finally, how well it will perform. Yes, the vocabulary we develop when writing code matters a lot. So much so that keeping a dictionary at hand can be, strangely, useful when writing code.

Returning to the ridiculous example, of course, no one would ask for the HashMap. We’d most likely draw a blank stare from Fred if you asked him to pass the HashMap. Yet when we look at how to model the domain, we hear about the need to lookup customer contact data that is organized by name. That screams HashMap. If we dig deeper into the domain then we’ll likely discover that the contact information is written on an index card that is neatly packed away in a Rolodex. Replacing the word HashMap with the word Rolodex not only offers a better abstraction in our code, it will have an immediate impact on how we think about the problem at hand and it offers a better way to express our thoughts to the reader of our code.

The take away here is that technical classes rarely have a place in the vocabulary of the domains we’re working in. Instead what they offer are building blocks for deeper more meaningful abstractions. The need for utility classes should be a red flag that you’re missing an abstraction. Additionally, technical classes in APIs should also be a red flag.

For example, consider the case where a method signature takes a String to represent a first name and a String for a last name. These are used to lookup data held in a HashMap:

return listOfNames.get(firstName + lastName);

The question is, what is the missing abstraction? Having two fields forming a key is commonly known as a composite key. Using this abstraction we get:

return listOfNames.get(new CompositeKey(firstName, lastName));

When you make this change in a benchmark, the code runs three times faster. I would argue it is also more expressive: Using CompositeKey better expresses the essence of the problem at hand.

--

--