Names Are the First Thing You Read and the Last Thing You Remember
View original- best
Summary (TL;DR)
Naming is the first thing you read in code and the last thing you remember, especially in pull requests and Slack snippets where no IDE or autocomplete exists. A function like toggleFoundAddress(false) forces readers to hold state in their head. Renaming it to closeManualAddressInput() makes intent clear without reading the implementation. Generic loop variables like value and key hide what the data represents. Rewriting them as brandName and jurisdictions carries the domain meaning so anyone can follow the logic. Arguments for weak names, that types, IDE hovers, or surrounding context will explain things, assume the reader has the right tool at the right time. Naming is a design decision, not a style preference. Good names work in any environment.
Names Are the First Thing You Read and the Last Thing You Remember
Code gets read in places where nothing else helps. A GitHub pull request has no IDE. A Slack snippet has no autocomplete. The only thing that tells you what the code does is the names inside it.
Naming is the primary unit of readability. Not comments, not types, not tooling. The name itself carries the meaning, or it doesn’t.
A toggle tells you nothing about intent
Years ago I worked in a function called toggleFoundAddress. It accepted a boolean. Call it with false, and it closed a manual address input. Call it with true, and it opened one.
toggleFoundAddress(false);
toggleFoundAddress(true);Reading this in a pull request, you have to hold state in your head. What does false mean here? Besides the clear Parameter Trap, the name describes the mechanism, not the intent.
Two simple changes made it clearer:
closeManualAddressInput();
openManualAddressInput();Same behaviour. The function name tells you what will happen before you read the implementation. You don’t need the surrounding code, the class definition, or the module’s broader context.
This is a small change with a large surface area. Every caller becomes easier to read. Every reviewer seeing it for the first time arrives at the right understanding without asking.
Generic names hide domain knowledge
Here’s a loop that registers translations for multiple brand jurisdictions:
_.each(i18nMessages, (value, key) => {
for (const jurisdiction of value) {
addTranslation(`${key}_${jurisdiction}`, value[jurisdictionName]);
}
addTranslation(key, value);
});value and key describe position in a data structure. They say nothing about what the data represents. To follow this code, you need to trace i18nMessages back to its source and figure out that key is a brand name and value is a collection of jurisdictions.
The rewrite:
// Duck type to a key/value object, don't use external dependencies
Object.keys(i18nMessages).forEach((brandName) => {
// State where it is coming from
const jurisdictions = i18nMessages[brandName];
// Duck type to a key/value object
for (const jurisdiction of jurisdictions) {
addTranslation(`${brandName}_${jurisdiction}`, jurisdictions[jurisdictionName]);
}
// key/value names are irrelevant for the domain
// It matters where they are, not from where they came from
addTranslation(brandName, jurisdictions);
});brandName and jurisdictions carry the domain meaning. A reviewer who has never seen i18nMessages before can still follow the logic. The code tells you that brands have jurisdictions and each combination gets a translation entry. That information was there before, but buried.
Good names remove the dependency on tooling. They carry meaning in any environment.
People argue for weak names in predictable ways. “The type system catches it.” “The IDE shows you on hover.” “Just read the surrounding context.”
All of those arguments assume the reader has the right tool at the right time. A GitHub PR strips that away. You see the diff. You see the names.
TypeScript won’t help you reading a diff on your phone. IDE autocomplete won’t help a reviewer who opened the PR in a browser tab between meetings. “Just read the surrounding context” means the code only makes sense if you’ve already read the code. That’s circular.
Dev tools should be an enhancement. They should speed up someone who already understands the code. They should not be required for understanding it at all.
Naming is a design decision, not a style preference
The difference between value and jurisdictions is not cosmetic. One encodes what the data is. The other encodes where the data sits in a structure. The difference between toggleFoundAddress and closeManualAddressInput is not taste. One requires interpretation. The other requires none.
That gap matters at scale. A codebase with a hundred generic names is a codebase where every reader spends time translating. A codebase with a hundred specific names is one where the translation is already done.
Write code that reads well without any tools at all. You never know who's gonna read it.