Review: Modern Software Engineering
This is actually a review of 3 books by Dave Farley, because they really form a set:
- Modern Software Engineering: Doing What Works to Build Better Software Faster (just released for 2022, 224 pages)
- Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation (co-authored with Jez Humble, 2011, 463 pages)
- Continuous Delivery Pipelines: How To Build Better Software Faster (2021, 160 pages)
I've recently become a big fan of Farley's work (spoiler alert: the book is great! Read it! And the others!). He's literally changed the way I do some things. He's really changed the way I'd like to do some things.
I started out with his YouTube videos, full of excellent advice (and great T-shirts!). Most recently he's started publishing extended interviews with other senior software experts like Martin Fowler. I binge these at 1.5-2x, then go back and re-watch parts.
The 3 books are nearly 850 pages of reading, so can be intimidating. Make a first pass through them by skimming, then go back and fully read the parts you need. Like watching videos at high speed, that's an efficient process that allows you to get the gist quickly, then focus where you need to.
Modern Software Engineering
His new book summarizes all of the material from his videos and other books into a coherent approach to software engineering. It's written at a level useful for both technical and management staff. It might be a checklist for a CTO.
For the technical folks, it provides an introduction and forms the root of a study tree for more details. For the management and executive folks, it provides sufficient detail to drive an organization. At any of those levels, if you don't read it, you're really doing your company a disservice.
Some of the recommendations are a significant change from the way many companies work. But this is in the interest of improving the perennially poor state of much of software development. He references one of my other favorite books, Frederick Brooks Mythical Man-Month, that shows these problems have been around since the 1960's.
One of his main concepts central to doing things better is continuous delivery (CD), hence the other 2 books. It consists of using fast feedback mechanisms such as Test-Driven Development (TDD), trunk-based development (which implies CI, continuous integration) and deployment automation to ensure that software is always in a releasable state.
You create a continuous delivery pipeline that automates the process (and the generation of feedback) from developer commit through deployment.
In contrast, the typical status quo in many organizations is:
- Test-after development (which often gets short-changed by the schedule axe).
- Branch-based development, with new features developed on long-lived branches that have to be merged to trunk.
- Manual deployment and verification.
- Resulting in poorly-tested software full of bugs and non-functional requirement issues, nightmare merge efforts that stall progress, and software that is rarely in a releasable state, delayed by months or even years.
The book outlines a number of other concepts in good engineering practice and software design, such as modularity, cohesion, separation of concerns, abstraction, and managing coupling (see my post Six Software Design Tools for some discussion of these).
He argues for a highly modular, componentized architecture. That's the main tool for managing complexity, underpinning much of software engineering. He uses a great analogy to the 1969 Apollo lunar mission, where the different physical modules of the spacecraft were highly focused on their specific mission phases, each relatively simpler than the total mission, independently developed and tested.
His 2011 book with Humble is then the primary reference for how to do CD. Even though it's now a decade old and some of the tools have changed a bit (for instance, Hudson is now Jenkins, and git has become a pre-eminent version control system (VCS)), it remains perfectly timely and relevant. The concepts haven't changed.
This is the book that those who build and manage the CD pipeline need to read. It covers the details of the pipeline stages and the tools used in them. It provides the justification and arguments for doing things this way.
The pipeline consists of these stages:
- Commit stage
- Automated acceptance testing
- Automated capacity testing
- Manual testing
The goal is to evaluate each committed change and answer the question, "Should we release this change?", i.e. is it a release candidate? The pipeline provides feedback at multiple points to weed out failures and keep the software always in a releasable state (possibly with latent code changes for features that are not yet enabled).
The process is intended to be repeatable and reliable. While most of it is fully automated, including most of the testing, the manual testing stage provides for exploratory testing and user acceptance testing (UAT).
Continuous Delivery Pipelines
His 2021 book is a briefer, practical handbook on CD pipelines. Specifically, it elaborates on these 7 essential techniques:
- Reduce the Cycle Time
- Automate Nearly Everything
- Control the Variables
- Work in Small Steps
- Make Evidence-based Decisions
- Work in Small Empowered Teams
- Apply Lean and Agile Principles
Among the various practices covered, I believe that TDD, when done right, is a force multiplier. If you want to be a 10X developer, if you want your team to be 10X developers, TDD is a strategic approach to getting there. If not 10X, certainly 2-4X. See my post Acceptance Tests vs. TDD for my treatise on TDD.
Farley clearly agrees. He says, "TDD is a talent amplifier which improves the skills of the developers and the quality of the code they write."
The biggest message I take from this is feedback. Your development, build, and deployment pipeline needs to give you feedback. It needs to do it quickly, at all stages. You need to live and breathe feedback.
Feedback is essentially a binary proposition at each point in the pipeline:
- Things are good. There is nothing at this point in the pipeline that would prevent release and deployment.
- Something is not good. There is something detected at this point in the pipeline that would prevent release and deployment.
As long as things are good, keep going forward. As soon as anything is not good, stop and make it good.
That's the fundamental closed-loop feedback control system from classical control theory:
- Monitor feedback at high frequency.
- When a measured variable goes out of spec, take corrective action.
- The shorter the latency between occurrence and correction (the better the responsiveness), the finer the control.
Here, the measured variable is releasability. The corrective action is to stop and fix the breakage.
In this context, "move fast and break things" takes on new meaning: fail fast. The key is fast feedback. If things are going to break, do it fast so you know what to fix:
- Fast, as in seconds, minutes, or hours, rather than days, weeks, or months.
- Fast, as in right after you did it, rather than long after you've forgotten all about it.
- Fast, as in while it's still easy to deal with, rather than after it becomes a big mess.
What are the feedback mechanisms?
- TDD: developer unit tests give developers feedback as they are coding, before ever committing any changes to the codebase.
- Trunk-based development: builds and automated tests give developers fast feedback on their integration with everyone else's work (rather than weeks or months later after merging their branches to trunk).
- Continuous deployment: deploying builds frequently (not necessarily to production) gives fast feedback about whether they actually work.
The automated tests are composed of unit tests (the developer tests) and acceptance tests (the customer tests).
Keeping trunk always releasable (which includes latent code for incomplete features) means there is fast feedback when something breaks it.
In my 40 years of software development, I've seen a lot of problems that could have been avoided with these methods.
I've been using VCS' for nearly the past quarter-century at a variety of jobs. ClearCase, SVN, Perforce, and git. In all cases, the organizations have used the branch model for feature development.
In all cases, they've suffered from painful merging prior to release. This means delayed releases with repeated rounds of stabilization. Merging has always been a miserable, thankless task that completely stalls progress.
Trunk-based development seems like a better way. Continuous delivery seems like a better way.
Thank you, Steve, for pointing out Dave Farley, his new book and his YouTube channel. I found there his recent video "The Next BIG Thing?" quite intriguing. In that video, Dave talks about the "actor model". This is something I've been also practicing for the last 20 years, except that I use "actors" (a.k.a. "active objects") in deeply embedded, real-time systems. I would highly recommend "The Next BIG Thing" video to fellow embedded developers.
You're welcome, Miro, and thank you for all your awesome videos! Your book is actually where I learned active objects! And now I'm off onto Bruce Douglass' books thanks to you...
To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.
Please login (on the right) if you already have an account on this platform.
Otherwise, please use this form to register (free) an join one of the largest online community for Electrical/Embedded/DSP/FPGA/ML engineers: