Book Review – A Philosophy of Software Design by John Ousterhout

“A Philosophy of Software Design” by John Ousterhout is a short and thought-provoking book about practical software development.

Key Concept

The book starts with a bold claim – the most critical job of a software engineer is to reduce and manage complexity.

Mr. Ousterhout defines complexity as “anything related to the structure of a software system that makes it hard to understand and modify the system.”

This definition serves as a motivating principle for the book. The author explores where complexity comes from and how to reduce it in a series of short chapters, which often include real-world code examples.

My well-thumbed copy of the book

Summary

The book starts with identifying the symptoms of complexity:

  1. The difficulty in making seemingly simple changes to a system.
  2. Increasing cognitive load – i.e., a developer’s ability to understand a system’s behavior.
  3. The presence of “Unknown unknowns” – undocumented and non-obvious behavior.

Mr. Ousterhout states that there are two leading causes of complexity in a software system:

  1. Dependencies – A given piece of code cannot be understood or modified in isolation
  2. Obscurity – When vital information is not apparent. Obscurity arises due to a need for more consistency in how the code is written and missing documentation.

To reduce complexity, a developer must focus not only on writing correct code (“Tactical Programming”) but also invest time to produce clean designs, and effective comments and fix problems as they arise (“Strategic Programming”).

The book provides several actionable approaches to reducing complexity.

Some highlights:

  • Modular design can help encapsulate complexity, freeing developers to focus on one problem at a time. It is more important for a module to have a simple interface than a simple implementation.
  • Prevent information leakage between modules and write specialized code that implements specific features (once!).
  • Functions (or modules) should be deep – and developers should prioritize sound design over writing short and easy-to-read functions.
  • Consider multiple options when faced with a design decision. Exploring non-obvious solutions before implementing them could result in more performant and less complex code.
  • Writing comments should be part of the design process, and developers should use comments to describe things that are not obvious from the code.

The book concludes with a discussion of trends in software development, including agile development, test-driven development, and object-oriented programming.

Conclusion

“A Philosophy of Software Design” is an opinionated and focused book. It provides a clear view of the challenges of writing good code, which I found valuable.

Mr. Ousterhout provides actionable advice for novice and experienced developers by focusing on code, comments, and modules.

However, the book is also relatively low-level. The book contains little discussion around system design, distributed systems, or effective communication (outside of good code and effective comments).

While books such as “The Pragmatic Programmer” provide a more rounded approach to software engineering, I admire that Mr. Ousterhout sticks to the core concepts in his book.

On Forgiveness in UX Design

As engineers and designers, we need to focus on building products that have empathy and forgiveness for their users. 

Software is eating the world, but as it optimizes for engagement and retention, it leaves behind confused and exhausted users. 

Companies raise millions of dollars at billion-dollar valuations. With those valuations comes a drive to add new features. With the move to SaaS for everything, user interfaces and modes of interaction seem to change overnight.

Perhaps we could take inspiration from the consumer packaged goods industry. 

As a new father, I have changed diapers in various circumstances. In the dark, in the park, trying to mitigate a full-on meltdown and sometimes just trying to stem an avalanche of 💩. 

And yet, the diaper works as intended. Forgiveness is built into the design. I can operate it one-handed if I have to, and it gives some protection even when not used correctly. I can be confident that the design won’t change dramatically in the next iteration.

So, dear UX designer, next time you fire up Figma, think of the humble diaper, and a poor sleep-deprived dad dealing with a poop 🌋 at 3am. 

Think of the mistakes a user may make and design your application to forgive them and not punish them when they make those mistakes when addled, distracted, or simply exhausted.