The Pragmatic Programmer — Flashcards


Q: What is the ETC principle and why does it unify all design principles?
A: ETC = Easier to Change. Good design is design that adapts when requirements change. Every classic principle (DRY, SRP, decoupling, naming) is a special case: DRY because duplication means multiple places to change; SRP because focused modules change in isolation; good names because you have to read code to change it.


Q: What is the DRY principle, and how does it go beyond code duplication?
A: “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” DRY is about knowledge duplication, not just code copy-paste. Acid test: when one fact in the domain changes, how many places in the code must you update?


Q: What is orthogonality in software design?
A: Two things are orthogonal if changing one has zero effect on the other. Self-contained, single-purpose components. Benefits: changes stay local, tests are smaller, reuse improves. Orthogonality test: if a requirement changes, how many modules change? Should be one.


Q: What is temporal coupling, and why is it a problem?
A: Forcing a sequence of operations that isn’t required by the problem. “Method A must be called before B” when there’s no real reason. Creates bottlenecks, brittle ordering dependencies, and prevents concurrency. Fix by analyzing workflows for true vs. imposed dependencies.


Q: What’s the difference between tracer bullets and prototypes?
A: Tracer bullets are thin end-to-end slices of production-quality code kept in the codebase — used to validate architecture and get early feedback. Prototypes are exploratory, disposable code used to answer a specific question about one risky aspect of the system.


Q: What is the Broken Window Theory in software?
A: One bad design decision or piece of poor code left unaddressed signals to everyone that quality doesn’t matter. More breakage follows rapidly. Fix broken windows immediately; if no time, “board them up” — placeholder, TODO, comment. Pristine code encourages everyone to keep it that way.


Q: What does “Design by Contract” specify?
A: Each function has: preconditions (what the caller guarantees before the call), postconditions (what the function guarantees on return), and class invariants (what must always be true from the caller’s perspective). Violations are bugs, not error conditions.


Q: Why should you “crash early” rather than continuing after an error?
A: A program that has encountered something impossible is in an unknown state. Everything it does from that point is suspect. A dead program does less damage than a crippled one that corrupts data or continues in an invalid state.


Q: Why leave assertions on in production?
A: Testing doesn’t find all bugs. Production runs under conditions that don’t appear in tests (memory pressure, race conditions, unusual data). The argument “but we tested it” is false confidence. Turning assertions off removes your only runtime safety net.


Q: What is “programming by coincidence” and how do you avoid it?
A: Code that works but the developer doesn’t know why — relying on undocumented behavior, accident of ordering, coincidental context. When it breaks, you won’t know why either. Fix: always know why your code works. Only rely on documented behavior. Document your assumptions. Test them.


Q: What is property-based testing and when does it add value over unit tests?
A: You define invariants (properties that must always hold) and let a framework generate random inputs to try to violate them. The computer, unlike you, shares none of your assumptions. Complements unit tests: unit tests verify known scenarios; property tests explore the space you didn’t think of.


Q: What are the five basic security principles?
A: 1) Minimize attack surface area (less code, validate all input, remove unused services) 2) Principle of least privilege (request minimum permissions for minimum time) 3) Secure defaults (most restrictive settings by default) 4) Encrypt sensitive data (never store credentials in plain text or version control) 5) Maintain security updates (patch everything immediately).


Q: What is the “actor model” and why does it simplify concurrency?
A: Actors are independent virtual processors with private state that communicate only via one-way messages. No shared memory → no locks needed → no race conditions. Actors can run on one CPU, many CPUs, or distributed machines — same code.


Q: What is the “Pragmatic Starter Kit” and why are all three legs necessary?
A: Version control + ruthless testing + full automation. VCS drives builds and releases. Testing (unit, integration, validation, property-based) catches regressions early. Automation ensures repeatability and removes human inconsistency. Without all three, you cannot deliver reliably.


Q: What is requirements creep and how does iterative feedback prevent it?
A: Requirements gradually expand (“just one more feature”) as the project progresses, often without visibility into the cumulative impact. Short iterations with client feedback make each addition visible — the client sees the story card go up, can reprioritize, and experiences scope changes in real time.


Q: What is Conway’s Law and why does it matter for team structure?
A: Organizations produce systems that mirror their communication structures. Siloed teams produce siloed systems. Cross-functional teams that include users produce software that reflects actual user needs. If you want modular systems, structure your team to have modular communication.


Q: What is “policy is metadata” and how does it improve software design?
A: Business rules that change (who can access what, what percentage to apply) should be expressed as configuration/data, not hardcoded logic. Implement the general mechanism; put the specific rules in metadata. When policy changes, you update data, not code.


Q: What’s wrong with relying on code coverage as a testing metric?
A: Line coverage only tells you which code was executed, not which states were exercised. A 3-line function with two integer parameters has a million possible states — you can execute every line and still miss the one state that causes a bug. State coverage is what matters.


Q: What does “find bugs once” mean in practice?
A: Every bug a human tester finds should be the last time a human finds that bug. Immediately write an automated test for it, every time, no exceptions. The test runs in every subsequent build, guaranteeing the bug can’t resurface silently.


Q: What is the agile feedback loop, and at what levels does it apply?
A: 1) Work out where you are. 2) Make the smallest meaningful step toward your goal. 3) Evaluate where you ended up and fix anything you broke. Repeat — at every level: naming a variable, designing a module, scoping a project, running a team retrospective. True agility IS this loop, at every scale.


Q: What makes a name “good” according to the Pragmatic Programmer?
A: Names should reflect role (what the thing is for in the problem domain), not type or implementation. They should read as domain vocabulary so code communicates intent to future readers. Names that lie (a function called getData that writes to a file) are worse than meaningless names. Rename when names drift from reality.


Q: What is the “knowledge portfolio” metaphor and what does it prescribe?
A: Your professional knowledge is like a financial portfolio — it earns returns but also expires. Manage it like an investor: invest regularly (learn consistently), diversify (know current stack + adjacent areas), manage risk (mix safe/proven and experimental), buy low/sell high (learn emerging tech early), and rebalance (drop outdated knowledge). Key strategy: learn at least one new language per year.


Q: What is a “semantic invariant” and how is it different from a policy?
A: A semantic invariant is a fundamental, inviolate requirement that cannot change without changing the entire meaning of the system (e.g., “never process a transaction twice on a debit card”). Policies are business rules that change with management (e.g., “only supervisors can see X”). Invariants → code; policies → configuration/metadata.