About "A Philosophy of Software Design" book

About "A Philosophy of Software Design" book

I recently read John K. Ousterhout book A philosophy of software design. The author encourages to keep in touch with him to discuss or relate experiences related to the book. This is the email I would have sent to him. To enjoy this article it would be nice that you've read already the book.


Hello!

I am Cesc, tech lead in a small company based in Barcelona. I have read your book "A philosophy of Software Design" (the 2nd edition). That's the one: https://www.amazon.com/gp/product/B09B8LFKQL/ref=kinw_myk_ro_title

I really enjoyed it and I would like to complement it with some of my findings. There is also a small part where I do not agree fully and maybe I can give you something to think about - I don't expect you to change opinion or anything - after all you wrote a book! (I aspire to do so one day), and well this is just my opinion, that nobody asked for it, but here it is nonetheless.

Starting from the beginning, I really like the simple definition of complexity and all the insights you give about how to reduce it. It's like you put down to words many of the things that I had as "intuition".

In your chapter 3 you put a figure explaining the differences of strategic and tactical programming, with the note "you are not aware of empirical measurements of the precise shapes". I don't expect to ever be some empirical measurement of that, but there is the book "Accelerate" (https://www.amazon.com/gp/product/B07B9F83WM/ref=kinw_myk_ro_title) where they do have a lot of "empirical measurements" just that it doesn't match exactly the definition of "tactical" and "strategic" programming, and it's more on a "higher-level" on architecture, and having it coupled or decoupled.

It would be nice to maybe find a relationship where your definitions match the research from Accelerate. After all, "architecture" is just software, and even a small piece of code -software- can be coupled or decoupled, depending on "what matters" to other parts, which would mean "tactical" or "strategic" programming.

I also wanted to bring DDD to the picture. I am quite a practitioner and I read your book through a DDD lens, and it does actually translate quite well. When you say "modules should be deep", it is equivalent to having a "rich domain". The opposite of a rich domain is an anemic domain where classes have little meaning and can be misused and workaround it. It's considered an anti pattern, but some might say that has its use cases. Now, thanks to you, I can argue that having a rich domain reduces complexity, by having deep modules and hiding information properly.

And when you say that "general purpose modules are deeper", at first I was disagreeing, but after thinking about it, I think it's about "modeling properly". Many - if not all- DDD practitioners just focus on the tactical aspects - about the patterns and kind of use a one size fits all solution. But the first book of DDD is focused almost purely on modeling the domain properly, it explains that at some point, after having gone through some inevitable bad modeling phases, one reaches some "breakthroughs" and models it better and everything becomes simpler.

I can confirm with my experience that modeling properly definitely makes everything simpler, and that models change over time, and that if you take into account your advice of "general purpose" modules, you are more likely to have it "right" from the beginning. It's like a clue that helps decide "what matters" and focus on what one needs to properly model.

You see I am quite focused on something that you might feel is a subset of what you're talking about. You're talking about all programming and software development in general, libraries, even designing languages etc, and I am focused only on working applications, but I do think DDD is applicable everywhere - the "modeling" - the deciding what matters. Maybe some tactical patterns won't be applicable but the DDD philosophy will, and I think it quite right matches with your point of view.

And now with the part that I don't fully agree with, probably I am not the only one, and it's about comments. It's not that I am against writing comments, but if you had written all the related chapters about comments:

  • why write comments? the four excuses

  • comments should describe things that aren't obvious from the code

  • write the comments first

I would have completely agreed with you if you'd replaced the word "comment" for "test" in all the chapters!

It really does match! For example about the excuses:

"Why developer don't write comments, they usually justify their behavior with one or more of the following excuses:

  • Good code is self documenting.

  • I don't have time to write comments

    • Comments get out of the date and become misleading
  • the comments I have seen are all worthless"

If you change the above paragraph the word comment -> test, it could be exactly the same. With the advantage that the third point "comments get out of date and become misleading" might never happen if someone has - as they should- a pipeline that executes tests. Then they will be forced to keep them up to date.

And that's just one of the many advantages of tests with respect to comments.

I don't argue for not commenting anything, comments really helped me, especially one I am new in a language and I don't understand the proper syntax yet - it happened to me recently with Golang -. If somebody writes a library and expects it to be used by others, I agree that documentation should be mandatory, and it normally is, you can see the default docs for rust cargo crate or go packages.

But comments for internal stuff that is not exposed to the API meant to be used, can be rapidly a waste of time, the solution to explain the code should not be a comment, but a test.

You argue to write the comments first, that it helps you better design the API. To me that has always been the job of a test, with the advantage that the test can be executed and can fail or pass. Tests are supposed to explain how the API/your code is meant to be used, how the module is meant to be used, and they should always be "black box tests". That's the fuss about TDD because it helps design better the API, first you think about what you want to achieve with your module, so you write it in the test, using the signature of the methods etc - the exact advice you give about writing comments first. TDD is not about mechanically and without thought just writing a test for a class and then making it pass - as you say that leads to tactical programming -. TDD can and should be used for strategic programming, and it has the advantage with respect to comments that they will always be up to date - as long as you have a pipeline.

Having said that, I think one can be way more relaxed about comments, and less relaxed about tests. Comment will help of course, but tests will give you security that a comment cannot.

Final note about comments, when you divide among four categories, only, and only about the "implementation comments" I agree with Uncle Bob where in that case a comment is a kind of a failure: an implementation that could not have been simple or elegant enough to be understood at first glance, and as I think that tests should be black boxed always, a test might not help in this case. Unless you can refactor it a little bit. Where I find myself writing more of these comments is when I feel I don't understand the language programming syntax quite well, so I need to explain what I am doing. Anyway I won't feel bad by adding comments of that kind.

And to end I would like to go through the software trends chapter, you didn't put DDD as a trend and I am surprised! It might fall into the "design patterns" category maybe, but that would be only the tactical DDD and then what you say matches perfectly. To me DDD goes together with agile development (btw I like the insight that agile development should focus on strategic programming - I will try to be more explicit with that) and clean architecture, maybe those are more focused on a subset of software development but I do think those practices complement the ideas and philosophy of your book.

I already said what I think about TDD, - should be the equivalent of the "write comments first" of your book. Getters and setters are a terrible practice that many DDD practitioners fall for, they lead to an anemic domain, especially the setters, and I will always ask why a setter is necessary, instead of something with more meaning. And it's not on the software trends chapter but on the naming chapter, where I agree with you that the GO lang point of view of naming things is completely rubbish (well you didn't use these terms exactly). Speaking about GO, i am also surprised that as a software trend there were no microservices - I say it coming from GO because I believe those are quite misunderstood in the GO community, it's a problem very very related to your chapter "better together or better a part" - again I might be speaking about architecture, but architecture is software and you are speaking about software-. microservices should be a way to decrease complexity, that's why the boundaries are important and all your advice about "modules" can be applied to microservices, which can also be applied to a "bounded context" in DDD which is the strategic pattern that should be used as a microservice boundary. Being able to test easily what matters also helps with the design - not the comments :), sorry I am just teasing.

And also sorry for all of this verbal diarrhea, I wrote it in one go and it might be missing structure, but I have been thinking about it for a while.

I am well aware that this is probably an unwanted opinion. I do have a blog with plenty of those! (https://blog.cesc.cool/, I'd like to even publish this email there - I am just doing that right now!). But I think you can make use of it, maybe to come up with even better arguments of your convictions, or you'll find a new novel point of view thanks to that? My ego needs to think that I might have been helpful by writing this.

I hope this email finds you well and, in case it wasn't properly expressed, thank you very much for writing your book, I really enjoyed it and I made it my own now. Thanks!

Sincerely,

Cesc