My review of A Philosophy of Software Design by John Ousterhout
keywords
reviews programming2024-07-27
This review is also available as a video.
It’s hard for me to give much criticism about A Philosophy of Software Design, because the author, John Ousterhout, is an extremely accomplished computer scientist and software engineer.
The book is well-written and easy to read. The chapters and sections are organized in a way that allows for effective speed-reading. Each chapter has a conclusion section that summarizes the concepts nicely. At the end of the book, each design principle, as well as red-flags to watch out for, are explicitly listed out. I love that, because it makes the book useful as a quick, hands-on guide that could be kept close to your desk.
The author acknowledges that software design is not an exact science. There are always exceptions to the rules, and any principle should always be taken with a grain of salt. I like that, because it’s easy to get dogmatic about software design.
In Section 1.1, the author states that the philosophies presented in the book may be hard to appreciate without looking at actual code. He says that it was challenging to come up with meaningful code examples.
I would even take that a step further, and say that it’s hard to understand design principles without personally suffering through the adverse scenarios that they are intended to overcome or avoid.
With that in mind, I wonder if new software developers would benefit from reading the book. My opinion is that most of the principles presented in the book would be better suited for mid-level to senior software developers.
The author claims that complexity is the ultimate antagonist in software design. Each chapter of the book is dedicated to minimizing and avoiding complexity. I tend to agree with most of the principles presented throughout the book.
No one design principle stood out as particularly ground-breaking. Some of the principles did not resonate with me, possibly because I haven’t experienced the specific type of problem.
There were also some principles that I already try to adhere to, but perhaps without knowing how to articulate them clearly. So, it was nice to have them presented and labeled in a clear manner (For example, the principle about deep modules from Chapter 4).
The author challenges some of the popular philosophies that exist in software development. He advises against completing features quickly in a short-sighted fashion (“Tactical Programming”), because it sacrifices good design. This is a bit at odds with Agile development. He also criticises test-driven development, warning that it may place too much focus on simply getting features working.
As I read the book, I kept thinking about empathy. It may sound vague, but I believe that it is the key to making good software design decisions. You must have empathy as a software developer. Empathy toward your teammates; Empathy toward the future developers, who must read your code, or use your API; Empathy toward the users of the application you’re building.
It takes hands-on experience to develop empathy, so there’s not a quick way to to get better at it, in my opinion. Reading books like this can help you know what to look for, though.
There’s no doubt it’s a good book, but you must be careful not to get hyper-focused on software design. Sometimes over-worrying about design decisions can end up being almost as big of a problem as the thing you’re trying to avoid in the first place: complexity.
In summary, the book is well-written, easy to read, and presents a lot of good advice to keep in mind as you write software. It attempts to give meaningful examples of many problematic scenarios (often from the author’s student’s code). While definitely helpful, the examples are no substitute for real-world, hands-on experience, in my opinion. The ideas presented in the book seem grounded and logical.