In this chapter
We'll learn to write code for the next person who reads it — clear names, naming conventions, small focused functions, named constants and sensible code organisation — explained as writing a recipe card someone else will cook from.
The Problem in Real Life
Month eleven. Anna opens her biggest pull request yet: the new pricing rules — group discounts, student discounts and early-bird prices, all working together. The tests pass. She's proud of it.
The next morning, it has 31 comments. The first one, from John, is at the top: "Hard to read." Below it: "What is f?", "What does 0.85 mean?", "What is c here — a count? a code?", "This function is 140 lines long. What does it do?" Anna's face goes hot.
John pulls up a chair. "The code works. That's the easy part. But in six months, someone — maybe you — will have to change these prices in a hurry, before a big sale. Right now, they'd need an hour just to understand what it does. Let's make it take five minutes."
Code is read far more often than it's written. Write it for the reader.
John
Code Only Its Author Understands vs. Code Anyone Can Change Safely
Cryptic names
f, a, b, c, tmp, data2 — every reader has to guess what they mean.
Mystery numbers
0.85, 10, 72 — are they percentages, limits, hours? Nobody can tell.
One giant function
140 lines doing five different jobs — impossible to understand or test one part.
Readable Code, Naming Conventions and Code Organisation
The recipe card analogy: a recipe card written only for yourself might say: "Mix A and B, add 2, bake till done." You understand it today. A stranger — or you in a year — can't cook from it. A good recipe card says: "Mix the flour and butter, add 2 eggs, bake at 180 °C for 25 minutes." Same recipe, but anyone can follow it. Readable code is a recipe card written for someone else.
In Act 07 we met naming, comments and formatting. Now let's use them on real, messy code.
- Names that say what something is: a good name answers "what is this?" without the reader looking anywhere else:
ticketCountinstead ofc,basePriceinstead ofb,calculateGroupPriceinstead off. Longer is fine if it's clearer. Avoid abbreviations only you know (cnt,prc,usr) and vague words (data,info,temp,handle). - Naming conventions — everyone writes the same way: each language has its own conventions. In JavaScript/TypeScript:
camelCasefor variables and functions (basePrice),PascalCasefor classes and types (PriceRule),UPPER_SNAKE_CASEfor fixed constants (MAX_GROUP_SIZE). Python usessnake_casefor variables and functions. Database columns are oftensnake_case(Act 13). Follow your project's existing style — consistency beats personal taste. - Names by kind of thing: booleans read like yes/no questions:
isStudent,hasDiscount,canRefund. Functions start with a verb:calculateTotal,sendReminder,findOrderById. Collections are plural:seats,orders. - Named constants instead of magic numbers:
price * 0.85hides its meaning.const GROUP_DISCOUNT = 0.15;andprice * (1 - GROUP_DISCOUNT)explains itself, and if the discount changes, there's exactly one place to edit. - Small functions that do one thing: if you need the word "and" to describe what a function does, it probably does too much. Split the 140-line function into
applyGroupDiscount,applyStudentDiscount,applyEarlyBirdPriceand one short function that calls them in order. Each piece is easy to read, name and test (Act 17). - Early returns instead of deep nesting: five levels of
ifinsideifare hard to follow. Handle the special cases first andreturnearly, so the main path reads straight down. - Code organisation — things that change together live together: group code by feature (
src/pricing/,src/orders/) rather than scattering one feature across many folders. Keep each file focused on one job. Follow the project's existing structure (Act 16).
| Before | After | Why |
|---|---|---|
| f | calculateGroupPrice | Says what it does, starts with a verb |
| a | ticketCount | Says what it counts |
| c | isStudent | A boolean, reads as a question |
| 0.85 | 1 - GROUP_DISCOUNT | The number has a name and one home |
| tmp2 | priceAfterGroupDiscount | Says exactly what the value is |
| data | upcomingShows | Says what's inside |
| Kind | Convention | Example |
|---|---|---|
| Variables, functions | camelCase | basePrice, calculateTotal |
| Classes, types | PascalCase | PriceRule, OrderService |
| Fixed constants | UPPER_SNAKE_CASE | MAX_GROUP_SIZE |
| Booleans | is/has/can + camelCase | isStudent, hasDiscount |
| File names (often) | kebab-case | group-pricing.ts |
function f(a, b, c) {let t = a * b;if (a >= 10) {t = t * 0.85;if (c) {t = t * 0.9;}}return t;}
const GROUP_MIN_SIZE = 10;const GROUP_DISCOUNT = 0.15; // 15% off for groups of 10 or moreconst STUDENT_DISCOUNT = 0.10; // extra 10% for student groupsfunction calculateGroupPrice(ticketCount, basePrice, isStudent) {const fullPrice = ticketCount * basePrice;if (ticketCount < GROUP_MIN_SIZE) {return fullPrice; // early return: not a group}const priceAfterGroupDiscount = fullPrice * (1 - GROUP_DISCOUNT);return isStudent? priceAfterGroupDiscount * (1 - STUDENT_DISCOUNT): priceAfterGroupDiscount;}
Same results for every input — the tests prove it. Only the reader's experience changed.
Anna's rewrite: function f(a, b, c) becomes calculateGroupPrice(ticketCount, basePrice, isStudent). The three magic numbers become GROUP_DISCOUNT, GROUP_MIN_SIZE and STUDENT_DISCOUNT. The 140-line function becomes five small ones, each with a test. She renames tmp2 to priceAfterGroupDiscount and laughs out loud at how obvious the code suddenly looks. Nothing about what the code does changed — only how easily a human can see it.
Key Takeaway
Readable code is a recipe card for someone else: names that say what things are (ticketCount, not c), your language's naming conventions (camelCase, PascalCase, UPPER_SNAKE_CASE), booleans as questions, functions as verbs, named constants instead of magic numbers, small functions that do one thing, early returns instead of deep nesting, and code grouped by feature. The code does the same thing — but the next person can change it safely.
Why This Matters
Most of a developer's time goes into reading and changing existing code, not writing new code. Readable code makes every future change faster and safer, makes reviews quicker, and is one of the clearest signs of a professional — interviewers and reviewers notice naming and structure immediately.
The code reads well now. But some things can't be said by names alone: why student groups get an extra discount only on top of the group one, and where the full rules are written down for Samantha's team.
