There are a lot of engineering books. They often have lots and lots of words but only one or two good chapters or ideas. Which isn’t that much fun, which leads to people not reading books.
The Philosophy of Software Design by John Osterhaut bucks that trend, and is packed with a lot of meaning in very few and consise pages. This makes it a great book club book. The topics involved can help a lot alignment around the philosophical mindset behind coding. It’s helped me with long running teams where they’d drifted in purpose, and on brand new teams where we were all getting to know each other. If you’re looking for an overview, there’s a youtube talk that’s ~1hr1.
In terms of guiding an engineering org, this book helps teams develop a shared understanding around the cost of complexity. In multi-team organizations every team has always asked “can we get the other teams to read this too?”.
The book covers 16 core concepts2, and they break up into nice 20-ish page sections for weekly discussions. In total this low-effort high-reward book club can be done in 5 weeks, about 30-45 minutes of reading each week.

Spaghetti is the enemy
Book Club Goals:
- Meaningful conversations
- Not too much reading each week
- Turn reading into adjustments to team processes/values
In the back of the book, there’s a “Summary of Design Principles” The goal is to break up the sessions to contain a few of those for discussion. When meeting to discuss walk through each chapter and relate it to current work, projects, or ongoing PRs. All the tradeoffs we make, even in little things, are relevant for discussion.
Tactically
- The reading should take about 45 min each week, it’s a small book
- Discussion should take about an hour
- Keep a running doc or slack channel for notes and thoughts as you go
- If you’re running the book club, try and prepare with some well known complex code from your codebase.
Week 1: Chapters 1-4
Principles Covered:
- Complexity is incremental, you have to sweat the small stuff
- Working code isn’t enough
- Make continued small investments to improve system design
- Modules should be deep
- Interfaces should be designed to make the most common usage as simple as possible
Some prompts:
- How might we start to get to having a lower tolerance for complexity?
- Any areas of our codebase that feel like “tactical tornados”?
- What might a team that has a strategic mindset value over a tactical approach?
Week 2: Chapters 5-9
Principles Covered:
- It’s more important for a module to have a simple interface than a simple implementation
- General purpose modules are deeper
- Separate general purpose and special purpose code
- Different layers should have different abstractions
- Pull complexity downward
Some prompts:
- How do we normally make design decisions?
- How do you think about where specialization should live when starting some work?
- How do you know, or define, the responsibility of a module?
Week 3 Chapters 10-13
Principles Covered:
- Define Errors out of existence
- Design it twice
- Comments should describe things that are not obvious from the code
Some prompts:
- How do we normally use exceptions in our code? How consistent are we in throwing?
- What errors are unimportant?
- If we don’t want to acutally design the whole thing twice, what are things we can do that get us close to that ideal?
Week 4: Chapters 14-16
Principles Covered:
- None called out specifically, but there’s a bunch in here
Some prompts:
- Is it better to give something a long descriptive name or a short unique name?
- How many people have tried “Comment Driven Design”? When is it helpful?
- What might help us avoid the added complexity of tactical fixes?
Week 5: Chapters 17-22
Principles Covered:
- Software should be designed for ease of reading, not ease of writing
- The increments of software development should be abstractions not features
- Separate what matters from what doesn’t matter and emphasize the things that matter
Some prompts:
- Where are we most and least consistent in our patterns?
- How long does it usually take you to understand what a module does?
- If you only read our code, what would you think matters most to us?
What next?
The rest is up to you.
Take a couple of the ideas that resonated most with the group and change a bit of process to encourage their use. Start to refer to these principles into code review. Use them to design the scope and shape of your pull requests. Let them do the work of representing a complex idea as it relates to complex code. Keep the ideas alive, and they’ll eventually flourish.
-
Watch it in doublespeed ↩︎
-
- Complexity is incremental: you have to sweat the small stuff
- Working code isn’t enough
- Make continual small investments to improve system design
- Modules should be deep
- Interfaces should be designed to make the most common usage as simple as possible
- It’s more important for a module to have a simple interface than a simple implementation
- General-purpose modules are deeper
- Separate general-purpose and special-purpose code
- Different layers should have different abstractions
- Pull complexity downward
- Define errors out of existence
- Design it twice
- Comments should describe things that are not obvious from the code
- Software should be designed for ease of reading, not ease of writing
- The increments of software development should be abstractions, not features
- Separate what matters from what doesn’t matter and emphasize the things that matter