Naming is the part of programming nobody puts on a roadmap, yet it eats a surprising chunk of my day. I used to stare at a blinking cursor naming a variable for five minutes, then rename it three times in code review. Here is what actually reduced that friction for me.
The two rules that kill most bikeshedding
1. Name the thing by what it is, not what it does. A boolean is a fact about the world, so it reads as a claim: isLoading, hasPermission, canEdit. If you find yourself writing checkPermission, you probably want a function, not a flag.
2. Length should match scope. A loop index can be i. A variable used three lines later can be id. A module-level export that appears in 40 files needs to carry its context: InvoicePaymentStatus, not Status.
That second rule is the one people violate most. Short names are not a virtue in themselves. They are a budget you spend on small scopes.
Pick a shape and stick to it
Consistency beats cleverness. I keep a tiny mental table:
// booleans: is/has/can/should
const isDirty = true;
const hasAccess = user.role === 'admin';
// functions: verb first
function parseConfig(raw) {}
function fetchUserById(id) {}
// collections: plural
const activeUsers = [];
const userById = new Map();
// handlers: on + event
function onSaveClick() {}
Once the shape is decided, naming becomes filling in a blank instead of an open-ended creative act. fetch___ById is much easier to finish than "what do I call this function."
Say the call site out loud
The fastest naming test I know: read the line where the thing is used, not where it is defined.
// Reads badly
if (data.flag) { ... }
// Reads fine
if (user.isEmailVerified) { ... }
The definition site is where you have the most context. The call site is where the next person has the least. Optimize for the reader who is 200 lines away and has forgotten everything.
Don't encode the type
I stopped doing this years ago and never missed it:
// Redundant, and lies the moment the type changes
const userListArray = [];
const nameString = 'Ada';
// Just say what it holds
const users = [];
const name = 'Ada';
Types change. userListArray becomes a Set and now the name is a bug you have to remember to fix. The same goes for IUser style prefixes and str/int suffixes.
When the name is hard, the design is usually the problem
This is the insight that saved me the most time. If I cannot name something cleanly, it is almost always because it is doing two jobs.
A function called processAndValidateOrder is a smell. Split it:
function validateOrder(order) { /* returns errors */ }
function processOrder(order) { /* assumes valid */ }
Now both names are obvious because both functions have one responsibility. Naming pain is often a design signal wearing a costume.
Rename aggressively, and let the tool do it
I used to avoid renaming because of the churn. Modern editors make it a non-event: rename the symbol, run the tests, commit. The cost of a slightly wrong name is that every future reader pays it. The cost of a rename is one commit.
I do not try to get the name perfect on the first pass. I write thing or tmp, get the logic working, then rename once I understand what the code actually does. Naming is easier after the code exists, not before.
A short checklist I actually use
- Does it read well at the call site?
- Is it a fact (boolean) or an action (function)?
- Is the length right for its scope?
- Does it avoid encoding the type?
- If it is hard to name, is it doing too much?
That last question resolves most of my naming stalls. When nothing fits, I stop trying to name the function and start asking why it is so hard to describe. Usually the answer is: because it is two things, and I should split it first.
Top comments (0)