‘A Philosophy of Software Design’ commentary

✍️ Written on 2021-03-20 in 995 words. Part of cs software-development

Motivation

John Ousterhout is known for inventing the Tcl scripting language. In his Google Talk “A Philosophy of Software Design”, he reiterates on some of aspects developed as part of a course at Stanford and followingly, the concepts presented in his book.

Fundamentally, he describes the motivation as follows: “People have been programming computers for more than 80 years now, and yet software design is still basically a black art. There is essentially no agreement on how to do software design or even what a good piece of software looks like. We talk a lot about software engineering and software tools and testing and processes, but we have almost no conversation about the fundamental act of designing software. This has bugged me for a long time. So today, I’d like to tell you about some things I’ve been doing to try to change that to start the conversation. And to see, if we can somehow create a greater sense of design awareness in the software community“

Notes

  • “If you had to pick one idea… one concept… that’s the most important thing in all of computer science. […] What would you pick?” “I asked Don Knuth this question. He said ‘Layers of abstraction’ which I’d say is almost right. Though some would say ‘by definition it is right’”. What John would say is “problem decomposition” (how to chop a problem into pieces that you can build relatively independently)

  • Can problem decomposition be taught or is it some inherent skill?

  • CS190 course at Stanford, less like a programming course and more like an English writing course, 3000–4000 LOCs after 3 iterations of code reviews

  • How common is it in reviews to discuss design issues as opposed to coding style and bugs?

  • What is John’s opinion on Hyrum’s Law? That it is sad, but true.

What are the secrets to software design?

A few (somewhat vague) overall concepts:

  • Working code isn’t enough; must minimize complexity

  • Complexity comes from dependencies and obscurity

  • Strategic vs. tactical programming

  • Classes should be deep

  • General-purpose classes are deeper

  • New layer, new abstraction

  • Comments should describe things that are not obvious from the code

  • Define errors out of existence

    • Exceptions are a huge source of complexity

    • Common wisdom: detect and throw as many errors as possible

    • Better approach: define semantics to eliminate exceptions

    • Tcl unset command is a design mistake: it should not throw an exception if an unset variable is unset

    • Exceptions versus extra status codes? John thinks both approaches are justified, but exceptions provide the most value if you “throw them the longest” (across various abstraction boundaries)

  • Pull complexity downwards

Paper “On the criteria to be used in decomposing systems into modules”

Since, John mentioned the paper, I also read it. Here is a quote of my review:

It illustrates the decomposition of a system by two exemplary modularizations. Whereas the first decomposition was created along the major steps of the processing routines, the second decomposition was created with information hiding in mind. Then several recommendable criteria for decompositions are mentioned:

  1. A data structure, its internal linkings, accessing procedures and modifying procedures are part of a single module.

  2. The sequence of instructions necessary to call a given routine and the routine itself are part of the same module

  3. The formats of control blocks used in queues in operating systems and similar programs must be hidden within a “control block module.”

  4. Character codes, alphabetic orderings, and similar data should be hidden in a module for greatest flexibility

  5. The sequence in which certain items will be processed should (as far as practical) be hidden within a single module

In the end, I think the paper advocates a clean style which (in some sense and with some limitations) is still true today (e.g. web frameworks heavily limit the way you can define your architecture). I recommend every programmer to reflect about possible decompositions of a system, because the most intuitive one might not be the best. The notion of a flowchart approach being the sequential one, is however awkward and foreign to me.

It is important to put the paper into proper historical context. To the best of knowledge, it addressed questions resulting from the transition from assembly language to higher-level programming languages.

Conclusion

I think proper API design, system decomposition, and finding proper abstractions are skills that distinguish good from average programmers. Mostly, we don’t understand the entire application domain good enough to solve these questions in a rigorous manner. I think Tcl is a good tradeoff, John makes some good points more directed towards object-oriented programming whereas the paper discusses assembly language versus imperative programming. But in the end, I am neither aware of universal guidelines nor some didactical concept to teaching these skills.