The Quest Begins (The "Why")
I still remember the first time I opened a legacy codebase and felt like I’d stepped into a dragon’s lair without a map. Variables called tmp, data, stuff, and functions named doIt() or process() stared back at me from the screen like cryptic runes. I spent three hours tracing a single bug only to discover that tmp was being reused for three completely different values across the same module. My head hurt, my coffee went cold, and I muttered, “Who wrote this?” — only to realize, with a sinking feeling, that it was me from six months ago.
That moment was my “aha!” moment. I realized that the real enemy wasn’t messy logic or missing tests; it was the names we give to our creations. Poor naming turns code into a puzzle that forces every reader (including future you) to constantly pause, guess, and re‑read. Good naming, on the other hand, turns the same code into a story you can read aloud and understand on the first pass.
The Revelation (The Insight)
The best practice that changed everything for me is simple: choose names that reveal intent. Not just “what does it hold?” but “why does it exist?” and “what does it do?” When a name answers those questions, the code self‑documents. You spend less time deciphering and more time building.
Think of it like the Fellowship of the Ring: each member has a clear role that tells you instantly what they bring to the quest. Gandalf isn’t just “the wizard”; he’s “the guide who knows the hidden paths”. Aragorn isn’t “the fighter”; he’s “the heir destined to unite the kingdoms”. If we gave them vague labels like “member1” or “person2”, the story would collapse under confusion. Our code deserves the same clarity.
Wielding the Power (Code & Examples)
Let’s look at a common scenario: calculating a discount for an e‑commerce cart. Below is a before version that I’ve seen far too often — names that tell you nothing about purpose.
// BEFORE – vague names, hidden intent
function a(p, d) {
let t = 0;
for (let i = 0; i < p.length; i++) {
t += p[i].price * p[i].qty;
}
return t - (t * d / 100);
}
// usage
const cart = [
{ price: 20, qty: 2, id: 1 },
{ price: 15, qty: 1, id: 2 }
];
const final = a(cart, 10); // 10% discount
What does a do? What are p and d? Why is t a running total? You have to read the whole function to guess, and even then you’re not entirely sure if the discount is applied per‑item or to the subtotal.
Now, let’s refactor with intentional names:
// AFTER – names that reveal intent
function calculateDiscountedSubtotal(cartItems, discountPercent) {
const subtotal = cartItems.reduce((sum, item) => {
return sum + item.price * item.quantity;
}, 0);
const discountAmount = subtotal * (discountPercent / 100);
return subtotal - discountAmount;
}
// usage
const cart = [
{ price: 20, quantity: 2, id: 1 },
{ price: 15, quantity: 1, id: 2 }
];
const finalPrice = calculateDiscountedSubtotal(cart, 10); // 10% discount
What changed?
-
a→calculateDiscountedSubtotal– the verb tells you the action, the noun tells you what’s being acted upon. -
p→cartItems– immediately conveys a collection of items in a shopping cart. -
d→discountPercent– makes it obvious the value is a percentage, not a flat amount. -
t→subtotalanddiscountAmount– each intermediate value now has a name that explains its role in the calculation. - Inside the reducer,
item.price * item.quantityis still clear, but we also renamedqtytoquantityfor readability.
The after version reads like a sentence: “Take the cart items, compute the subtotal, figure out the discount amount, subtract it, and return the result.” No mental gymnastics required.
Common Traps to Avoid
-
Stuffing meaning into abbreviations –
cnt,tmp,info. They save a couple of keystrokes but cost minutes of confusion later. Spell it out unless the abbreviation is universally understood (likeidorurl). -
Reusing variables for unrelated purposes – using the same
tmpvariable for a loop index, a flag, and a cached value. Give each concept its own name; the compiler will thank you, and so will your future self. -
Names that lie – a function called
getUserData()that actually modifies the database. Names should be honest contracts; if they don’t match the implementation, refactor either the name or the code.
Why This New Power Matters
When you start naming with intent, you’ll notice a cascade of benefits:
- Fewer bugs – mis‑understandings drop dramatically because the code’s purpose is explicit.
- Faster onboarding – new teammates can jump in and contribute without a lengthy “code archaeology” session.
- Easier refactoring – when a name clearly states what something does, you can safely change its internals knowing the contract stays the same.
- Better documentation – the code itself becomes the documentation; comments shift from “what does this do?” to “why did we choose this approach?”.
In short, good naming transforms your codebase from a mysterious cavern into a well‑lit hallway where every door is labeled. You’ll spend less time decoding and more time delivering features that delight users.
Your Turn – Embark on Your Own Naming Quest
Here’s a quick challenge: pick a function or variable you’ve written recently that makes you pause when you read it. Rename it so that someone unfamiliar with the project could guess its purpose at a glance. Then, read the surrounding code again. Do you feel the fog lift? Share your before/after snippets in the comments — let’s celebrate the small victories that make our codebases healthier, one meaningful name at a time.
Happy naming, and may your code always be as clear as a wizard’s spell!
Top comments (0)