Names That Pack Information
A colleague once asked me to review a function called process. It took a parameter called data and returned a value called result.
I stared at it for 5 minutes before asking: "What does this actually do?"
"It converts user timestamps to the local timezone," he said.
That function should have been called convertTimestampsToLocalTimezone. The parameter should have been userEvents. The return value should have been localizedEvents.
Naming is not decoration. It's documentation that can't go stale.
The Specificity Principle
Generic names are placeholders. Specific names are information.
| Generic | Specific |
|---|---|
data | userProfile, orderHistory, sensorReadings |
temp | previousBalance, cachedResponse, retryDelay |
result | validatedEmail, calculatedTotal, filteredProducts |
handler | paymentWebhookHandler, errorResponseHandler |
process | normalizeAddress, calculateShipping, parseLogEntry |
Every time you type a generic name, you're making the next reader do extra work.
The Word Association Test
Here's a technique from The Art of Readable Code: imagine someone reading just the name, with no context. What might they assume?
Take fetchData:
- Data about what?
- From where? Database? API? File?
- In what format?
Now take fetchUserProfileFromCache:
- It's about user profiles
- It comes from a cache
- It implies there's probably also a
fetchUserProfileFromDatabase
The second name prevents wrong assumptions.
Words to Avoid
Some words are almost always filler:
data — Everything is data. What kind of data?
info — Same problem. userInfo should be userProfile or userCredentials or userPreferences.
temp — If it's temporary, what is it for? previousValue, swapBuffer, intermediateResult.
thing, stuff, item — These are admissions that you don't know what you're naming.
Manager, Handler, Processor — These often indicate a class doing too much. We'll cover this more in the classes lesson.
Length vs. Clarity
"But long names are hard to type!"
Two responses:
- Your IDE autocompletes after 3 characters
- You type the name once; others read it hundreds of times
A name should be as long as necessary to be clear, and no longer.
| Scope | Appropriate Length |
|---|---|
| Loop counter (2-line scope) | i, j, k are fine |
| Local variable (10-line scope) | Short but descriptive: total, user, items |
| Function parameter | Descriptive: userId, startDate, options |
| Class field | Full context: maximumRetryAttempts, defaultTimeoutSeconds |
| Global/constant | Very explicit: MAX_CONNECTION_POOL_SIZE, DEFAULT_CACHE_TTL_SECONDS |
The longer the scope, the more descriptive the name needs to be.
Code Transformation Example
This function exists in many codebases:
function process(d) {
const t = d * 24;
return t;
}
What does it do? You'd have to trace every call site to find out.
Now:
function daysToHours(days) {
const hoursPerDay = 24;
return days * hoursPerDay;
}
Same logic. But the name tells you:
- Input: days
- Output: hours
- Operation: conversion
You can understand this function without reading its body. That's the goal.
The Search Test
Can you search for your variable in the codebase and find it?
If your variable is named e, d, or x, searching for it will return thousands of false positives.
If your variable is named errorCount, deliveryDate, or xCoordinate, you can find every usage instantly.
Searchability matters for refactoring, debugging, and understanding.
Practical Exercise
Go to your codebase right now. Search for variables named:
datatempresultitemobj
Pick 10 of them. For each one, rename it to describe what it actually holds.
This exercise will improve your codebase more than many hours of "refactoring."
Key insight: Names are compressed documentation. Every generic name (data, temp, result) forces readers to expand it manually by reading surrounding code. Specific names (userProfile, previousBalance, validatedEmail) carry their meaning with them.