Names Reveal Intent
What This Concept Is
A name is compressed documentation. When you name a class, method, or variable well, the reader learns three things at once:
- what it is (domain or role)
- why it exists (purpose)
- how to use it (expected behavior)
A bad name forces the reader to reconstruct those three facts by scanning implementation, running a debugger, or guessing from usage. Every bad name is rented: you pay interest every time someone reads the code.
Clean Code's rule of thumb: if a name needs a comment to explain it, the name is failing.
Why It Matters Here
Naming is where design becomes visible. A class named DataManager tells the reader almost nothing. A class named OrderExporter tells them the responsibility, the data involved, and the direction of work. Before we apply SOLID or refactor moves, we name things so that the problems become legible.
A local rename can be inexpensive, but public names may be used by reflection, imports, serialized records, plugins or external clients. A compiler does not inspect all those consumers. Specify compatibility before calling a rename behavior-preserving.
Concrete Example
Bad naming -- everything is "data":
def process(d):
r = []
for x in d:
if x[2] > 0:
r.append(x[0])
return r
The reader has no idea what d is, what x[2] means, or what's being filtered.
Names that reveal intent:
def customer_ids_with_outstanding_balance(customers):
ids = []
for customer in customers:
if customer.balance > 0:
ids.append(customer.id)
return ids
The names reveal intent, but this example also changes rows indexed by position into objects with attributes. It is not only a rename. First preserve the tuple representation while naming local bindings; migrate representation separately with compatibility checks.
Common Confusion / Misconception
"Short names are clean names." Not in general. Short names are fine when the scope is tiny (i in a three-line loop) or when the name is a well-known convention (e for an exception in a catch). Long names pay for themselves whenever the distance between declaration and use is large.
A second misconception: "the name should say how it works." A name should say what it does and why, not how. bubbleSortCustomers is worse than sortedByName because the algorithm is implementation; the sort order is intent.
A third: "Hungarian-style type prefixes are informative." In modern typed languages they duplicate the compiler, and in untyped languages they lie as soon as the type changes.
How To Use It
When writing or renaming, apply this drill:
- Write the purpose and observable effects. Words such as "and" can flag complexity, but a coherent operation may legitimately validate and update one invariant.
- Name by role, not by type (
usernotuserMap;isActivenotactiveFlag). - Prefer verbs for functions (
compute,find,render) and nouns for classes (Order,Report). - Avoid disinformation:
accountListthat is actually aSetlies. - When you rename, delete any comment the rename obsoletes in the same commit.
Check Yourself
- Why is a comment that describes what a method does often a naming failure?
- When is a very short name (like
i) actually a good name? - What is the difference between naming by role and naming by type?
Mini Drill or Application
Pick any 200-line file you know. Do all four:
- Mark every name you had to read the body to understand.
- For each, propose a rename that makes the purpose clear at the declaration.
- Delete the comment above at least two of them, confirming the rename carries the information.
- Verify that usage sites still read correctly with the new name.
Read This Only If Stuck
- Clean Code: Meaningful Names -- introduction
- Clean Code: Use pronounceable names
- Clean Code: Add meaningful context
- Refactoring: Mysterious Name smell
- Good Code, Bad Code: Comments are a poor substitute for descriptive names
Engineering extension: Names can be part of external behavior
Rename a local variable freely after checking scope, but inventory an exported method through imports, string lookup, serialized fields, templates and documented examples. Preserve an alias or version the boundary when compatibility matters. Names such as timeout_ms and amount_minor preserve units that a generic value obscures. Try: improve the tuple-based customer example without changing its input type. Check: a representation migration and a rename need separate evidence even when both improve readability.
Use the design contracts and practice feedback after an independent attempt.