Software Design Reviews
What is a design review?A design review is a technical meeting that is held at an early stage in the software development process. A design review generally involves a presentation of a planned software design, at a time early enough in the process to allow for changes is necessary, to an audience of stakeholders. Design reviews can fill a number of purposes, such as:
Software Design Reviews
Therefore, effective design reviews must include the presentation of several alternatives. The discussion should not be if a particular design satisfies or not the requirements. Correctness is the most fundamental attribute of a solution, so the diverse design choices must differ on some other attributes that can be compared. In other words, each option has its advantages and disadvantages, and by choosing one of them we are actually deciding which attributes are the most important ones, but all options must be correct.
For an enterprise to practice architecture in an agile environment, several architects and designers must support the project's agile value streams, which are the actions taken from conception to delivery and support that add value to a product or service. One organization may have a distinct team of architects producing solution designs and templates. Another might place the architect inside the agile squad in a dual senior engineer role.
No matter the operating model, designing and implementing features in scaled agile environments is a song sung by many voices that may differ in tone, views, opinions, and experience. Therefore, you need to develop processes that:
Design review is a process that can step in to align, homogenize, and enhance the architects' ideas and opinions. In enterprise architecture terms, it is a tool from the governance arsenal. In software engineering terms, it is like a code review for design. Code review is a well-established software engineering practice that helps assess the code, identify bugs, and increase code quality and help developers learn the source code. An architecture team can reap these benefits from a design review.
An architect needs to design an e-commerce feature for adding a coupon during purchase. The designer documents the benefits, the areas of impact, and the low-level details of the changes. Then, they submit the document to a fellow architect for review. The reviewer may have remarks about the security of the APIs and potential fraud risks or provide a reference to coupon management in loyalty features. Once the designer and the reviewer agree on the final design, the feature can proceed to implementation.
The parties must also consider the time factor in a design review. You cannot endlessly discuss a feature necessary for the business either from a practical or philosophical (we are architects, after all) aspect. Deliverability is essential. Therefore, you should set metrics to measure and control the process' performance. Some examples are:
The design review process needs to be a priority for the designer and the reviewer, as the features are urgent for the business. Someone needs to prioritize the design review backlog and correlate it with deliverability.
Design review has clear value that far outweighs the overhead it introduces, much like code review does in software releases. Organizations should consider it part of their governance model in conjunction with other tools and practices, including architecture review boards. The two processes can co-exist, with the design review focusing on constant calibration and course correction of the agile teams' value streams.
Christos Gkoros is a software engineer and architect at Vodafone with more than 12 years of experience in various industries. For Vodafone, he has built critical enablers for its digital transformation from a telco to a tech company. More about me
I was somewhat skeptical when starting to read a Philosophy of Software Design, despite having it recommended by a friend. The book does a delightful job underselling itself. It is odd-shaped, published by a university press, and the preface mentions, "At this point, you might be wondering: what makes me think I know all the answers about software design? To be honest, I don't."
However, the fact that the book was written by someone who's been writing code for decades, the university press being Stanford press, and the book covering lessons learned during the first software design class at Stanford gauged my interest. Still, I wondered just how much I would learn about software design from experience partially distilled from a classroom - even if a Stanford classroom. A lot, as it would turn out.
There is a significant difference between most books written on software design and John Ousterhout's one. It's repeatability. While almost all software architecture books are based on real-world experiences of experienced developers and consultants, those are not repeatable experiences. Those people solved challenging problems using certain methods: but they did not have the opportunity to do the same with a different approach. Even my views on software architecture are based on one-off projects and their aftermath.
John, on the other hand, had the vantage point of having multiple teams solve the same design problem during a semester, with him observing. He also had the luxury of repeating this experiment multiple times. With each repeat, he was able to both validate and tweak his observations.
So how, exactly, should we fight this complexity? By encapsulating complexity via modular design and making code simple and obvious, like eliminating special cases or using consistent coding styles. The first part of the book focuses on good, modular design practices, while the second part of the book touches on techniques to make the code simple, as well as goes in-depth on commenting best practices.
Tactical vs strategic coding: deciding when to invest for the longer-term isn't easy. Be aware if you are putting out a fire, or building for the long-term. This observation matches my experience: "hacking" something together quickly, just to make it work, versus platformizing (making it reusable, extensible) is a tricky tradeoff to make. While this advice sounds simple, it is the one that requires experience and times of being burnt, to get it right. The challenge here is similar to the software development dilemma of moving fast, without breaking things.
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.
Information hiding and information leakage (Chapter 5) is another take on what good abstraction is and how efficient interfaces should behave. Those who have designed APIs have probably had first-hand experience with why leaking information beyond the bare minimum leads to tech- and architecture debt later on. John also mentions a glaring example of bad API design: over-exposing internals.
For backend systems, I view exceptions as a good thing: as long as they are thoroughly monitored and alerted on, targeting a zero exceptions policy. For client-side software like mobile apps and desktop apps, I agree that exceptions make for more complex logic. In these cases, exception masking - and logging - that John suggests in Chapter 10 can be a good solution. He lists the option of deciding that it's fine to crash the application on an exception: which would not fly in areas like mobile development.
While the book does a good job covering architecture concepts when writing code, there are several areas that it does not touch on. Most of these are outside the scope of the software design course itself. However, some reference to these would have been useful.
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. 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.
Testing was absent from the book, save for the last part, mentioned at the end of the book, in 19.3, as part of software trends. In my view, good architecture and testability go hand-in-hand and would have welcomed this topic mentioned earlier. John dedicates discussing strategies to modify existing code in-depth in Chapter 16. His two pieces of advice are on staying strategic in modifying the design and maintaining the comments. This does not match my reality. The surest and safest way I know to modify existing code is to have tests. With tests in place, go ahead and make whatever change is necessary - and sensible. If there are no tests, start by writing tests. If there are tests, major refactors that wildly modify the existing design can also fly - the tests should give a safety net to do so. And with tests in place, comments become an afterthought: if there is a test for it, a comment is not that necessary. Note that after exchanging emails with John, he pointed out he focused the book on architecture, treating other topics deliberately out of scope.
I very much recommend the first half of the book - chapters 1-9 and chapter 14 - for all software engineers to read, digest, and consider applying. Concepts like depth of modules, layers adding complexity - or keeping complexity at bay - and information hiding are pragmatic tools to use when designing software. The book offers a fresh take on the concept of abstractions, and nicely complements principles like simplicity, KISS (Keep it Simple, Stupid) and YAGNI (You Ain't Gonna Need It). 041b061a72