A Philosophy of Software Design (英語) ペーパーバック – 2018/4/6
Kindle 端末は必要ありません。無料 Kindle アプリのいずれかをダウンロードすると、スマートフォン、タブレットPCで Kindle 本をお読みいただけます。
This book addresses the topic of software design: how to decompose complex software systems into modules (such as classes and methods) that can be implemented relatively independently. The book first introduces the fundamental problem in software design, which is managing complexity. It then discusses philosophical issues about how to approach the software design process, and it presents a collection of design principles to apply during software design. The book also introduces a set of red flags that identify design problems. You can apply the ideas in this book to minimize the complexity of large software systems, so that you can write software more quickly and cheaply.
PoSD is best read as a tactical guide of how-to’s. About a quarter of it is spent on naming and comments, and much of the rest is about specific patterns. His few attempts to jump from tactical advice to principles are either done by trying to blur together similar-sounding tips, or are hamstrung by his inability to see the meaning of a program beyond the code. He demonstrates the lack of principles comically in Chapter 19, where he promises to apply the books’ “principles” to several software trends, and then fills the rest of the chapter with standard (but solid) advice on unit-testing and OOP, with nary a reference to the rest of the book. On the whole, the book’s advice is higher-level than beginner books like Clean Code, but most of its contents will be familiar to a senior software engineer, and the novel parts are hit-and-miss.
A huge underlying theme of the book, and one of its few novel parts, is Ousterhout's idea of deep modules: modules should have an implementation which is simpler than the interface. This sounds elegant, and impossible to argue with. Unfortunately, it's also objectively wrong. Further inspection shows that actually many common abstractions like stacks fail this test, and even Ousterhout's own example of a deep module has an interface which is far more complex than he claims. Overall, Ousterhout misses the deeper notions of complexity, the kind which is about what a piece of code means and how it may be used and how it may be changed, rather than the kind that can be gleaned by glancing at the code. This is a major blindspot which damages the book significantly, and limits his ability to give precise advice.
When Ousterhout tells you do reduce complexity, it often sounds like telling someone going on a date or interview "just be yourself:" the advice only works if you already understand complexity.
Despite that, there is a lot of really good advice in this book, and it's explained with clear and concrete examples. I especially enjoyed his sections on comments. While I don't agree with everything in that section either, there are some really good points that I hope become common practice, and which I have not seen others write about. His chapter on performance engineering is also gold.
So, read the book, savor the advice, but take his justifications with a grain of salt and know that they're not universals, because there are deeper principles to be found.
I wrote a much longer review on my blog, going into these points in more detail. For my full review, see: http://www.pathsensitive.com/2018/10/book-review-philosophy-of-software.html
A Philosophy of Software Design is a good book, but not a great one. But it's one of the only books of its kind out there. Hence, I am proud to recommend it to all junior-level software engineers.
What bothered me the most is the lack of rigor, for instance, he advocates for incremental design which costs 10-20% and if you don't it will make you 10%-20% slower after some point. The only motivation a graph with no units. It may matter if is 10% or 20%, as that is after all a factor of 2. Also, it's not really clear that once in a while 10% investment, let's call it 45 minutes is a very different cost than a recurring daily 45 minute overhead due to cost being a mess. I don't have any data to dispute the numbers, btw, but on the other hand, I have not seen any studies to support it either, and the author does not tell us where he is getting this from.
His advise of avoiding lots of small functions as it means you will be bouncing all over the place to understand the code is not necessarily wrong. It adds lots of boiler plate, for example. Using an argument from the book itself, however, you could argue that good names and comments would mean you didn't need to read those lower level functions. The counter argument is that smaller functions are much easier to unit test. Then you have the unit test vs integration test discussion of course.
There are 3 chapters on comments. Why?! I am towards the "good code is self-documenting" end of the spectrum, although I would say a lot of comments is often (but certainly not always) a code smell that suggest refactoring using better names, extracting code to function etc. I do like how he describes good comments as either lower or higher level than the code.
The text editor example that runs through most of the book becomes trite. What I find way more interesting is when he talks about his experience with TCL (design mistakes, or the benefits derived from unit test suite), or towards the end RAMCloud and a specific implementation detail.
I love that this book focuses on reducing complexity. It gives very practical ways that I can reduce complexity in my software.
The author puts such a high value value on simplicity and it's so refreshing when so many of today's "best practices" lead to complexity.
This book is helping me become more design oriented and strategic -- and less of a "tactical tornado".
This books stays relatively high level and is philisophical, which makes it an easy read. There are practical examples, but not too many that it disrupts the flow.
I am going to buy moe copies for my team. I would highly recommend it to any developer or manager.