The Quest Begins (The "Why")
I still remember the first time I opened a legacy codebase and felt like I’d stepped into a dark dungeon without a torch. The file was a single 800‑line function called processData. Inside, variables bore names like tmp, x, flag, and comments that tried to explain every line:
// TODO: refactor this mess
function processData(input) {
let r = []; // result array
for (let i = 0; i < input.length; i++) { // loop over items
if (input[i] > 10) { // if value greater than threshold
let v = input[i] * 2; // double it
if (v % 2 === 0) { // if even
r.push(v); // add to result
}
}
}
return r;
}
I spent three hours tracing why a certain edge case produced an empty array, only to discover the comment “if value greater than threshold” was outdated—the threshold had changed to 12 in a later commit, but the comment never got updated. The code lied, the comments misled, and I felt like a hero who’d just swung at a shadow.
That frustration sparked a question: What if we could write code so clear that comments became unnecessary? Not because we’re lazy, but because the code itself tells the story.
The Revelation (The Insight)
The treasure I uncovered wasn’t a new framework or a slick library—it was a mindset shift: make the code self‑documenting through intention‑revealing names and small, focused functions. When a variable, function, or class name reads like a sentence, the reader can infer what’s happening without a side note.
Think of it like reading a well‑written novel. You don’t need footnotes to understand that “She opened the door and stepped into the rain” means she’s going outside. The same principle applies to code: if you name a function filterValuesAboveThreshold, the intent is obvious.
Why does this matter? Because comments decay. They become outdated, they get ignored, and they add noise. Self‑explanatory code, on the other hand, stays accurate as long as the name stays accurate. It also forces you to think about the why behind each piece, which often leads to better design decisions.
Wielding the Power (Code & Examples)
Let’s see the transformation in action. Below is a typical “before” snippet that leans heavily on comments to explain what’s happening.
Before – Comment‑Dependent Code
# Calculate the total price for a shopping cart
def calc_total(items):
total = 0 # start with zero
for i in items: # iterate over each item
if i['discount'] > 0: # if the item has a discount
price = i['price'] * (1 - i['discount']) # apply discount
else:
price = i['price'] # no discount
total += price # add to running total
# apply tax if total exceeds $100
if total > 100:
total *= 1.08 # add 8% tax
return total
The comments are helpful, but they’re also a maintenance liability. Imagine the tax rate changes to 7.5% or the discount logic becomes more complex—now you have to hunt down every comment and keep it in sync.
After – Self‑Explanatory Code
def calculate_cart_total(items):
subtotal = sum(_apply_discount(item) for item in items)
return _apply_tax_if_needed(subtotal)
def _apply_discount(item):
if item['discount'] > 0:
return item['price'] * (1 - item['discount'])
return item['price']
def _apply_tax_if_needed(amount):
if amount > 100:
return amount * 1.08 # 8% tax
return amount
What changed?
-
Function names read like sentences:
calculate_cart_total,_apply_discount,_apply_tax_if_needed. -
Variables (
subtotal,amount) convey their role at a glance. - The logic is split into tiny, pure functions that each do one thing—making the flow obvious without a single comment.
If the tax rule changes, you only touch _apply_tax_if_needed. If discount calculations become more elaborate, you edit _apply_discount. The main function stays a clear, high‑level overview: “get the subtotal, then maybe add tax.”
Common Traps to Avoid
-
Over‑abbreviating names –
calcTot,itm,disc. Short names save a few keystrokes but cost hours of confusion later. - Leaving stale comments – A comment that contradicts the code is worse than no comment at all. If you feel compelled to comment, ask yourself: “Can I rename something to make this obvious?”
- Creating god‑functions – Even with perfect names, a 200‑line function is hard to follow. Break it down; each piece should be a single, named intention.
Why This New Power Matters
Adopting this habit transformed how I work. Code reviews now focus on logic and edge cases rather than deciphering what a variable meant. Onboarding new teammates feels less like handing them a cryptic map and more like giving them a clear guidebook.
Most importantly, it reduces the mental tax of “comment drift.” When the code speaks for itself, you spend less time fixing mismatched documentation and more time building features. It’s like upgrading from a flickering torch to a steady lantern—you can see the path ahead, and you’re less likely to trip over hidden roots.
Your Turn
Try this on a small piece of code you’ve written recently. Pick a function or block that currently leans on comments, rename the variables and functions to express intent, and extract any tangled logic into helpers. Notice how the need for comments fades away.
Challenge: Refactor one messy function today and share the before/after with a teammate. Ask them: “Did you need any comments to understand what it does?” I bet they’ll say no—and you’ll feel that same rush of triumph I felt when I finally escaped that dungeon, lantern in hand.
Happy coding, and may your code always speak clearly! 🚀
Top comments (0)