“He’s perhaps one of two dozen people who knows the name of Iron.”Kvothe, Name of the Wind, The Kingkiller Chronicles
Names have power. Patrick Rothfuss adeptly harnesses this truth in his excellent novel series The Kingkiller Chronicles. In the word of Temerant, knowing the true name of an element such an Iron or Wind gives someone supernatural control of it.
The power of names is demonstrated through a simple photograph of place signs. Each of the words on the wall above conjures a feeling of excitement, or curiosity, or perhaps a distant memory, fleeting and poignant.
What we choose to call events, concepts and people measurably changes our view of them. The names we given ourselves quietly in our hearts have enormous influence over our mental state.
Astonishingly, recent research has discovered that we even look like our given names. Researchers have shown that people and computers can infer our name by looking at our face, an effect demonstrable beyond socioeconomic cues. Therefore, our facial appearance represents social expectations of how a person with a specific name should look.
The importance of naming for clean code
This a significant realisation for our mental health and well-being, but how does it fit with delivering clean code faster?
Names communicate. They have the power to tell others what a thing is and does. That reduces friction in our development teams, and allows us to understand code faster and deliver more quickly.
Why should we expend so much effort to get them right? Because the name of a concept gives us insight into how it fits into the system we are designing. Conversely, if we’re not careful with naming, we’ll be producing write-only code which drifts apart from the whole, lost and destined for eventual deletion.
Here are some principles you can use to help you choose the best names and produce clean code with less effort. We’ll start with the nuts and bolt of naming code, then move to how to determine meaningful names in conjunction with our customers.
Intentionally move through the four stages of naming
There are two hard problems in computer science: Cache invalidation, naming things, and off by one errors.”Martin Fowler
How should we pay attention to names as we get started with coding something new? J.B. Rainsberger talks about names of classes, methods and variables going through four stages towards clean code:
- Nonsense: For example, we might extract a method from a larger one and quickly rename it
somethingWhatever()to get the refactor done and the tests passing.
- Accurate: We rename the nonsense method to what it actually does, such as
- Precise: Once we realise what the method really does, we might refine the accurate name and give it more precision, such as
- Meaningful: At this point, we’ve revealed the complexity of the method, and can look to split it up into two methods:
forEachEmployee()and perhaps a
payWages()method on a separate interface.
Don’t be afraid of nonsense or longer names
We shouldn’t shy away from the early stages of naming. If we’re not sure what something is yet, give it a nonsense name. The name
foo() is fine, as long as it’s only going to last fifteen minutes.
It doesn’t belong in a commit, and it’s not clean code, but it’s a start. It gets our code moving so we can begin to see how our concepts fit together.
As you progress, some concepts or ideas will outgrow your abstractions. They become ripe for future refactoring. If in doubt as to what or where something fits, use a long name: the longer and more precise the better. I will call a variable something like
computed_unsorted_project_task_matrix if I don’t like it and want to refactor it at some point.
This is much more intention revealing than
r). I reveal the complexity of the object through the name, which helps reveal complexity in the code.
Characters are cheap
Let’s not make things harder for the programmers who come after us. Remember, this is just as likely to be ourselves in a few months. Let’s avoid using a name like
project is only a few characters more.
Anything that reduces reading friction in our code is a good thing.
This isn’t fashionable amongst developers in certain languages communities like Clojure or Haskell. They prefer brevity in variable names, relying on convention for understanding. For example,
v often refer to
value in a Clojure Map.
The important thing is to reduce friction in the team. If your team are used to these variables, it’ll be quick to understand: for them, it’ll be clean code. However, this will increase the barrier to other team members. In general I prefer longer more meaningful names to this. I don’t think it’s worth sacrificing the team’s understanding for the sake of a few characters. If names are becoming so cumbersome their length is reducing clarity, this shows the need for a refactor.
Name concepts for your customer, not yourself
Along the steps we take through to making names more precise and meaningful, how do we choose what words to use for the concepts we’re dealing with? We name these concepts through continual conversations with customers.
Ubiquitous language is an excellent concept and tool that Eric Evans introduced years ago in the book Domain Driven Design. Every coder would do well to read at least the first half of this book. The idea is often taught within a Behaviour Driven Development context, but it is logically independent. Any agile team can work towards a Ubiquitous Language.
The central idea is that there are two languages that we can use to talk about a concept: the “problem” language or the “solution” language. The problem language is the language of the customer. For example, a payroll system might use concepts like wages, salary, PAYE, tax, paying. The solution language is the language of developmers. For example we might use the following names for the code that runs the payroll system: button, element, value, collection, style, parent-child, container, object.
The solution language is where many programmers naturally live, think and speak. It’s easy for us to operate with these kinds of concepts. The trouble is, they’re often alien for our customer. Instead of lazily reaching for
child (or the more problematic
slave vernacular) when describing a concept, let’s instead collaborate with our customers on a shared language that works well for everyone. Perhaps we add an employee to a tax band rather than insert a user into a collection, both when discussing the next feature, and when we’re writing the code itself.
Intentional conversations reduce confusion and produce clean code
It’s common for teams to have to deal with concepts and words that overlap and interact with each other. Single concepts are called different things by different people on the team. Different groups of people within an organisation use the same word for wholly different ideas.
It’s such a universal problem people often don’t pay attention to it. However confusion and cognitive load will build up and cause communication problems over time.
It’s also fairly easy to solve this problem through having quick, regular, intentional conversations.
Next time you’re discussing a concept with your team that’s poorly named, speak up. Ask whether there’s another name for the concept that could reduce confusion. Try a few different words or phrases out with the team until you settle on the right thing. This might mean inventing entirely new words or concepts that fit well with everyone in the team. That’s ok, as long as it makes our language more precise.
Once a word has been decided on, commit to using it everywhere from now on. Deliberately take the time to update the names in the code to match.
Perhaps you could volunteer to maintain a glossary of words so that everyone feels the benefit. Newer team members are often great people to keep an eye on these documents, and update them whenever they encounter errors.
There’s always going to be a barrier for incoming team members new to our code and our concepts. If we’re having these intentional conversations, we’re helping newer people by creating a smaller set of names for them to learn.
Names have power. They can drive insight and influence communication. Let’s intentionally practice our naming as a team, so that everyone has a say about the language and terminology we use. Let’s build those names right into our codebases, moving through the stages towards the team’s language as the code becomes clearer. This will harmonise the team’s work, make for cleaner code, and puts the team on the right track to improving their delivery times.