Search

Why Is Naming Things So Hard in Programming?

The short answer

Quick answer: Naming is hard because a name is a compressed explanation. To name something well, you have to know exactly what it is, what it is not, and how the people reading it will understand the word. That is a design problem dressed up as a vocabulary problem. Names must also be short, distinct from their neighbours, consistent with the rest of the codebase, and still true after the code changes. When you cannot find a good name, it is usually a sign that the thing itself is unclear or does too many jobs.

The famous joke

Phil Karlton, an engineer at Netscape, is credited with the line:

There are only two hard things in Computer Science: cache invalidation and naming things.

Martin Fowler records the quote and its variations on his TwoHardThings page, including the popular extension: "two hard things: cache invalidation, naming things, and off-by-one errors."

The joke lasts because it is true. Cache invalidation is hard for technical reasons; see caching strategies. Naming is hard for human ones.

Why it is hard

A name is an abstraction

Code is read far more often than it is written. A name is what the reader sees in place of the details. calculateShippingCost(order) promises that you do not need to open the function to know what it does. If the promise is false, every reader is misled.

So the real work of naming is deciding what the thing is. If a function validates input, saves a record and sends an email, no honest name fits, because it is three things. Trouble naming is frequently the first visible symptom of a muddled design.

You name it when you understand it least

Names are chosen at the start, while the idea is still forming. By the time you understand the problem properly, the first name is used in fifty places.

Names go stale

Code changes; names often do not.

def get_user(id):
    user = db.find(id)
    if user is None:
        user = db.create_default(id)     # added later
    audit.log("user_accessed", id)       # added later
    return user

get_user now creates users and writes audit records. Nothing warns you. A wrong name is worse than a vague one, because people trust it.

Words mean different things to different people

In one company, "account" can mean a login to the engineers, a customer organisation to sales, and a ledger to finance. "User", "customer", "client" and "member" may be four things or one. The code inherits every ambiguity the business has.

Competing goals

A good name should be:

  • Precise enough to be accurate
  • Short enough to read comfortably
  • Distinct from similar names nearby
  • Consistent with existing conventions
  • Searchable

These pull against each other. data is short and says nothing. customerOrdersAwaitingPaymentConfirmationList is precise and exhausting.

Names are hard to change

Inside one codebase, a rename is a tool command. Across boundaries it is not: database columns, public API fields, event names, configuration keys and URLs are depended on by other systems. The HTTP Referer header has been misspelt since the 1990s and always will be.

The good words are taken

Manager, Handler, Service, Processor, Helper, Util, Data, Info. They are available because they mean almost nothing.

What bad names cost

  • Slower reading. Every unclear name forces a trip to the definition.
  • Bugs. A variable called timeout that is in seconds in one place and milliseconds in another.
  • Wrong reuse. People call a function for what its name says, not what it does.
  • Harder onboarding and harder searching.

These costs are a form of technical debt: small each time, paid on every read.

Practical rules

Say what it is, not how it is stored

WeakBetter
list, arr, datapendingOrders
userMapusersById
flagisArchived
temp, result2discountedTotal

Include the unit

const timeout = 30;            // seconds? milliseconds?
const timeoutMs = 30_000;      // clear

sizeBytes, priceCents, delaySeconds, createdAtUtc. This prevents a whole class of bugs. See why time zones are a programmer's nightmare for one place it matters.

Verbs for functions, nouns for things

  • Functions do something: sendInvoice, parseDate, findUserByEmail.
  • Booleans read as questions: isEmpty, hasAccess, canRetry, shouldSync. Avoid negatives such as isNotDisabled.
  • Classes and variables are nouns: Invoice, retryPolicy.

Make the name honest about side effects

If it writes to a database, the name should not start with get. getOrCreateUser is uglier than getUser and far more useful. Code with fewer hidden side effects is easier to name; see why immutability matters.

Match length to scope

A loop index used for three lines can be i. A value used across a module needs a full, descriptive name. The further a name travels, the more it must explain by itself.

One word per concept

Do not mix fetch, get, load and retrieve for the same operation. Pick one and use it everywhere. Equally, do not use one word for two different concepts.

Use the language of the domain

If the business says "policy", "claim" and "premium", the code should too. Domain-driven design calls this a ubiquitous language: one vocabulary shared by developers and domain experts. A short glossary in the repository settles many arguments.

Avoid

  • Abbreviations that are not universal (usrCnt, procMgr).
  • Type prefixes such as strName. The type system and editor already know.
  • Numbered names (data2, handlerNew, final_v3).
  • Clever names and in-jokes. They are funny once.
  • Names that differ by one character.

Follow the conventions of the language

snake_case in Python, camelCase in JavaScript, PascalCase for types, and so on. Wikipedia's article on naming conventions surveys them. Consistency is worth more than any individual preference, and a linter can enforce it.

When you are stuck

  • Describe it in one sentence. If the sentence contains "and", consider splitting the thing in two.
  • Write the calling code first. How do you wish it read?
  • Ask a colleague what they would expect a function with that name to do.
  • Use a deliberately bad placeholder (thingamajig) so nobody mistakes it for final, and rename once you understand it.
  • Rename freely while it is cheap. Modern editors make it safe.

Code review is a good place to catch names that only make sense to the author.

Do AI tools change this?

AI coding assistants are good at proposing conventional names, and at renaming consistently. They do not know that your company means something particular by "account", or that a function gained a side effect last month. The underlying work, deciding what the thing is, still belongs to someone who understands the system.

Frequently asked questions

Who said naming things is one of the two hard problems?

The saying is attributed to Phil Karlton, who worked at Netscape.

How long should a variable name be?

As long as needed to be clear in its scope: short for small, local scopes, and more descriptive for anything used widely.

Is it worth renaming existing code?

Inside a codebase, usually yes, when the old name is misleading. For names that cross system boundaries, weigh the cost of migration against the confusion.

What makes a name bad?

It misleads, it is vague, it is inconsistent with similar names, or it describes how something is stored and not what it means.

Conclusion

Naming is hard because it forces you to understand what you have built and to predict how someone else will read it. That difficulty is useful: a name that will not come is telling you something about the design. Treat names as part of the design, keep them honest as the code changes, and prefer plain and accurate to clever.

Related articles

Sources and further reading

Usama Muneer

Usama Muneer

Coder, Blogger, Tech Speaker & Web Technologies Enthusiast. Passionate about working on open-source Programming languages & Tools while utilizing my Product Development skills.

Your experience on this site will be improved by allowing cookies Cookie Policy