There are only two hard things in computer science: cache invalidation, naming things, and off-by-one errors. –Tantek Çelik (& Phil Karlton)
When learning how to write software, one of the early lessons is to give your code elements (variables, classes and methods) good names. This seems simple enough, but it’s actually a vital skill that ties together everything we know about writing software. Naming things is challenging, and I’ll explain why.
Humans write software to solve problems in the real world, and this involves reasoning and understanding. Because problems are not limited to the individual, understanding must be shared between people. This is accomplished through communication and collaboration.
Ultimately though, to implement the solution in software, it must be communicated to an unthinking entity. The computer will follow the instructions you have explicitly stated for it to the letter (well, to the byte).
Because they are unthinking, much of our communication with computers relies on syntax. The computer doesn’t care about the meaning of what we express, just that we have expressed it in a syntactically correct way. Code may be syntactically correct and compile without any issues, but at the same time may be logically incorrect. In this case, the computer can tell you that your code is syntactically correct, but it cannot tell you that it is doesn't solve the problem because it doesn’t understand what the problem is.
Names are an element’s semantic representation.
When pair-programming, there is a rich exchange of ideas between the partners. They can keep each other in check syntactically (‘hey, you forgot the end statement’) or semantically (‘What is this method supposed to be doing?’). When writing code by yourself, that exchange doesn’t occur. It’s sometimes easy to get lost in the syntax and lose the semantic meaning of what you write.
One of the vital ways that programmers communicate through code (that is, not side-by-side) is by giving variables, classes and methods good names. By assigning a programming element a name, you are essentially tying it to the solution space. You are declaring it to be representative as a piece of the solution. When other programmers see that element, its name is their first introduction to what it is supposed to represent. If an element has name that doesn’t quite match what it actually is or does within the software system, this can lead to confusion, and ultimately higher maintenance costs. Programmers that maintain the solution down the track (remember, this includes future you) will have to spend extra brain cycles to mentally map what the element actually is, and its name.
Name smell: Just for now
Because the computer doesn’t care about the semantic value of names, you can get away with writing code that is syntactically correct but semantically meaningless. You can call your element some temporary name ‘just for now’ (be it ‘x’ or “method_that_does_some_thing_and_some_other_thing’) and forget about it. It’s easy to forget that down the line, someone else will have to understand your approach from the perspective of solving the problem and derive for themselves what the ‘x’ actually represents in your solution!
Naming a code element allows us to solidify our understanding of that element.
At its core, all programming is problem solving. Software developers take a problem in the real world and analyse it by breaking it down into subparts that they can understand. The solution we then design must be based on that analysis. Maintenance involves ensuring that the resulting software continues to model the problem correctly, even when the problem changes. If developers don’t understand the business problem correctly, then the design will be wrong from the outset.
Incorrect or vague names can cause issues even in trivial applications. When people first start programming, they are told to give their variables good names. When a programmer has an application in which variables are named ‘a’, ‘b’ or some other arbitrary name, this can cause them become stuck, even if the application is trivial. By reviewing their code and renaming their variables to ones that accurately communicate their original intent, it more often than not clears up a lot of issues.
If, as humans, we understand code as a syntax-only construct - that is, we derive our design from syntax - it sets us up for the pitfalls associated with ad-hoc design.
Name Smell: Supplementary comments
If you have to use comments to further describe what an element does, rename it.
Correctly naming design elements helps to ensure single responsibility.
When we design a system, we build on layers of abstraction. A class has methods that perform certain functions, but to build a system that conforms to OO best practices, we try to ensure that each class has only one responsibility. And when we understand what that responsibility is, we can apply a name that makes sense.
Name smell: Trouble naming. One could go as far as to say that if you have trouble naming a class, you haven’t determined what it’s supposed to be doing. That might indicate a problem with the analysis, meaning you as the developer have not developed sufficient understanding of the problem and therefore more analysis is required.
On the other hand, a naming problem could indicate that a class or method is doing too much. If you can’t think of a single, concise name for what the class is supposed to represent or what a method is supposed to do, it may indicate that you should split it up.
Naming is an abstraction mechanism.
When we give a name to a code element, it is a fundamental step to communicating to other humans what that entity is supposed to be, or what it is supposed to do (and by the way, ‘other humans’ includes you in the future, trying to reacquaint yourself with the code after days, weeks or months of not looking at it).
When developers in other parts of the system call that method, the name becomes the semantic anchor by which the author of that code can understand to the class or method in question without needing to understand how the code works. If a method name does not reflect what the method does, then other developers calling that method will be faced with broken code, because the method name was an incorrect description of its function. Names should describe what the code or method does, not how it does it.
Name smell: If your name describes how the element works, rename it. A method ‘use_pythagorean_theorem’ should really be named ‘calculate_hypotenuse’.
Naming is hard.
It’s not just you. Coming up with a good name for a field, method or class combines all the skills that a software developer needs to write good object-oriented code, including communication of ideas and analysis of the problem. By focusing on each element and ensuring the name accurately describes its function within the system, we can design better systems. But it’s hard - even with a thesaurus - because naming involves all of the semantic skills associated with software design - analysis of the problem, design of a solution, and communication of semantic intent.
Even though we write code to be interpreted and executed by computers, it through the semantics of that code that we communicate our intentions to other humans. In other words, we give the computer instructions using syntax, and we make sure we are giving computers the right orders using semantics. We communicate not only what the computer is supposed to do, but the original intent behind those instructions.
Thus, it is humans who must be the bridge the gap between syntax and semantics - they read and understand code semantically. Thus, we must consider how the elements in the software - fields, methods, and classes - fit together as design elements to solve the problem. How these elements are named is vital to this semantic understanding by both the developer of the system and other developers interacting with that system.
– Charlie Ablett