Meaningful Names

Names should reveal intent, making code self-documenting without requiring mental translation.

Overview

Every name in code—variables, functions, classes, files—is a chance to communicate intent. Good names tell you what something is and why it exists without requiring you to dig through implementation details. Poor names force readers to hold mental mappings between cryptic symbols and their meanings, draining cognitive resources that should go toward understanding the actual problem.

Key Principles

Reveal Intent

A name should answer: why does this exist, what does it do, and how is it used? If a name requires a comment to explain it, the name isn’t doing its job.

// Unclear
const d = 86400; // seconds in a day
 
// Clear
const SECONDS_PER_DAY = 86400;

Avoid Disinformation

Don’t use names that suggest something different from reality. Don’t call something a “list” unless it’s actually a list. Don’t use names that differ in subtle ways that are easy to miss.

// Misleading - suggests a list but might be a map
const accountList = new Map<string, Account>();
 
// Accurate
const accountsById = new Map<string, Account>();

Make Meaningful Distinctions

If you have two things, their names should clearly distinguish what makes them different. Noise words like “data,” “info,” or numbered suffixes indicate that names aren’t communicating meaningful differences.

// Indistinguishable
function copyData(data1: Data, data2: Data) { ... }
 
// Distinguished
function copyAccount(source: Account, destination: Account) { ... }

Use Pronounceable Names

Names you can’t say out loud create communication barriers. Discussing code becomes awkward when you can’t verbalize what you’re talking about.

// Unpronunceable
const genymdhms = new Date(); // generation year-month-day-hour-minute-second
 
// Pronounceable
const generationTimestamp = new Date();

Use Searchable Names

Single-letter names and magic numbers hide in code, making them impossible to find. The length of a name should correspond to its scope—larger scopes need more descriptive, searchable names.

// Unsearchable
for (let i = 0; i < 7; i++) { ... }
 
// Searchable
const DAYS_PER_WEEK = 7;
for (let dayIndex = 0; dayIndex < DAYS_PER_WEEK; dayIndex++) { ... }

Example

Consider a function that processes user status:

// Before: Requires mental translation
function proc(u: any, s: number): boolean {
  if (s === 1) {
    return u.a > 30;
  }
  return false;
}
 
// After: Self-documenting
function isUserEligibleForPromotion(user: User, status: AccountStatus): boolean {
  if (status === AccountStatus.ACTIVE) {
    return user.accountAgeDays > MINIMUM_PROMOTION_AGE_DAYS;
  }
  return false;
}

The refactored version tells a story: we’re checking if an active user has been around long enough to be eligible for a promotion.

Common Mistakes

Using single-letter variables beyond tiny scopes - Variables like i are acceptable in a three-line for loop, but a variable used across twenty lines needs a real name.

Encoding type in names - Hungarian notation (strName, intCount) adds noise without value in modern typed languages.

Using generic names - Words like Manager, Processor, Data, or Info often indicate that you haven’t thought clearly about what something actually does.

Inconsistent naming across similar concepts - If you call it fetch in one place and retrieve in another, readers will wonder if there’s a meaningful difference.

References

  • Martin, R. C. (2008). Clean Code: A Handbook of Agile Software Craftsmanship. Chapter 2: Meaningful Names.
  • Hunt, A., & Thomas, D. (1999). The Pragmatic Programmer. Section on “Naming Things.”