ousterhout-software-design
Skill0 starsChanged 26 days agoMITView on GitHub
Knowledge base from \"A Philosophy of Software Design, 2nd Edition\" by John K. Ousterhout. Use when applying Ousterhout's frameworks for managing complexity, deep modules, information hiding, strategic programming, comments, naming, and everyday software design decisions, or when studying/referencing the book's concepts.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- tslateman/skillstheir own version, first seen Oct 11, 2026
- BipBop-Labs/bipbop-skillstheir own version, first seen Oct 2, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- BipBop-Labs/bipbop-skills★ 3same name
- tslateman/skills★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository9 other files it gives its agents.
- AGENTS.mdAGENTS.md
- effective-goSkill
- git-commitSkill
- github-publishSkill
- github-releaseSkill
- github-topicsSkill
- matklad-architectureSkill
- nystrom-game-programming-patternsSkill
- silber-pixel-artSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 3 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 14
With a topic: - ask about complexity, deep modules, comments, errors, performance, etc..
- Very specific: line 15
With a chapter: - ask for ch04 or "chapter 4".
- Distinctive: line 16
Browse: - ask "what chapters do you have?" to see the full index.
- Distinctive: line 18
When you ask about a topic not fully covered in Core Frameworks below, I read the relevant chapter file(s) before answering.
- Distinctive: line 38
Pull complexity downward: When a module has unavoidable, related complexity, absorb it internally rather than punting to many callers (a …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- argument-hint: [topic, framework name, or chapter number like ch04] -->A Philosophy of Software Design (2nd Edition)
Author: John K. Ousterhout (Stanford; creator of Tcl) | Pages: ~190 (210 PDF) | Chapters: 22 | Generated: 2026-08-02
How to Use This Skill
- Without arguments - load the core frameworks below for reference.
- With a topic - ask about
complexity,deep modules,comments,errors,performance, etc.; I find and read the relevant chapter file before answering. - With a chapter - ask for
ch04or "chapter 4"; I load that specific chapter summary. - Browse - ask "what chapters do you have?" to see the full index.
When you ask about a topic not fully covered in Core Frameworks below, I read the relevant chapter file(s) before answering. For fast decisions, see cheatsheet.md (the 16 principles + 14 red flags as decision rules).
Core Frameworks & Mental Models
The book is about one thing: complexity. Complexity is anything that makes a system hard to understand and modify. Everything below is a lever against it.
Complexity (the enemy). Defined practically, not by size: C = Σ(cₚ × tₚ) - complexity of each part weighted by developer time spent there. Three symptoms: change amplification (one change touches many places), cognitive load (how much you must know), unknown unknowns (not obvious what to modify or what info you need - the worst). Two causes: dependencies (code not isolable) and obscurity (important info not obvious). Complexity is incremental - it accumulates in thousands of small chunks - so adopt zero tolerance. The positive goal is an obvious system. (Ch 2, 18)
Strategic vs. tactical programming. Tactical = "get it working now" (accumulates complexity); strategic = "produce a great design that also works" (invests continually). The tactical tornado ships fast and leaves wreckage. Invest ~10–20% of dev time continually (proactive + reactive); payback ~6–18 months; technical debt is mostly never repaid. (Ch 3)
Modules should be deep. Visualize a module as a rectangle: area = functionality, top edge = interface complexity. Deep = much functionality behind a simple interface. A simple interface matters more than a simple implementation. Interfaces have formal (code) and informal (comments) parts; informal is usually larger. An abstraction that omits important details is a false abstraction. Resist classitis. (Ch 4)
Information hiding (and leakage). Each module encapsulates design decisions invisible in its interface. The opposite - information leakage, a decision reflected in multiple modules - is a top red flag, often invisible (back-door leakage). Decompose around knowledge, not execution order (temporal decomposition is an anti-pattern). private ≠ hidden; getters/setters leak. Make the common case simple with defaults; "do the right thing without being asked." (Ch 5)
General-purpose modules are deeper. Over-specialization may be the single greatest cause of complexity. Make modules "somewhat general-purpose": functionality for today, interface not tied to today. Push specialization up (to callers) or down (to pluggable low-level modules). Eliminate special cases by designing the normal case to handle edges for free. (Ch 6)
Different layer, different abstraction. Each layer must earn its keep with a different abstraction. Pass-through methods (forward a similar signature, add nothing) and decorators signal confused responsibility - redistribute, expose, or merge. Same signatures are fine only for dispatchers and multiple implementations. Collect pass-through variables into a context object. (Ch 7)
Pull complexity downward. When a module has unavoidable, related complexity, absorb it internally rather than punting to many callers (a simple interface > a simple implementation). Avoid configuration parameters; auto-compute values and default them. Pull down only complexity that's related and simplifies elsewhere. (Ch 8)
Define errors out of existence. Exceptions are a major complexity source; reduce the places they're handled. Best: redefine semantics so the error can't occur. Else: mask low (TCP resends), aggregate high (one top-level handler), or just crash for unrecoverable, infrequent errors. Expose exceptions only when the info is genuinely needed outside. (Ch 10)
Design it twice. For each major decision, sketch ≥2 radically different alternatives; compare on ease-of-use for higher-level code first; choose, combine, or let the weaknesses drive a new design. Costs ~1–2 hrs for a class; hard for smart people to embrace, but the problems are just hard. (Ch 11)
Comments are a design tool. Comments capture what code can't and are fundamental to abstraction - without them, complexity isn't hidden. Describe the non-obvious (a first-time reader's view) at a different level than the code: lower for precision, higher for intuition; never repeat the code. Write comments first - a long/hard comment is a red flag (Hard to Describe) signaling a bad abstraction, not a writing problem. (Ch 12, 13, 15)
Choosing names. Names are abstraction: precise and consistent. Booleans are predicates; avoid generic nouns and type-encoding. If a name is hard to pick, the design may be muddy - let naming drive refactoring. (Ch 14)
Decide what matters. Structure around what matters; minimize what matters (and where it matters); emphasize it via prominence, repetition, centrality. Look for leverage - one decision that solves or clarifies many. "Good taste" = distinguishing important from unimportant; it underlies every other principle. (Ch 21)
The author's own distillation: 16 design principles and 14 red flags are in cheatsheet.md as decision rules.
Chapter Index
| # | Title | Key Frameworks |
| ch01 | Introduction (It's All About Complexity) | Two approaches to complexity; continuous design; red flags |
| ch02 | The Nature of Complexity | 3 symptoms; 2 causes; incremental; zero tolerance; obvious |
| ch03 | Working Code Isn't Enough | Strategic vs tactical; tactical tornado; 10–20% investment; technical debt |
| ch04 | Modules Should Be Deep | Interface/impl; formal/informal; abstraction; deep vs shallow; classitis |
| ch05 | Information Hiding (and Leakage) | Hiding; leakage; temporal decomposition; defaults; overexposure |
| ch06 | General-Purpose Modules are Deeper | Somewhat-general; push specialization; eliminate special cases; false abstraction |
| ch07 | Different Layer, Different Abstraction | Pass-through methods/variables; decorators; context object |
| ch08 | Pull Complexity Downwards | Simple interface > simple impl; avoid config params |
| ch09 | Better Together Or Better Apart? | Costs of subdivision; bring-together rules; split/join methods; depth > length |
| ch10 | Define Errors Out of Existence | Mask; aggregate; just crash; exception promotion |
| ch11 | Design it Twice | Multiple alternatives; compare; weakness-driven redesign |
| ch12 | Why Write Comments? The Four Excuses | Comments capture code-can't; fundamental to abstraction; refutes excuses |
| ch13 | Comments Describe the Non-Obvious | Precision vs intuition; interface vs implementation docs; cross-module |
| ch14 | Choosing Names | Precision; consistency; avoid extra words; Hard to Pick Name |
| ch15 | Write The Comments First | Comments-first workflow; comments as design tool; Hard to Describe |
| ch16 | Modifying Existing Code | Stay strategic; comments near code & once; check diffs |
| ch17 | Consistency | Cognitive leverage; document/enforce/when-in-Rome; invariants |
| ch18 | Code Should be Obvious | Whitespace; avoid generic containers; design for reading |
| ch19 | Software Trends | Interface vs impl inheritance; agile/TDD critique; patterns; getters/setters |
| ch20 | Designing for Performance | Awareness; measure; design around the critical path |
| ch21 | Decide What Matters | Leverage; minimize; emphasize (prominence/repetition/centrality); good taste |
| ch22 | Conclusion | Complexity as the one thing; investment compounds; design is fun |
Topic Index
- Abstraction / false abstraction -> ch04, ch06
- Agile development -> ch01, ch19
- Caching / performance -> ch20
- Change amplification -> ch02
- Classitis / shallow modules -> ch04, ch19
- Cognitive load -> ch02
- Comments (design tool, first, non-obvious) -> ch12, ch13, ch15, ch16
- Complexity (definition, causes, symptoms) -> ch02
- Composition vs inheritance -> ch19
- Configuration parameters -> ch08
- Conjoined methods -> ch09
- Consistency / invariants -> ch17
- Context object -> ch07
- Cross-module decisions / designNotes -> ch13, ch16
- Decorators -> ch07, ch19
- Deep modules -> ch04, ch06, ch08
- Defaults / "do the right thing" -> ch05
- Dependencies -> ch02, ch07
- Design it twice -> ch11, ch21
- Design patterns -> ch17, ch19
- Device drivers -> ch06
- Errors (define out / mask / aggregate / crash) -> ch10
- Exception handling -> ch10
- General-purpose modules -> ch06
- Getters/setters -> ch19
- Information hiding / leakage -> ch05
- Inheritance (interface vs implementation) -> ch19
- Investment mindset / technical debt -> ch03
- Leverage / decide what matters -> ch21
- Modifying existing code -> ch16
- Modular design -> ch04
- Naming -> ch14, ch18
- Obscurity / obviousness -> ch02, ch18
- Overexposure -> ch05
- Pass-through methods/variables -> ch07
- Performance -> ch20
- Pull complexity downward -> ch08, ch10
- Red flags -> ch01, ch02, ch05, ch07, ch09, ch13, ch14, ch15, ch18 (full list: cheatsheet.md)
- Repetition -> ch09
- Special cases -> ch06, ch10, ch20
- Strategic vs tactical programming -> ch03, ch16, ch19
- Temporal decomposition -> ch05
- Test-driven development / unit tests -> ch19
- Together vs apart -> ch09
- Unknown unknowns -> ch02
- Waterfall model -> ch01
- Zero tolerance -> ch02, ch03
Supporting Files
- glossary.md - all key terms with definitions and chapter refs
- patterns.md - the book's reusable techniques (when/how/trade-offs)
- cheatsheet.md - the 16 design principles + 14 red flags as decision rules, thresholds, and decision trees
Scope & Limits
This skill covers the book's content only. It is conceptual/design guidance, not a coding library - combine it with project-specific tools for hands-on implementation. For topics beyond this book (e.g. specific algorithms, domain architectures), check related skills or ask the agent directly. The book's examples are in Java/C++; the principles apply to any language and to non-class modules (functions, subsystems, services).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

