What is the Point?
The point of good naming is not “to have good naming.”
Nor is it “to have followed the rules.”
Nor is it “standardisation.”
When people reduce the art of naming to rule-following and source-quoting, they have lost the point of this whole exercise.
Arguing Against Naming Skill
You and I can express the same programming concept in dozens of different ways, even inside a single programming language. Some ways are more efficient, more obvious, more elegant, more robust, or more pleasing than others.
All those ways will work.
Occasionally, specific names may be required by a framework that works via reflection to find specially named members or functions. Then we have to comply in order for our software to work.
In other cases, names don’t matter to the underlying technology.
1 def a8f4e2c1(b7d9c3a5: int) -> List[str]:
2 e2b6f9d4: List[str] = []
3 for c1e4a8b7 in range(1, b7d9c3a5 + 1):
4 if c1e4a8b7 % 15 == 0:
5 e2b6f9d4.append("FizzBuzz")
6 elif c1e4a8b7 % 3 == 0:
7 e2b6f9d4.append("Fizz")
8 elif c1e4a8b7 % 5 == 0:
9 e2b6f9d4.append("Buzz")
10 else:
11 e2b6f9d4.append(str(c1e4a8b7))
12 return e2b6f9d4
The compiler doesn’t care.
So why bother choosing “good names?”
LLMs don’t care
Perhaps you are generating more of your code with LLMs or other coding assistants, and they also don’t care about the names.
When I have code generated for me, the variable names are not what we would consider exemplary. Instead, we get very long and complicated functions with short and cryptic names and lots of comments between steps of an algorithm.
Often these are largely untestable as given.
They also tend to make poor use of existing functions from the standard library and even our own utility functions are ignored (not part of the context).
But the code works. If that’s all that matters, then why bother having good names?
It certainly can seem like a self-satisfying, pointless ritual and a needless concession from a certain point of view.
Does it Actually Matter?
If all practices are equally effective, the only reasonable standard is to use personal preference. If all code will only be read, debugged, tested, and used by compilers then names don’t really matter.
But that’s not how it plays out.
We can’t trust our code generators. We certainly should use them, and use them to our advantage, but we need to examine their output to ensure that they are doing the right things, and only the right things.
For that matter, the same is true of many of our developers. Face it, people do things in the worst ways when their entire focus is just getting it off their plates.
But what about when something unexpectedly goes wrong in the middle of the night? Can you find and fix the problem?
Who takes responsiblity for the quality of the program and for its continuing operability? Does the LLM come with guarantees? Does the programmer who likes to delete vowels and add digits to the ends of filenames want to come and puzzle the meaning of the code for you?
You need source code that works for people who live in the codebase.
There is an engineering concept:
How we do our work makes a difference.
We think that the way to get a better result is to do the work differently.
Good naming in source code is essential for rapid comprehension, maintainability, and software quality.
- Well-chosen word identifiers improve speed to find defects (by nearly 20%)
- Descriptive identifiers speed accurate source code comprehension.
- Where good naming is used, less documentation is necessary (including comments)
- Poor identifiers are associated with low-quality code (although this may be a tautology, since poor naming is flagged by lint tools as poor code).
Since it does make a difference, we need to understand why and how.
Features of Good Names
Humans read, write, debug, and review code. Even when some AI is used to help generate the code, it’s humans who are held accountable. The AI can’t take responsibility for programs.
Benner’s Principles
Tom Benner wrote a pragmatic and helpful book called “Naming Things: The Hardest problem in software engineering.”[^naming]
I recommend this book for further reading, and I will present some nuance here that isn’t present in that volume.
[^naming]: add isbn and such here
Benner gives us four criteria that are crucial, which I will paraphrase slightly for our purposes:
- Understandability: The name is known, or needs to be known, by the reader to describe the concept it represents.
- Conciseness: The name has as few words as possible without sacrificing understandability.
- Consistency: Names are used and formatted consistently.
- Distinguishability: Each name stands out as different from the names around it.
There is nothing wrong with any of these suggestions. They are well-explained and the examples are great.
I will lean more on relational, hierarchical, and incremental aspects, hopefully without conflicting with either my work in Clean Code, or Tom Benner’s work in Naming.
Who Cares?
Note that in the earlier example with random names, the compiler had no problem with these words.
Each term is equally distinguishable to the machine, even if the name is 1000 characters long and only has one bit of difference from another name. Understandability is beyond the purview of compilers. Consistency and conciseness are not involved in the generation of machine code.
All of these qualities affect only humans.
The reason for having a “good” name is that it speeds humans in their work.
- We want people to find the code they need to change, and find it quickly.
- We don’t want them to make errors due to misunderstanding the code.
- We don’t want to spend a lot of time explaining the code.
Who cares? Everyone who will be tasked with understanding this code, whether to extend its functionality, correct a flaw, or improve its performance, cares.
You care.
And it’s up to you to care for others.
And now, the question is. “which others am I to consider, and how?”