A Philosophy of Software Design
John Ousterhout's short book arguing that the central problem in software is complexity, that complexity accumulates through small decisions, and that the standard advice about small functions often makes it worse.
- First published
- 2018
- Publisher
- Dpunkt.Verlag GmbH
- Pages
- 193
- Shelf
- Technology
- Level
- Core
- ISBN-13
- 9781732102217
Record checked against
Only one source carried a publication date for this work, so the year is uncorroborated.
Catalogue note
- Reads as
- TechnicalAssumes and builds craft knowledge.
- Level
- Core / BuildingAssumes general familiarity with the subject.
- Approach
- Applied
- Written for
- Engineers, Readers with some grounding
Saved in this browser only — no account, nothing sent anywhere. My library
Read this if
- You build software and want the ideas under the tools.
- You care why some things are obvious to use and others are not.
- You keep fixing symptoms and want to see the structure producing them.
- You work in this area and want depth rather than an overview.
- You know roughly how the subject works and want the fuller account.
Complexity as the subject
His definition is operational: complexity is anything about the structure of a system that makes it hard to understand or modify.
His three symptoms are the useful part — change amplification, where a simple change requires edits in many places; cognitive load, the amount a developer must know to make a change; and unknown unknowns, where it is not obvious what must be modified. The third is the worst because there is no way to discover it before being wrong.
Unknown unknowns are the worst kind of complexity, because nothing tells you what you needed to know.
Devmark’s reading — not a quotation from the book
Deep versus shallow modules
His central concept. A module's value is the ratio of the functionality it provides to the complexity of its interface. A deep module offers a simple interface over substantial functionality; a shallow one has an interface nearly as complex as its implementation.
His argument is that shallow modules add cost without benefit, because the interface must be learned and the implementation is not hidden by it.
The direct argument with Clean Code
Ousterhout states explicitly that he disagrees with the advice to make functions as small as possible, and the book is partly a response to it.
His position is that decomposing aggressively produces many shallow modules, that the resulting indirection is itself complexity, and that a developer following a single operation through a dozen tiny methods is worse off than reading one longer coherent function. The disagreement is genuine and both positions have serious practitioners.
Information hiding and leakage
His treatment of what a module should conceal, and of the ways design decisions leak across boundaries — including temporal decomposition, where code is structured by the order operations happen rather than by what knowledge they need.
His observation that temporal decomposition is a common and rarely recognised source of leakage is one of the book's more original contributions.
Different layer, different abstraction
His rule against pass-through methods and pass-through variables: if adjacent layers have similar abstractions, the layering is adding indirection without adding anything.
The diagnostic is simple and catches a great deal of unnecessary structure in real codebases, particularly in systems built by applying architectural patterns uniformly.
Define errors out of existence
His most contrarian chapter. Rather than handling every exceptional case, redefine the interface so the case is not exceptional — his example is a delete operation that succeeds whether or not the item existed.
His argument is that exception handling is a major source of complexity, and that much of it exists because an interface was designed to make ordinary situations into errors.
Much error-handling complexity exists because an interface turned an ordinary situation into an exception.
Devmark’s reading — not a quotation from the book
Comments as design
His position on comments is the opposite of Clean Code's: comments should describe things the code cannot, and the act of writing them is a design technique because an interface that is hard to describe is badly designed.
His comments-first discipline — write the interface comment before the implementation — is the concrete practice, and it uses documentation as a design test rather than as an afterthought.
Strategic versus tactical programming
His framing of the underlying attitude: tactical programming optimises for getting the current feature working, strategic programming invests a small proportion of time in structure that keeps future changes cheap.
His estimate of ten to twenty per cent investment is arbitrary, as he acknowledges, but the framing — that complexity accumulates through individually reasonable tactical decisions — is accurate and useful.
Where it is limited
It is short, opinionated, and based on the author's experience teaching a software design course and building systems, with no evidence beyond that.
The examples are also drawn from systems programming and from student projects, and readers working on web applications or data pipelines will have to translate more than the book acknowledges.
How to read it alongside Clean Code
The honest position is that both are practitioner opinion, that they genuinely disagree, and that the disagreement is about a real trade-off rather than one of them being wrong.
Read both and hold the tension. Martin is better on naming, tests and professional responsibility; Ousterhout is better on modularity, interfaces and the costs of over-decomposition.
What to take away
- 01Deep modules, simple interfacesA module's value is functionality divided by interface complexity, which makes shallow ones pure cost.
- 02Over-decomposition is itself complexityFollowing one operation through a dozen tiny methods is worse than reading one coherent function.
- 03Temporal decomposition leaksStructuring code by the order things happen rather than by what knowledge they need is a common hidden cost.
- 04Design errors out of the interfaceA great deal of exception handling exists because the interface made an ordinary case exceptional.
- 05Write the comment firstAn interface that is hard to describe is badly designed, which makes documentation a design test.
