Bad variable names don't feel expensive when you write them. They feel expensive three weeks later, when you reopen the file and wonder what data2 was supposed to mean.
That is why variable naming best practices matter. Not because clean code is a religion. Because names are the first thing you read when you try to understand what a program is doing.
You don't need poetic names. You need boring names that tell the truth.
Name the Value by Its Job
A variable name should answer one question: what job does this value have in this block?
items is weak if the function handles invoices. invoices is better. paidInvoices is better again if the list was already filtered.
Bad:
const data = invoices.filter((x) => x.paid);Better:
const paidInvoices = invoices.filter((invoice) => invoice.paid);The second version doesn't need a comment. The names carry the context.
This is also why style guides spend real space on naming. Python's PEP 8, for example, separates naming rules for functions, variables, constants, classes, and exceptions. Naming is part of how code explains itself, not decoration.
Pick Specific Nouns, Then Stop
A useful variable name is specific enough for the local code around it.
That last part matters. Long names can be just as annoying as vague names.
You don't need listOfInvoicesThatHaveAlreadyBeenPaidByTheCustomer. It tells the truth, but it makes the line painful to read.
A better rule:
| Weak | Better | Too much |
|---|---|---|
data | paidInvoices | paidInvoicesReturnedFromDatabaseQuery |
user | currentUser | currentlyAuthenticatedDashboardUser |
flag | isExpired | booleanThatChecksIfTokenExpired |
value | orderTotal | calculatedOrderTotalIncludingTaxAndDiscounts |
A good name gives enough context for the reader standing inside that function. It doesn't need to explain the whole business model.
If the function is short and focused, the names can be shorter too. If the function is doing five jobs at once, naming gets harder. That is usually a design smell, not a naming problem.
Use Domain Words When They Exist
Code is easier to read when it uses the same words as the product.
If the app sells tickets, call the thing ticket, not record. If the app handles invoices, call it invoice, not document. If the business calls someone a subscriber, don't randomly call them member in one file and customer in another.
That sounds small until search becomes annoying.
When a bug report says "subscriber renewal fails," you want to search for subscriber and find the code that matters. If the code says userAccountEntity, good luck.
Consistency beats cleverness here.
Booleans Should Read Like Yes or No
Booleans are easier when they sound like a yes or no question.
Use names like:
isLoadinghasPermissioncanRetryshouldSendEmailwasArchived
Avoid names like status, permission, or retry. Those could mean anything.
This small habit makes conditions read naturally:
if (canRetry && !isLoading) {
retryPayment();
}You can almost say it out loud. That is the test.
Be careful with negative boolean names, though. isNotDisabled or hasNoAccess can turn conditions into little brain traps.
if (!isNotDisabled) {
// Wait, so it is disabled?
}Use the positive form when you can:
if (isDisabled) {
showUpgradeMessage();
}One negation is fine. Two negations in a condition means future you will start bargaining with the compiler.
Functions Need Verbs
Variables usually hold things. Functions do things. So functions should start with verbs.
invoiceTotal() is unclear. Is it a number? A function? A property?
calculateInvoiceTotal() tells me it does work.
Some verbs I reach for a lot:
| Verb | Good for |
|---|---|
get | Simple reads |
create | New values or records |
calculate | Derived numbers |
parse | Turning raw input into shaped data |
validate | Checking rules |
format | Preparing text for display |
Be careful with handle. It becomes a junk drawer fast.
handleSubmit is fine in a UI component because it names an event handler. handleStuff, handleData, and handleProcess deserve jail.
If you can't name the function with a clear verb, the function may be doing too many things.
Match the Name to the Scope
The wider the scope, the clearer the name should be.
A variable inside a three-line loop can be short:
for (const invoice of invoices) {
total += invoice.amount;
}That is fine. invoice is local, obvious, and gone in a few lines.
A value passed across files needs a stronger name:
const monthlyRecurringRevenue = calculateMonthlyRecurringRevenue(accounts);Nobody wants to chase mrr, rev, or amount across five files unless the team already uses that abbreviation every day.
Short names are not evil. Random short names are.
Avoid Names That Describe the Type Only
Names like array, object, stringValue, and numberData don't tell the reader much.
The type is already visible in many editors. TypeScript makes this even clearer. What the reader needs is meaning.
Bad:
const userArray = await getUsers();
const stringValue = user.email;Better:
const users = await getUsers();
const emailAddress = user.email;The first version talks like the computer. The second version talks like the product.
There are exceptions. If you are writing generic utilities, type-focused names like key, value, input, or result can be fine. But in business logic, meaning wins.
Rename When the Code Changes
Names rot.
A variable that started as activeUsers might later include invited users. A function called sendWelcomeEmail might now also create a notification record. The code changed, but the name stayed behind.
That mismatch is where bugs hide.
When you edit logic, ask one boring question: does the name still tell the truth?
If the answer is no, rename it in the same change. Modern editors make this cheap. Tests make it safer. The same habit applies when you write tests: names should tell the reader what behavior you expect.
Comments Shouldn't Apologize for Bad Names
A comment can explain why code exists. It shouldn't explain what a lazy name means.
Bad:
// d is the number of days since signup
const d = getDays(user.createdAt);Better:
const daysSinceSignup = getDays(user.createdAt);Now the comment can disappear. The code says the thing directly.
Save comments for intent, tradeoffs, and weird business rules. Don't spend them translating x, tmp, and stuff.
A Quick Variable Naming Checklist
Before you commit, scan the diff for names that smell vague:
dataresulttempobjvalueflagitemthing
Those names aren't banned. Sometimes they're fine in tiny loops, tests, or throwaway code. But if one survives in business logic, it needs a second look.
Ask these instead:
- What does this value represent?
- Has it already been filtered or changed?
- Is it a boolean that should start with
is,has,can, orshould? - Does the name still match the code after this edit?
- Would a new teammate understand it without opening three other files?
The best names are boring in the best way. You read them once and move on.
Future you has enough problems. Don't make variable names one of them.


