I tend to go through phases of reading books related to development, often reading a few back to back and then taking a break for a few years at a time. This isn't intentional but seems to be a natural cycle for me. Recently I've been reading them again, and the most recent book I read was John Ousterhout's A Philosophy of Software Design, and I wanted to make a few comments about it and to recommend it to others, because I think it's a worthy read for all developers.
I must admit, that I didn't actually look up John Ousterhout prior to reading the book (and now I feel it's criminal that I didn't already know his name): I simply picked up due to a recommendation from a friend of mine, and this meant I had a rather pleasant surprise about halfway through when Ousterhout mentions that he created TCL. As somebody who spent close to two years developing in TCL professionally (though I must say I've never used it outside of that role) I had to do a bit of a double take, and immediately go look him up. TCL is a dynamically typed language that can be used in a range of domains: the company I worked for used it extensively because of how well it could be interfaced with C. They used C for the core of their web application framework and then TCL was used to drive the interface and higher level business logic. The point though, is that Ousterhout has seen his fair share of development, system design and architecture, and it's clear he's picked up some excellent ways of working along the way.
Upon finishing the book I reached out to my friend to get his final thoughts on it, and while he liked it he felt that "Philosophy" was a bit of a strong word to use in the title. I do a agree to some extent, but I do think the word fits because it's definitely given me an alternative way at looking at the code I write. The book is not a detailed guide to architecture patterns, or hard and fast rules about how to put software together, but it does present a few generic guide lines and methodologys with which to approach software development.
The book opens with a discussion on what complexity means in software, and highlights that while complexity can not be eliminated from a large scale software solution, it can be handled, and sometimes that handling takes a little up-front investment. I wasn't entirely engrossed in this discussion, but that's not to say that I didn't get anything out of it, I just wanted to get to the meat of the book. That's where I was perhaps a little let down, because there is no grand overall idea presented, but instead a series of small ideas that work together. Of course, you've probably realised from that sentence alone what the deal is: the small ideas come together to make a grand whole, and I worked that out after the fact. There is no big summary or conclusion, it's simply presented as ideas and guidelines and left to you to deal with.
Anyone who's familiar with the concept of emergent behaviour knows that simple rules can build powerful systems, and that's how I believe Ousterhout's guidelines work. The ideas are not complicated or difficult to reason about, and they are easy to leverage both when considering your application architecture as a whole and on the fly as you write your methods and classes. I find it quite fascinating how he's managed to distill a few simple rules that impact your behaviour to the point of having a considerable impact, and the best part of them being simple is that you won't find yourself having to go back to the book to remind yourself about how some pattern works, or how something should be structured: this is more fundamental stuff and I believe that's how it can be considered a philosophy.
Whenever you modify any code, try to find a way to improve the system design at least a little bit in the process. If you're not making the design better, you are probably making it worse
John Ousterhout, A Philosophy of Software Design
I don't want to go ahead and bastardize the content of the book here, because I simply wouldn't do it justice. But one concept that's easily explained (and gives a good taster) is Ousterhout's classification for Shallow vs. Deep, which applies from high level structures such as modules, through classes and down to individual methods. The core idea is that complexity should be hidden away, meaning interfaces for code should be simple, and the code itself complex. If the interface is complex it'll necessarily become harder to use, and often more difficult to maintain. Sure, moving the complexity out of the public interface doesn't remove it, but it removes it from consideration by users for the module/class/method. Methods themselves may become more complicated internally, but I think it's fair to say that in most large systems, features and updates rarely involve rewriting existing code, more often than not they're about expanding interfaces or bolting in new modules, and utilising what's already in place. If the interfaces to the exsting code are simple and obvious then they should be easy to work with and re-use. This is what constitutes the definition of "Deep": Simple Interface - (more) Complex Implementation. In contrast, shallow classes and methods are those with detailed interfaces, resulting in relatively simple code because the complexity is often being deal with by the caller, which as you can imagine puts the burden of complexity on said caller and results in all code using the module assuming the complexity instead, which significant effect on a lot more of the code base.
These ideas may not be for you, you may even fundamentally disagree with them if you're of the persuasion that no method should ever be longer than 10 lines of code, but for me the book really works, and that's why I think all developers should read it. Even if you do disagree in some of the core concepts there's bound to be something of benefit in the book for you.