A Philosophy of Software Design Part 2 - Working Code Is Not Enough
A Philosophy of Software Design treats software design less as architectural theater and more as the daily work of managing complexity. This part covers Chapter 3 Working Code Isn’t Enough and Chapter 4 Modules Should Be Deep. It uses only short key phrases from the source and turns the reading into summary, interpretation, and application.
The guiding question is: Where does quickly working code diverge from code that remains understandable tomorrow?
This is part 2 of a ten-part reading of A Philosophy of Software Design. The scope is Chapter 3 Working Code Isn’t Enough and Chapter 4 Modules Should Be Deep.
The operating principle remains: book notes are storage; insight cards are currency.
L0 · Entry
- Core sentence: Strategic programming treats future change cost as part of the design problem, not as a later cleanup task.
- Why read this: As AI tools and automation make code faster to produce, I want sharper standards for code that remains understandable and changeable.
- Initial hypothesis: In practice, working behavior can dominate design judgment. This range lowers working behavior to a minimum condition and treats deep modules as units of long-term investment.
- Author context: John Ousterhout is a computer scientist known for work in operating systems, distributed systems, Tcl/Tk, and software design education at Stanford.
- Scope: Chapter 3 Working Code Isn’t Enough and Chapter 4 Modules Should Be Deep
L1 · Captures
“tactical programming”
This names the habit of solving only the immediate problem. Fast local fixes can slowly make the structure slower to change. ^q01
“strategic programming”
This treats future change cost as part of today’s work. The habit needed here is small recurring design investment. ^q02
“deep modules”
This describes a module with a simple interface and substantial hidden capability. The useful measure is not class count but functionality per interface burden. ^q03
This public note does not reproduce long source passages. It uses chapter-level concepts and short phrases as anchors, then provides transformative summary and commentary.
L2 · Map
| # | Range | Summary | Main claim |
|---|---|---|---|
| 1 | Tactical programming | Prioritizes getting behavior to work while delaying structural cost | Completion may be fast while future change becomes slow |
| 2 | Strategic programming | Adds small design investments consistently | Design is a daily choice rather than a later rewrite |
| 3 | Module interface | Reduces the surface users must understand | A simpler interface lowers memory burden |
| 4 | Deep modules | Provide large functionality behind a small interface | Good abstractions absorb internal complexity |
| 5 | Shallow modules | Split code without reducing user burden | Division alone does not guarantee design quality |
Argument in one paragraph:
Strategic programming treats future change cost as part of the design problem, not as a later cleanup task. In practice, working behavior can dominate design judgment. This range lowers working behavior to a minimum condition and treats deep modules as units of long-term investment. In practice, this moves review questions from “does it work?” toward “what must the next reader know in order to change it safely?” Design is not a separate ceremony; it is embedded in names, boundaries, exceptions, comments, layers, and performance choices.
L3 · Insight Cards
- A Philosophy of Software Design - I2.1 Working behavior is the start of design judgment, not its finish line
- A Philosophy of Software Design - I2.2 A deep module is evaluated by the burden it removes from users
- A Philosophy of Software Design - I2.3 Strategic programming is repeated small investment, not a heroic rewrite
L4 · Production Board
- Blog draft: Part 2 as “Working Code Is Not Enough”
- Code review question: Where does quickly working code diverge from code that remains understandable tomorrow?
- Insight card: Working behavior is the start of design judgment, not its finish line
L5 · Review
- Connections: This stands in tension with YAGNI: avoid speculative generality, but also avoid tactical blindness to future change.
- Open questions:
- Where does this part’s red flag appear most clearly in my current codebase?
- What check would an AI coding agent need in order to apply this principle reliably?
- Final takeaway: A deep module is not one that hides for its own sake; it lets users know less while doing more.
댓글
GitHub 계정으로 의견을 남길 수 있습니다. 댓글은 GitHub Discussions에 저장됩니다.