DEV Community

Hector Williams
Hector Williams

Posted on

A Book Review of A Philosophy of Software Design-how to create software that is easy to maintain

Introduction

A while back I was given a list of books to read in order to become a world class software engineer.One of these books was A Philosophy of Software Design by John Ousterhout. As the title implies, this book describes a way to design software. I would add how to design software that is easy to maintain.

As experienced engineers know, software engineering isn't just about creating software. User requirements may change in the future and new features may need to be added,bugs may be discovered in the existing functionality or changes in the existing codebase to make the code more efficient may be needed.

However, changing the existing codebase to incorporate these changes may interrupt existing functionality. This usually occurs because the code written was complex in the first place.

Complexity

The book describes two reasons for complexity:dependencies and obscurity. Dependency arises when one piece of code can't be changed without affecting others.Obscurity happens when important information isnt obvious.

The author also describes 3 symptoms of complexity.

1.Change Amplifications
A simple modification requires a lot of changes due to the fact that there are a lot of dependencies.

2.Cognitive Load
The developer needs to understand a lot of the codebase to make it easy to understand.

3.Unknown unknowns
It isn't obvious what pieces of code must be modified to complete a task or what information a developer must have to carry out the task successfully.In the author's opinion,this is the worst of the 3.

The author's proposed solution to eliminate or reduce code complexity is to make the code obvious. The book lists a number of ways that this can be done.

Programming Mindset

Software engineers are often in a rush to meet tight deadlines. As a result, they focus on writing code which works without thinking about the future. The author labels this as tactical programming and advises against it as due to its short sighted nature,it can lead to increases in the complexity of the code.

Instead the author recommends thinking with a strategic programming mindset. Here, developers must try not to introduce unnecessary complexity in the system. The focus must be on improving the design of the system where possible thus making it easier for other programmers to work in the future.

Modular Design

A technique the author recommends to reduce complexity is to use modules.This ensures that developers face a fraction of the system's overall completixy.The author advises to use deep modules-systems with a simple interface but a lot of complexity and advises against shallow modules-systems with a complex interface.

Information Hiding and Leakage

One way of creating deep modules is to use a technique known as information hiding. It involves providing other modules and users with a simple interface whilst hiding the implementation. People familiar with object oriented programming may know this as encapsulation.

In contrast, the author recommends against information leakage. This involves sharing of critical design information in multiple modules.This is a violation of the Dont Repeat Yourself principle of software engineering.

General purpose vs Special purpose Modules

Another approach the author proposes to reduce complexity is to use modules that are somewhat general purpose rather than special purpose. The former modules can cover a lot of use cases whilst the latter covers special cases. The difficulty is of course knowing what problems a module may solve today versus tomorrow.

Exception Handling

The author gives some advice that is controversial which is to define errors out of existence. This is because exceptions and errors may increase the code needed to deal with them and thus their complexity. However, this may not be always practical. I would say to minimize the errors you are dealing with where necessary.

Comments

The author makes another recommendation that is controversial. For those of us familiar with the book Clean Code by Uncle Bob, we were advised there to avoid comments where unnecessary. The author takes the opposite approach and recommends using comments as part of the system's design. We should start with comments.

He gives the reasons people give for not using comments and a reply as to why you should. He does raise some valid points. My recommendation having read both schools of thought is to use comments to explain design decisions and where the code may not be obvious. This should decrease the cognitive load.

Usage of Proper Names in Variables

The author recommends the use of variable names that are easy to understand, consistent and that create the right image in the minds of developers. This is one of the clean code guidelines recommended by Uncle Bob.

Consistency

The author recommends the use of consistency in naming, coding styles, interfaces, design patterns and invariants. This should reduce the cognitive load on developers. Those of us familiar with working on complex codebases will appreciate how much consistency helps.

Code Optimization

As experienced engineers know, the speed and memory usage of software is important when designing and implementing software. The author agrees but he does not think that this should come at the expense of increased code complexity.

Conclusion

The book argues that software design is an important part of the software engineering process. Designs where the code is obvious will make future work on that codebase easier. In contrast, code that is complex increases future work and makes bugs likelier.

This is something I agree with. Some of the recommendations are a bit controversial. You should look at the pros and cons of the error handling and comments advice before deciding.

The ideas put forward in this book are clear and practical. The book is short along with the chapters. In conclusion, I recommend this book for all software engineers.Which of Ousterhout’s design principles do you think is hardest to apply in your codebase, and why?

Top comments (1)

Collapse
 
jerryyorke profile image
Jerry Yorke

Loved your summary. “Unknown unknowns” hit home for me. On a legacy project, I once spent days tracing side effects just to fix what should've been a 10-minute bug. For me, the hardest principle to apply is keeping modules truly “deep” — deadline pressure always tempts us into shallow, leaky abstractions that feel faster now but hurt later.