The Pragmatic Programmer — key concepts
Hunt and Thomas treat programming as a craft built from daily habits rather than rigid process: keep every piece of knowledge in one place (DRY), design orthogonal components that don't tangle, and never live with a broken window of sloppy code, since neglect compounds into software entropy. They also argue a working programmer should treat their skills as a Knowledge Portfolio to invest in continuously, and that software good enough to meet the user's real requirements beats a perfect design that never ships.
DRY (Don't Repeat Yourself)
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. Hunt and Thomas apply DRY beyond copy-pasted code to comments, documentation, database schemas, and build scripts, anywhere the same fact is expressed twice, a later change has to be remembered and repeated in every place it appears.
Orthogonality
Two components are orthogonal when a change to one has no effect on the other, a term borrowed from geometry. Hunt and Thomas argue for decoupled, self-contained modules connected through minimal, well-defined interfaces, since an orthogonal system is easier to test in isolation and safer to change without unpredictable ripple effects elsewhere.
Broken Windows and Software Entropy
Borrowing the broken-window theory of urban decay, Hunt and Thomas warn that a single unrepaired flaw (an ugly hack, a bad name, a shortcut taken under deadline pressure) signals that nobody cares, and invites more of the same. Left unaddressed, small neglect accumulates into software entropy; their rule is to never live with a broken window, even temporarily.
Tracer Bullets
Tracer bullets are thin, working, end-to-end slices of the real system, built to see exactly where the design lands, in contrast to prototypes meant to be thrown away once they've answered a question. Because tracer code ships and grows into the finished product, it gives the team early, honest feedback and a visible target instead of a disposable mock-up.
Programming by Coincidence
Code that happens to work, because of accidental timing, an untested edge case, or a lucky guess about how a library behaves, is programming by coincidence rather than programming by intent. Hunt and Thomas warn that a developer who cannot explain precisely why their code works has no way to know when the next change will break it.
Answer these before you check.
These are the kind of open questions Recall asks in a real review session — no multiple choice, no re-reading the highlight first. Try answering out loud or on paper, then open the reveal to self-grade.
01What does DRY actually prohibit, according to Hunt and Thomas, and why isn't it the same rule as "don't copy and paste code"?
DRY prohibits duplicated knowledge, not duplicated text. Two functions can share several identical lines without violating DRY if they express unrelated facts that happen to look alike and could reasonably evolve apart. Conversely, the same business rule spelled out in a validation function, a database constraint, and a paragraph of documentation violates DRY even though no code was literally copied. The real test is whether a single change in requirements would force a developer to hunt down and update several separate places by hand; if so, that knowledge needs one authoritative home instead.
02Why do Hunt and Thomas insist that even a small, seemingly harmless piece of bad code should never be left in place "for now"?
They borrow the broken-window theory from criminology: a single unrepaired flaw signals that quality doesn't matter here, and that signal invites more sloppiness, the same dynamic observed in neighborhoods where one broken window goes unfixed. The response doesn't have to be a rewrite. It can be as small as leaving a warning comment, renaming a variable, or reverting to a simpler design until there's time to do it properly. What matters is that the fix is visible, because a codebase that visibly gets cared for keeps getting cared for, while one that looks abandoned keeps decaying further.
03How does a tracer bullet differ from a prototype, and why do Hunt and Thomas prefer it for exploring an uncertain design?
A prototype is deliberately disposable: a rough, fast exploration of one uncertain area, built to answer a question and then be thrown away. A tracer bullet is thin but real, a minimal slice wired through every layer of the actual system, from interface to storage, that the team keeps and builds on rather than discarding. Hunt and Thomas prefer tracer code because it exposes integration problems early, gives the team a working target instead of an approximation, and shows stakeholders visible, honest progress toward the real system rather than a convincing mock-up of one.
This is a one-time snapshot. Recall keeps testing you on it.
Import your own highlights from The Pragmatic Programmer (or any book) and Recall generates fresh open questions, grades your free-text answers, and schedules the next review with spaced repetition — so the concepts above don't fade in a month.