Some of you may own copies of “Clean Code” and may be aware that I wrote Chapter 2, Meaningful Names (at least most of it).
This was based on a naming rules paper that I wrote many years earlier, with vetting from who-knows-how-many people on Usenet’s comp.object in the 90s.
There is an historical version of that paper available online, and also a revision I made when incubating AgileInAFlash, which is still available as a pdf from Pragmatic Programmers.
That book was published in 2008. Neither the world nor my brain stopped working in 2008. So with these intervening years and lessons learned, what changed?
By the way, Tom Benner wrote an entire book on naming things. I had nothing to do with it but it seems much more extensive than my little chapter, so you may want to pick up a copy of Naming Things and see for yourself.
First let’s get the big question out of the way:
Was I Wrong?
I don’t think I was wrong.
The recommendations there are all pretty good advice, and fairly “soft” so they’re easy to adopt and use, but may produce different results in practice.
Here I will fill in some of the blanks and voids from that chapter.
Chapter 2 Outline of Suggestions
- Use Intention-Revealing Names
- Avoid Disinformation
- Make Meaningful Distinctions
- Use Pronounceable Names
- Use Searchable Names
- Avoid Encoding
- Avoid Mental Mapping
- Class names are Nouns
- Method names are Verbs
- Don't Be Cute
- Choose One Word Per Concept
- Don't Pun
- Use Solution Domain Names
- Use Problem Domain Names
- Add Meaningful Context
- Don't Add Gratuitous Context
The Changes
Experience brings nuance, nuance changes understanding, and understanding changes approach.
There have been only a few profound changes since 2008.
- Recognizing Objective and Subjective Elements of Readability
- Naming as a Social Art
- Naming as a Process
Recognize Objective and Subjective Elements of Readability
We have always known code isn’t automatically and unavoidably readable. Writing readable code takes skill.
When we said “the code is the documentation,” we expected people to understand “if it is written to be so.”
If people learn to use their programming language well, they make use common terms, idioms, algorithms, and standard library functions to inform people who know the same things.
Some elements of code readability are objective, and others are somewhat subjective. I’ve attempted to catalog these in the blog post “7 Code Virtues Explained.”
Sometimes code involves complicated equations and procedures that cannot be written in a way that is obvious and clear. In those cases, we must provide additional context for the reader. We do that with naming where possible.
Naming and commenting both serve the same function: providing context to the reader.
Eddie Bush, agile coach, said that naming is our most powerful tool:
We get to choose what to name (an expression, value, or code block) and what to call it.
We will see in my chapter that the expression:
is named by extracting it to a method on the cell class and naming it:
This goes one step beyond “renaming” into class ands interface design.
How does this change what I wrote in the book?
- We need more focus on the objective elements of readability. My minesweeper example showed how naming could impart readability improvements without actually changing the objective features of the code, but it leaves the false expectation that naming is always sufficient alone.
- The final minesweeper example in my chapter converted the for-each loop to a list comprehension, which simplified the code and made some prior naming changes unnecessary. This interplay of structure and naming was not called out and was subsequently lost in translation to Java.
- I regret not mentioning extracting code to variables or methods so that they can go from unnamed blocks of code to named blocks of code.
Naming As A Social Art
We used to think that a smart programmer should be able to imbue their code with readability, that this was an individual skill.
We were at least partly wrong. Readability isn’t a property solely of the code, nor merely a skill of the developer. Readability is a quality of the relationships between the code artifact and its audience.
The author is one member of the artifact’s audience. The compiler is one other member of the audience. In our side-projects and solo school assignments, that’s the whole audience. We can make ourselves happy with the code and that is good enough.
This is not so when we share a codebase with other people.
Everyone who visits the codebase is part of our audience. The current author and the compiler are now maybe 1/20th or 1/50th of the audience. Our self-satisfying approach must change.
In a “code, then review” process, the audience may not see our work for days or weeks. This puts the author at a disadvantage.
When programmers work alone, they constantly evaluate the code they’re writing. When they later receive stylistic feedback it feels like an imposition and an interruption. They can be resentful of the reviewer’s criticism, even when the style guidelines were clearly presented in a style guide.
This is because when the programmer worked on the code alone, the code seemed personal. A critique of the code feels like an attack on the author, and may have even been expressed as such.
Class, method, and variable names must inform us personally but also must evoke the right ideas in the minds of our colleagues. If our colleagues are not present when the code is composed, we can’t accurately gauge their needs. We do what we think/hope is right, pleasing to the author rather than the audience.
Writing code is like writing any other prose. If we reach and please our audience then we succeed. If we fail to communicate to our audience, then the product does not fulfill its purpose.
One alternative is to co-create the code with a sample of our audience. Then the code isn’t personal, and suggestions to change are timely.The code that is written is a product of the group and does not feel so much like personal property.
Not only can I change my code to match my peers’ understanding, but I can also use my code to educate peers on the best use of language and library features. I want to be clear that the answer isn’t to “dumb down” the code, but to make it the clearest example of using modern language features well. Reading code should be profitable, not needlessly painful.
How does that change what I wrote in Clean Code?
- I would have given more space to the idea of ubiquitous language when discussing intention-revealing names.
- I would have insisted that individuals involve their peers in the process
- I might have shortened the list, as merely involving more of your audience in code-writing would have made 9 or 10 of those suggestions unnecessary.
The place to focus on improving the quality of names is during the initial code-writing session, using the opinions of your peers to spot confusing passages and suggest improvements.
Naming As A Process
I apologize for the idea that a developer in isolation can pluck a name out of thin air that meets all the criteria for meaningful names.
Naming is notoriously hard.
I have an infamous method of progressive naming where the programmer, unable to conceive a good enough name, uses a particularly poor name, a nonsense name that will motivate you to change it ASAP.
I think it helps for the nonsense name to be something embarrassing so you want to eradicate it from the codebase as soon as possible. It is helpful if it is easy to search for, so you may easily locate its usage. If you are consistent with the bad name you can find all the bad names at once with “Find in Files.”
Some notable work has been done on processes for evolving better names in uncertain circumstances.
- JB Rainsberger published a model for improving names
- Arlo Belshee recommends naming as a process
- Feitelson, et al, have a study and 3-step recommendation on how
to choose names
which essentially boils down to
- Select the concepts to include in the name
- Choose the words that communicate these concepts
- Create a name from these words
- Arlo, again, promoted the idea of Read By Refactor, which also supports refining names progressively.
Sometimes a great name just occurs to us, sometimes a great name is obvious, and sometimes it takes a continuing process to gradually improve the name from the best we could do at the moment of coding to something universally acceptable.
Difficulty devising a good name is not always a failing of the writer’s imagination. It is frequently an indication that the code itself is not clearly and crisply designed.
The changes:
- Help readers deal with “unnameable” operations and classes by refactoring
- I would describe a process of successively refining names and refer to existing techniques
- Rather than focus on qualities of good names, I might focus more time on making code nameable
Anything else?
A few little things only.
Horizontal Scrolling
The advantage of putting an expression on one line is that you can take it in at a glance.
If you have to scroll horizontally, it’s not only more work than vertical scrolling, but you can’t see the beginning and the end of an expression at the same time.
Excessively long names tend to cause a lot of horizontal scrolling. That’s inconvenient.
For one-line expressions, any inline names might be especially short. This is okay when the variable winks into and out of existence in a single code expression.
Of course, you must check with your code’s audience to see how others feel about it.
Noun-Verb
It is still good to make a class name a noun, and to name member functions with verbs. Not everything is a member function, though.
For pure functions, there is a functional programming idiom of naming the function after the result it produces. It is a good idiom for many audiences. You might want to use it for some member functions sometimes, too.
Also, I really wish I’d let you know about harmonizing names. Naming methods or variables in isolation can produce confusing classes. If you list the method names in a class, they should agree and even look like they belong together.
Autocomplete
Autocomplete is a big productivity booster if we use it well. It seldom pays to fight your tools, so try to use names that help you find the function you need without scrolling through a list of methods that aren’t interesting.
One of the places I feel this is in properties that have set and get methods. For a long time, you would see all the setters listed together at the bottom of the list of methods, and all the getters listed together at the top.
I seldom want to type ‘get’ and see all the things I can get. I’m more likely to have a subject in mind, and want to see all the methods available with that subject in the function name or in the parameter list.
Autocomplete systems have gotten more competent over time, but if you find your tools aren’t making your job easier, you may need to adjust your local standards to cooperate with the tools for everyone’s sake.
You are my audience…
We are leaving comments open so you can help me to reach you better. What would you have said differently, and what mistakes or omissions would you have called out?