Naming & Readability

Clean Code, SOLID & Refactoring

Chapter 2 · Naming & Readability

Chapter 1 measured what "clean" costs to change. This chapter is about the cheapest lever for getting there: names. Not as a style preference — this chapter verifies three specific, concrete costs bad naming carries, each measured directly rather than asserted.

Mental Mapping Hides Bugs From Even a Trivial Check

A classic real bug: copy-pasting a domestic-shipping calculation into an international one, and forgetting to update one variable reference.

# CRYPTIC def calc_international_bad(w, d): base = w * 2.5 fee = w * 0.1 # BUG: copy-pasted, forgot to change w to d return base + fee # DESCRIPTIVE def calculate_international_shipping(weight_kg, distance_km): base_cost = weight_kg * 2.5 distance_fee = weight_kg * 0.1 # the SAME bug, copy-pasted the same way return base_cost + distance_fee
Verified directly — both versions compute the identical wrong result
Called with weight 10 and distance 500: both the cryptic and descriptive versions return 26.0. The correct result — using distance for the distance fee — is 75.0. Neither version's own bug is hypothetical; both are real, silently wrong.
Verified directly — the cryptic name gives a checker nothing to check
The variable is named fee. There is no word in that name promising what it should be computed from — a consistency check comparing the name against its own source variable literally cannot be constructed, because fee makes no claim at all.
Verified directly — the descriptive name lets a one-line check catch the exact bug
The variable is named distance_fee — a name that promises its value comes from something related to distance. Checking whether the actual right-hand side (weight_kg) contains that promised word: False. The mismatch is caught immediately, using nothing but the name itself — no test run, no manual trace through the logic required.
Why this is the real argument for descriptive names
It isn't that distance_fee is more pleasant to read than fee — it's that a name carrying real information (what category of value belongs here) makes an entire class of copy-paste bugs mechanically detectable, by a human skimming the code or by a simple automated check, in a way a cryptic name structurally cannot support.

Consistent Vocabulary: Findable vs. Not

Verified directly — inconsistent naming makes a codebase's own functions unfindable by search
A small codebase using three different words for the identical operation — get_user, retrieve_order, fetch_product_data, get_invoice, retrieve_customer: searching for get_* finds only 2 of 5get_user and get_invoice. The other three, doing the same kind of thing, are invisible to that search. The identical codebase, using one consistent word (get_user, get_order, get_product, get_invoice, get_customer): the same search finds 5 of 5.
Why this matters beyond a single search
A developer trying to find "all the places we fetch something from the database" — for a security audit, a caching pass, a refactor — genuinely misses 3 of 5 real matches in the inconsistent codebase, with no error or warning telling them they missed anything. The search succeeded; it just wasn't looking at the right words, because the codebase never agreed on what the right words were.

Names as Documentation That Can't Go Stale — a Comment Can

def calculate_total(items): # returns the sum of item prices total = sum(item['price'] for item in items) total = total * 0.9 # NEW: apply a 10% loyalty discount return total
Verified directly — the comment is now false, and the function still "works"
For two items totaling $150: the comment claims the function returns the sum of item prices — that would be $150. The function actually returns $135.0. The comment is wrong by $15.00 — a real, measurable lie, sitting one line above the code that contradicts it, and nothing in Python enforces any relationship between a comment's own text and what the code beneath it does.
Why a name is different in kind, not just in convenience
A comment is a second, separate piece of text describing the code — the two can drift apart, as just verified. A function's own name isn't a separate description sitting near the code; it's how every caller refers to the code. If calculate_total had been renamed to calculate_discounted_total the moment the discount was added, that rename would need to happen at the exact same place the behavior changed — not several lines above it, easy to forget. This doesn't make a misleading name impossible, but it removes the specific failure mode just verified: a description silently going stale while nobody's looking at it.

Where This Connects

This chapter's findingWhat it connects to
A descriptive name making a copy-paste bug mechanically detectableChapter 1's own "blast radius" test — good naming is part of what made apply_tier_discount() safe to change in isolation
Inconsistent vocabulary hiding 3 of 5 real matches from a searchSoftware Architecture Fundamentals Chapter 5's own coupling analysis — a static search is only as good as the vocabulary discipline behind the code it's searching
A comment verified drifting $15 away from the truthChapter 9's own Technical Debt chapter — stale documentation is a specific, common form of debt this course names directly later

Hands-On Exercises

Exercise 1

This chapter's own name-based check only worked because distance_fee contains the word "distance". Rename it to extra_charge instead (keeping the exact same bug — computed from weight_kg) and verify whether this chapter's own consistency-check technique can still catch the bug. Explain what this reveals about the limits of the technique.

📄 View solution
Exercise 2

Add a sixth function to this chapter's own inconsistent codebase list, named obtain_shipment, and a corresponding one named get_shipment to the consistent list. Verify the get_* search results for both lists after the addition, and report the new totals.

📄 View solution
Exercise 3

Fix this chapter's own calculate_total example two different ways: (1) update the comment to match the code, and (2) rename the function to calculate_discounted_total instead and remove the comment. Verify both fixes produce a function whose documentation (comment or name) accurately reflects its behavior, and explain which fix is more likely to still be accurate after a second, future change nobody remembers to update.

📄 View solution

Chapter 2 Quick Reference

  • Mental mapping, verified costly: a copy-paste bug was undetectable by any name-based check with cryptic names, but caught in one line by checking a descriptive name against its own promised word
  • Consistent vocabulary, verified: a search found 2 of 5 real matches with inconsistent naming, 5 of 5 with consistent naming
  • Names vs. comments, verified: a stale comment was wrong by $15 with nothing enforcing its accuracy — a failure mode a name, tied directly to its own code, structurally avoids
  • Next chapter: Functions: Size, Purity & a Single Level of Abstraction