Simple Naming Conventions That Instantly Improve Readability
I spent 20 minutes last week trying to understand what data meant. It was used in 47 places in one file. Sometimes it was user data. Sometimes API responses. Sometimes form inputs. The author (me, six months ago) thought it was obvious.
Code is read 10x more than it's written. Every time you name something temp or flag, you force every future reader to stop, read the implementation, and mentally translate. That's cognitive load you're dumping on others.
Booleans Should Ask Questions
A boolean is yes/no. Its name should sound like a question:
// ❌ Ambiguous - is "open" a function? a string?
if (modal.open) { ... }
if (user.login) { ... }
// ✅ Clear - reads like English
if (modal.isOpen) { ... }
if (user.isLoggedIn) { ... }
if (file.hasErrors) { ... }
if (user.canEdit) { ... }
Prefixes like is, has, can, should instantly communicate "this is a boolean."
And avoid negative names. if (!isNotEnabled) takes 2 seconds to parse. if (isEnabled) takes 0.1 seconds.
Functions Should Be Verb-Noun
Functions do things. Start with a verb:
// ❌ Is this returning data or sending it?
function email(user) { ... }
function userData() { ... }
// ✅ Action is clear
function sendWelcomeEmail(user) { ... }
function fetchUserData() { ... }
function calculateTotal(items) { ... }
Common verbs have standard meanings: get returns from memory, fetch makes a network call, create instantiates, compute/calculate derives values.
Arrays Are Plural
If a variable holds multiple items, its name should reflect that:
// ❌ Is this one user or many?
const user = getActiveUsers();
// ✅ Obviously a collection
const users = getActiveUsers();
for (const user of users) { ... }
for (const user of users) reads naturally. for (const user of user) is confusing.
Kill Magic Numbers
Raw numbers in code are mysteries:
// ❌ Why 86400? Why 30?
if (seconds > 86400 * 30) {
expire();
}
// ✅ Self-documenting
const SECONDS_PER_DAY = 86400;
const EXPIRY_DAYS = 30;
if (seconds > SECONDS_PER_DAY * EXPIRY_DAYS) {
expire();
}
Named constants explain the "why" and make changes easier. If expiry becomes 60 days, you change one place.
Match Scope to Length
In a 3-line loop, i is fine—the declaration is right there. In a 100-line function, data means nothing.
// ✅ Small scope = short name is fine
for (let i = 0; i < items.length; i++) { ... }
// ❌ Large scope = needs context
let data = fetchResponse();
// ... 80 lines later ...
processData(data); // What data? From where?
// ✅ Large scope = descriptive name
let userProfileResponse = fetchUserProfile();
// ... 80 lines later ...
processData(userProfileResponse); // Ah, the profile data
Be Consistent
If you use fetch in one file, don't use get, retrieve, and load elsewhere for the same concept. Pick one verb and stick with it.
Same for pairs. If you have start, the opposite should be stop (not end or finish or kill):
// ❌ Inconsistent pairs
startEngine() / killEngine()
// ✅ Symmetric
startEngine() / stopEngine()
openConnection() / closeConnection()
beginTransaction() / endTransaction()
The Readability Test
Read your code out loud. If you stumble—"and then it takes the, uh, data variable..."—rename it.
Good names eliminate comments. isAdmin && fileIsEditable needs no explanation. u.role === 1 && !doc.l needs a paragraph.
Naming is not about saving keystrokes. We have autocomplete. It's about reducing the time to understand what code does.