In the interest of running a social experiment to amuse myself, I won’t do a Google search for the term design document. I could easily do this, but I won’t. Instead, I’m going to hazard a guess as to what the search would yield: a Wikipedia article and a bunch of really old web pages that use the passive voice a lot.
I say this because design documents, like the singleton design pattern and systems such as Hungarian notation, were legitimately good-seeming ideas that just landed on the wrong side of history. (And like those two things, I’m sure someone will come storming straight out of 1998 and into the comments section below, telling me that I’m a horrible human being for claiming this. “It says it’s a good idea in a book, Erik, you imbecile, which you’d know if you could read!” But I digress.)
The design document captures design intent. It helps junior developers work with less supervision. It paves the way for maintenance programmers to know what happens. And it even communicates technical concepts to non-technical stakeholders. That’s a lot of nice wins for one modest four-page MS Word document. How can I possibly claim we should retire the design document?
Well, here’s the thing. I’m not saying a design document provides no benefits. I’m saying that, when compared to other options, a design document does a less efficient job at providing every benefit that it offers. Oh, and it comes with significant downsides. So let’s look at those downsides and then at more efficient ways to realize its benefits.
Design Document as Part of a Failed Metaphor
In 1970, a gentleman named Winston Royce wrote one of the most ironically misunderstood articles you’ll ever find. He drew a now-iconic picture of software as a series of rigidly delineated phases that resembled a waterfall, and described it as a “flawed, non-working model.” But, oops. The industry at large said, “You had me at waterfall,” and by 1985, the US Department of Defense had immortalized these rigid phases into their standard for working with software development contractors.
This idea of software development tracked neatly with construction and manufacturing. Spec out what people need, draw up an elaborate blueprint of every last detail, have the working grunts construct it, then send in the quality people. So much did we like this metaphor that our job titles track closely with these disciplines (architect and engineer)—except when you stop and think about it, building construction actually makes an apt metaphor for terrible software: rigid, massively expensive to change, and completely interdependent.
The design document hails from a different time—a different world. It makes sense in a world where the following things are true:
- Software happens in two phases: architects think and plan, and grunts code up their vision without hurting their brains very much.
- Design documents inform code, but the reality of code doesn’t inform design documents.
- You can control scope enough to make design document creation not wasteful/prohibitively expensive.
- The most faithful way to generate representations of a codebase/architecture are manual diagrams and typed explanations.
But we don’t live in this world.
Design Document: the Downsides
I mention the clash of worlds behind the design document to serve as context for a more concrete set of downsides. First and foremost, there’s the literal cost of making and maintaining these things. Everything employees do has labor cost and opportunity cost, and design documents are no different.
Every time you fire up Visio and make a sequence diagram or an entity-relationship schema, you’re spending that time not building software. We take on faith that the investment will prove worthwhile, but it may not. The design document might age badly, or perhaps nobody ever reads it. It’s a speculative time investment that may never pay off.
But I’d argue that there are two substantially more difficult downsides than that one, which you can take steps to minimize. First up, consider what I’ll call the maintenance dilemma. Recall that we don’t really exist in a world where design documents are stagnant. Your software will change—and change a lot. This forces you to spend time forever maintaining these documents or else they become out of date and create confusion rather than value. On a long timeline, the likelihood of them being a liability approaches 100%.
And finally, the design document creates drag on the team’s technical competence. It encourages you not to evolve the system as you go, since doing so generates document maintenance busywork. But it also creates a culture where thinking and programming are considered two separate activities. Dream up the system architecture, and then just put the brain on autopilot and code it up.
Up-Front Plan With Whiteboards, Collaboration, and Team Skill
On that note, let’s start to look at how you can realize the benefits of a design document without resorting to an awkward and dated practice. One of the first benefits historically conferred by design documents is to force some planning. When someone commissions your team for a $10 million project, you don’t just say “thanks” and fire up your IDE. You do need some kind of architectural plan.
But that plan doesn’t need to be a binder full of Word documents with UML diagrams, created by the brainiacs and consumed by the grunts.
Get rid of the “planners and coders” paradigm altogether and have the most skilled folks in the mix, leading by example. Why write a binder of architecture when they can show it to the other developers, who can learn a lot more rapidly?
Collaborate loosely and easily with whiteboards and brainstorming sessions. Take pictures as needed. The folks with architectural experience can lay a good initial groundwork for the team. They can then monitor what’s happening, iterating and adapting as they go. (This is as opposed to a waterfall world where they might shuffle off to another project.)
Use Pair Programming and/or Code Review for Sanity Check
Another historical benefit of the design document in a lot of shops is to act as a sort of governor that prevents the inexperienced from doing things that are, well, insane. Or at least naive. Because newbies do naive things.
Design documents have historically guarded against that by putting bumpers in the metaphorical bowling lanes. A class diagram with method stubs as input means that someone programming really can’t mess anything up at the architectural level. But it means they won’t learn much of anything, either.
Take the bumpers out and let them code and design. Pair them up with experienced folks so they learn without consequences. Or absent that (or in addition to it), have them work in bite-sized chunks and perform frequent code reviews with a “fail fast” mentality.
Software development labor is too scarce to waste years of people’s careers coding by numbers against some giant document.
De-Risk Change with Automated Tests, Clean Code, Design Patterns, and Principle of Least Surprise
Another legacy benefit of the design document has to do with ririsk and with maintenance programmers. Software is complex and often difficult to understand, especially at scale. It’s hard to understand code that you wrote six months ago, let alone that someone else wrote even longer ago.
So what do you do? Well, you write a document explaining what you do and why, how, and where you do it. The idea is that maintenance programmers will come along, read the document, and understand your code more readily. This, in turn, will lead to modifications in less time, with fewer defects. In other words, it will lead to less risk.
But you can mitigate maintenance risk in plenty of other ways. First of all, if you have an elaborate suite of tests—unit, integration, smoke, load, acceptance, etc.—you have powerful risk mitigation. And while those things don’t necessarily aid understanding as much as a design document, they do allow you to change the code with a lot more confidence. You don’t need as much understanding when you have a robust safety net.
Add to this good, clean code and design. If you keep your code clean and readable, follow known design patterns and conform to the principle of least surprise, you’ll help significantly with understanding. Put all of this together and your team will be fine without documents.
Use Auto-Generated Documents for Communication
This leaves us with one final benefit of the design document. It’s good for explaining the system to outsiders or even to non-technical stakeholders. I certainly wouldn’t dispute the usefulness of something like a package diagram for certain reviews or meetings.
But again, you don’t need a traditional design document to do this. Visual Studio, for instance, has allowed you to generate certain UML diagrams for years. And that’s just one example. As IDEs and static analyzers get smarter, there are plenty of other tools out there that let you generate all manner of visual representations of your codebase. These are always going to be 100% faithful representations of reality. And best of all, these don’t require maintenance, and they don’t rot the way that diagrams and Word docs in source control do.
You’ve Got to Up Your Automation Game
At the time of writing, it’s the year 2018. If your best communication strategy around code and design is to write a document, code by its guidance, and then maintain that document, you’re doing something comfortable, something familiar, and something completely obsolete.
Over the last 20 years, we’ve created wonderful technology around automated testing and static analysis. We’ve automated integration, environment management and deployments to the point where shops release hundreds of times per day. We’ve evolved to a world of discoverable design where nobody says “read the manual” anymore because nobody bothers to make manuals. That is our current reality.
If you want a picture of your system and a way to communicate about it, then you need automated solutions to those things. Technology, your competition, and life in general all move too quickly these days for you to solve the same problem in two different media. So ditch the design document once and for all, and adopt these other techniques until you have no gaps in your team’s performance. Do that, and you’ll continue to improve on past the break-even point.