This week’s meeting of the BSC had lots of potential for discussion, debate, and religious crusades — the topic of discussion was naming.
Naming things is an important part of a programmer’s daily life. He creates a new variable, function, module, script, file, or other tool literally every few minutes. And they all need a name.
A programmer’s life is acted out in text. Everything we produce is text. We use text because both the computer and the humans can be made to understand it. But we name things because humans need more information about the program than the computer does. In fact, what a name encodes is meta-information. It is information about the program itself, which is lost at compilation time. One doesn’t need this information to run the code. One only needs this information to edit the code. Thus it is extra information that humans need, because their job is to edit the code, not run it. So naming is very crucial for us, and is more than a trivial study.
There. Now that I’ve had the chance to philosophize about it, what follows is an assorted collection of the things we had to say about naming.
When naming unit tests, omit the word “test.” It’s redundant. It’s a relic from old testing frameworks that is no longer needed. It’s already clear that it’s a test. You can also omit the name of the method you’re testing — it bears no real relevance to the test itself. For example, what if a method name changes from “lessThan” to “worseThan?” The tests are still correct, but they refer to a method that no longer exists. In addition, you’re often testing more than one method at a time. And if you need to trace a method back to its test suite, you should be using your IDE’s call hierarchy anyway (or simply a “find across files” if your IDE isn’t that fancy).
Better to name your tests by what the test itself does, not which parts of the program it’s testing. If you’re testing that
1 |
lessThan(-1, 0) |
returns a negative number (to indicate the first argument is less than the second), then don’t name it “testLessThanNeg10” — name it “neg1IsLessThan0.” See? Now we understand what fact is being tried. Much better. Some people phrase their test names as “given, when, then” statements, but these words seem redundant, too. We already understand how tests work, so we can omit these words without losing any meaning.
Looking even deeper, we began to wonder why do we name tests in the first place? They are never used in code; they are only run by the unit test framework. So why bother naming it? Well, it turns out the names behave as comments. When a test fails, you can read the name of the test and immediately have some knowledge about the failure. You can’t do that with real comments, because those aren’t normally included in a test report. However, testing frameworks do allow you to attach a message to each of your assertions, so does that make the method name redundant? Perhaps.
Another lesson to learn is that variable naming is almost as important as method naming. Sometimes we tend to focus on the latter a lot more, because we are sometimes more concerned with what something does rather than what something is. Some argue that you should never inline a constant, though I would argue that there is no benefit to making a variable that is only used once.
Variable naming is important, but the goal is not always uniform. Sometimes you might in fact want to name a variable by what it’s used for rather than what it is. For example, in tests, with fake data, the content of the data itself is often unimportant. It helps in these cases to name variables
1 |
irrelevant |
or
1 |
dontCare |
. This helps the you determine that those particular pieces don’t apply to the actual test. Furthermore, you can shape things so that they look like real data in a UI, but they’re still obviously fake. You might, for instance, name all insurance agents in the database as “James Bond.”
We asked ourselves about package/module names. Do we normally use them for categorization, or for common purpose? Do we lump all the models in one folder and all the views in another? Or do we put all the MVCs for Banks in one place and all the MVCs for Videos in another? This is a debate about organizing programs in an encyclopaedic fashion. Do you index by one set of categories or by another, orthogonal set of categories? Reginald Braithwaite has said some intelligent things on the subject. He might argue that these are two completely valid, but completely contradictory layouts.
Someone pointed out, partly joking but not entirely, that Ruby programmers are sometimes a bit reluctant to name things because their IDEs do not typically support it. The upshot is that different languages and even different toolchains may have an effect on name choices.
Perhaps the most important, introspective question came from a blog post by J.B. Rainsberger. Why do we name things? Some answers:
- To discover their purpose. (jbrains’ argument)
- To get a handle on things, to gain control over things. (Western hermetic magic concept, related to jbrains’ argument)
- To have a common domain language. Now whenever anyone says anything, you immediately know what they’re talking about.
A prime example of a domain language that every programmer already knows is that of design patterns. Back in the 80s, the Gang of Four realized that there existed certain common patterns, and that we needed a common way of referring to them. Much how mathematicians come to agree on a common set of notation, so they can share their findings with each other. Naming gives us the power to discuss complex subjects and still be understood.
Oh, and one more thing. How many of us have developed a new feature, and agreed upon a name, only to have marketing give it a different name when it comes time to release? Ignore whatever marketing tries to call it. This is just the flavor of the month. A dev team should pick one, consistent name, and stick to it. This reduces confusion, even if you do have to use a different name when you talk about it to people outside the dev team.