The Hidden Architecture of Names: Why Good Code Starts as Good Interpretation
Hatched by Jaeyeol Lee
Jul 10, 2026
9 min read
3 views
62%
The Strange Burden of Naming
What if the hardest part of writing code is not solving the problem, but deciding what the problem actually is? A variable name can look like a tiny cosmetic choice, yet it often reveals whether the underlying design is clear or confused. The moment you struggle to name something, you are usually not facing a vocabulary problem. You are facing a shape problem.
That is why naming feels so uncomfortable in serious codebases. We imagine we are choosing labels for already formed ideas, but in practice, the name is often the thing that helps the idea come into focus. Until a function can be named cleanly, it may still be carrying too many responsibilities, too many exceptions, or too much hidden context. The name does not just describe the code. It exposes the code's real structure.
This is why naming has a peculiar power: it turns software design into an act of interpretation. You are not just asking, “What should I call this?” You are asking, “What is this thing, really?”
Names Are Not Tags, They Are Models
A weak naming mindset treats words like sticky labels. We create a thing, attach a title, and move on. But strong naming works differently. A good name is a compact model of intent. It tells you what the thing contains, what it does, and just as importantly, what it does not do.
Think of the difference between a box labeled “miscellaneous” and a box labeled “winter gloves.” The first is technically a label, but it is not useful. The second carries enough meaning to guide action. You know where to look when you need gloves, and you know where not to look when you need tools. Good code names behave the same way. They reduce search costs, but more than that, they reduce ambiguity.
A good name does not misdirect, omit, or assume. That sounds simple, yet those three failures account for much of the pain in real systems:
- Misdirection: a function called
Authorizationthat is actually used for authentication. - Omission: a name that hides critical behavior, such as
processDatawhen the function also persists records and sends notifications. - Assumption: a term that only makes sense to the original developer, not to future readers or teammates.
This is why naming is inseparable from context. A name is never universal. It exists inside a codebase with its own vocabulary, conventions, and narrative. The same word can be precise in one system and misleading in another. A good name is not merely correct in isolation, it is coherent in its neighborhood.
A name is a local theory about reality. If the theory is good, the code becomes easier to navigate. If it is bad, the code becomes harder to trust.
The Deeper Truth: Naming Reveals Design Quality
The most important insight is that naming is not downstream from design. It is one of the fastest ways to detect design quality. If a function is difficult to name, the function is probably doing too much. If a variable name needs a long explanation, the underlying concept is probably overloaded. If a class name works only when you add a paragraph of comments, the architecture may be hiding complexity instead of organizing it.
This is why long names are not automatically bad, and short names are not automatically elegant. Length follows scope. A short variable in a tiny lambda may be ideal because the surrounding context does the heavy lifting. A long name in a broad module may be necessary because the concept spans many responsibilities. The point is not brevity. The point is precision relative to context.
In practice, naming becomes a design review disguised as a wording exercise. If you find yourself reaching for words like “and” or “then” inside a function name, that often signals composition hiding inside a single unit. A name like validateAndSaveUserThenSendEmail is not just verbose. It is a confession that the code may be trying to wear three hats at once. The name is telling you where the seams are.
Consider a kitchen drawer labeled “kitchen things.” It is not wrong, but it is uninformative. Now imagine a drawer labeled “spare batteries and measuring spoons.” That is not a category, it is a compromise. It tells you the drawer was organized around convenience rather than meaning. Bad names often have the same feel. They are evidence of local patching, not deep understanding.
The cleaner the design, the less the name has to compensate.
The Architecture Hidden Inside a Vocabulary
There is another layer to this: the names in a codebase do not stand alone. They form a system of relationships. Good code reads like a coherent story, where the nouns and verbs reinforce one another. When that story is strong, readers can move through the system almost intuitively. When it is weak, every file becomes a translation exercise.
This is where the idea of dependency becomes more than a technical concern. A system is not merely made of objects calling each other. It is made of meanings calling each other. If names are inconsistent, the conceptual map fractures. A reader sees “user,” “account,” “profile,” and “member” used interchangeably and must constantly ask whether those terms refer to the same thing or different layers of the same thing. That uncertainty is not semantic nitpicking. It is architectural friction.
Tools that visualize or validate dependencies are useful precisely because they expose hidden structure. They force a question that naming also forces: do these parts truly belong together? A dependency graph can show which modules rely on which others, but the naming layer tells you something subtler. It tells you whether those dependencies make conceptual sense. If a module called auth contains logic for permissions, login identity, token refresh, and user onboarding, the name and the structure are already at odds. One is pretending the other is simpler than it is.
A strong naming system does three things at once:
- It clarifies ownership. What is this thing responsible for?
- It clarifies boundaries. What is this thing not responsible for?
- It clarifies relationships. How does this thing fit with everything around it?
When those three are aligned, code becomes easier to modify because the reader can predict the blast radius of a change. A name is therefore not only a label, it is a small contract with the future.
Good names are not decoration on architecture. They are one of the ways architecture becomes legible.
When Comments Help, and When They Are a Warning
Comments are often described as a necessary evil, and that phrase is more revealing than it first appears. A comment is useful when it captures knowledge that cannot yet be expressed cleanly in the names or types. But it is also a clue that something in the code may still be incomplete as communication.
This is why comments should be treated as a supplement, not a substitute. If a comment says, “This is temporary,” or “Do not change this,” or “This is named X because of legacy reasons,” the code may be carrying hidden history that the current structure has not reconciled. In other words, comments often record the gap between what the code says and what the code means.
A well designed system needs fewer rescue notes. The names, types, and boundaries should carry as much meaning as possible. Comments then become reserved for the genuinely non-obvious: business rules, external constraints, performance tradeoffs, and domain knowledge that cannot be inferred from syntax alone.
A useful mental model is to treat naming and comments as different levels of compression. Names should compress the obvious. Comments should preserve the exceptional. If you are using comments to explain what a name should have conveyed, the system is paying interest on conceptual debt.
This is also why the best naming process is iterative. You often begin with a provisional word, then refine it as understanding deepens. The goal is not to pick the perfect label immediately. The goal is to let the name evolve until it reveals the essence rather than the accident of implementation.
A Practical Framework: Ask What Must Be True for This Name to Work
When stuck on a name, most developers ask, “What word fits this thing?” That is a reasonable start, but it is not the best question. A better question is, “What must be true about this concept for this name to be honest?”
This shifts naming from search to diagnosis. Instead of hunting for a noun, you inspect the structure behind the noun. If you cannot name a function cleanly, ask:
- Does this function do more than one thing?
- Does it depend on context that is not obvious from its signature?
- Does it mix domain logic with infrastructure concerns?
- Would a better boundary make the meaning simpler?
If you cannot name a variable cleanly, ask:
- Is this actually one concept, or several blended together?
- Is the variable holding a role, a state, a collection, or a temporary result?
- Would splitting it into smaller parts make the name self-evident?
If you cannot name a module cleanly, ask:
- Is the module coherent enough to deserve a single purpose?
- Are the dependencies pointing in a clear direction?
- Are the terms in this area of the codebase consistent, or are they drifting?
This framework works because names are not endpoints. They are diagnostics. A good name emerges when the underlying concept is stable enough to deserve one. In that sense, naming is a test of conceptual honesty. You cannot call a thing by a precise name until the thing itself has been made precise.
That is why naming has so much leverage in programming. It is one of the rare practices that improves both communication and structure at the same time. Refine the name, and you often refine the code. Refine the code, and the name often becomes obvious.
Key Takeaways
- Treat naming as design feedback, not as a final cosmetic step. If a name feels awkward, the underlying code may be too broad or too vague.
- Prefer precision over brevity. A longer name can be better when the scope is larger, as long as it is honest and readable.
- Use names to expose boundaries. If a function name needs “and” or “then,” it may be doing multiple jobs and should be split.
- Let context do work. A name should fit the surrounding vocabulary and conventions of the codebase, not fight them.
- Reserve comments for what names cannot carry. Comments should explain exceptions, constraints, and domain knowledge, not rescue unclear naming.
Conclusion: Naming Is the First Form of Architecture You Can Read
We often think architecture begins with diagrams, modules, or dependency graphs. But in practice, architecture becomes visible much earlier, in the words we choose. Every name is a small attempt to align language with reality. Every successful name says, “This is what the thing is.” Every failed name quietly admits, “I do not yet know.”
That is why naming matters so much. It is not about making code prettier. It is about making thought more exact. The best names do not merely point at code. They help reveal why the code exists, how its parts belong together, and where the design is still unfinished.
In the end, the real power of naming is that it forces you to confront the essence of a problem before you can hide it inside syntax. A good codebase is not one where everything has a clever label. It is one where the labels are so aligned with reality that the structure almost reads itself. That is not just good style. That is clear thinking made durable.
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣