Saturday, April 27, 2024

A Philosophy of Software Design: My Take and a Book Review The Pragmatic Engineer

a philosophy of software design

There isn't much to say about this, other than thatI intuitively agree. The book is also quite small and light which makes a great read for your daily commutes. The author emphasises the benefits of trying to stay in Technical Credit rather than Technical Debt. John, on the other hand, had the vantage point of having multiple teams solve the same design problem during a semester, with him observing. With each repeat, he was able to both validate and tweak his observations.

Event-driven programming makes code less obvious

I particularly like the way the author challenges conventional thinking within software industry and highlights the inefficiency in this thinking. Despite this, the critical issue in any software project is always how to successfully manage the complexity going forward. In the particular project I am architecting there are a lot of moving parts, integrations and complex workflows that need to be addressed, this can often result in spinning out of control quickly.

Chapter 13 — Comments Should Describe Things that Aren’t Obvious from the Code

This kind of decomposition has a different purpose to designingpublic interfaces, but sometimes get added to the public API of a class ormodule. The primary focus of the book is about attempting to eliminate or at least reduce complexity in software. This can be achieved by taking more time and consideration in the design and thinking about the implications of design. Related to the concept of deep modules is the advice to make them “somewhat general purpose”.

Comments

It's awell-structured, concise read about managing complexity in software design. An example of a deep module is the Unix/Linux system calls for I/O operations. There are five of them (open, read, write, lseek, close), and the signatures are simple, but they hide an enormous amount of implementation details on how files are stored and accessed on disk. In contrast, an example of a shallow module is the Java I/O classes. In order to open and read from a file, you need to use a FileInputStream, a BufferedInputStream and a ObjectInputStream.

A philosophy of software design - John Ousterhout

This means that the interface of some functionality should be a lot simpler than its implementation. That way, the cost of understanding and using the interface is lower than the benefit of the implemented functionality, thus helping to lower the overall complexity of the system. A module in this sense can be anything from a method or function, to a class or a subsystem. The goal of software design is to reduce the complexity of the system.

Writing up, sharing, and debating design with other peers is a practice more and more common in tech companies. This includes both whiteboarding and presenting to a group of peers, as well as more formal RFC-like design processes. While it might be less applicable to the course John taught, it's a practice that comes with many benefits. These days, as shared editing and commenting tools are more common, with editors like Google Docs and O365.

Case Study: A Philosophy of Automation - Automation.com

Case Study: A Philosophy of Automation.

Posted: Mon, 14 Dec 2020 08:00:00 GMT [source]

The author generally supports writing unit tests, which can catch problems during refactoring; he doesn’t like TDD. When fixing defects that can be tested beforehand, he suggests adopting TDD so that the test may verify that the bug was fixed once the required adjustments have been made. The book also introduces a set of red flags that identify design problems.

Whitespace can help break up code into logical blocks

There are multiple chapters on code comments; even Chapter 15 has the title “Write The Comments First” (Comments-first development?). He states, “Every class should have an interface comment, every class variable should have a comment, and every method should have an interface comment.” This way of thinking introduces a lot of noise in the code. Such comments need to be constantly synced with the changes in the code.

a philosophy of software design a philosophy of software design

However, it turns out that the most common use of unset was to clean up temporary state created by a previous operation. But it was hard to know how far the previous operation had progressed, so it was hard to know if a variable had been created or not. Thus you had to be prepared to handle exceptions from unset in a lot of places. It would have been much more useful, and simpler, if unset had been defined to mean that it ensures a variable with that name does not exist after it has been run, regardless of if it existed before or not. If your code throws an exception, you are forcing all callers of that code to be prepared to handle it if it happens.

Sharing design ideas upfront and opening a debate using these tools is a great way to build more sturdy architecture. Especially when applying the "design it twice" principle, and writing up alternative designs considered, and the tradeoffs why the other design was not chosen. Still, I wondered just how much I would learn about software design from experience partially distilled from a classroom - even if a Stanford classroom.

However, in my opinion, the documentation of a system is not the sum of the comments. It is a separate document that describes how the system fits together. Extracting the JavaDoc comments from all the classes does not become the documentation. Nothing highlights which classes are most important, and what the overall structure is. The chapter on optimization starts by listing typical times taken by various operations such as network communication, I/O to storage (disk, flash), memory allocation and cache misses.

Still, they all present interesting viewpoints, backed with examples. They also make for potentially sound advice to give, when mentoring less experienced engineers. Ousterhout argues that the best modules are those that provide powerfulfunctionality, but have a simple interface. He describes these as deep modules,in contrast to shallow modules, which have a complex interface but not muchfunctionality, thereby not hiding significant complexity. After that, you have to concentrate on speeding up the most commonly executed path. Currently maybe several method calls are used, but perhaps all the work could be done in a single method call.

Designing things twice (Chapter 11) is a suggestion that hits close to home. This is advice I've been suggesting to people to get better at designing systems, well before I read this book. This post summarizes key takeaways of the book and my take on these principles, drawing from my professional and industry experience.

It was one of the primary sources of making procedural/spaghetti code and the source of many unpredictable bugs. I agree with the author that we should write comments if we have to explain something tricky (such as an algorithm or something similar) or non-obvious (why, not how). In addition, the author mentions a famous API design antipattern involving overexposing internals, which later adds to an architecture debt. One way to make code more obvious to the reader is to have blank lines betweenparts that are logically separate, and maybe to preface the code block with animplementation comment. The overall complexity of a system can be determined by the complexity of eachpart, weighted by the fraction of time developers spend working on that part. Ifyou isolate complexity in a place where it will never be seen, then that'salmost as good as eliminating it entirely.

It continues with the standard advice of always measuring instead of assuming. When optimizing, the biggest gains can usually be had by fundamental changes. For example by introducing a cache, or changing the algorithm or data structure. As a budding developer, using jQuery extensively taught me the importance of simple interfaces in driving adoption of your code. On page 68, the author mentions the GOTO command to eliminate duplication by refactoring the code so that we can escape from the nested code. This is a big surprise, as the GOTO command has been considered a terrible idea by most authors for decades now.

You often throw an exception because you don’t know what to do in that case. But if you have trouble knowing what to do, chances are the caller also has trouble knowing what to do. If you can define your functionality such that it never needs to throw an exception, then you have reduced the complexity of the system. There are few books that discuss software design in a simple and approachable way, while leaving the reader novel and practical concepts to use. A Philosophy of Software Design is a standout and recommended read for this reason.

No comments:

Post a Comment

Master the Perfect Half Up Half Down Wedding Hair in Just 7 Steps

Table Of Content Soft Waves and Subtle Pins Incorporate Intricate Braids Pulled Back Layers with Headband Hot braid hairstyles of 2017: The ...