Waterfalls Take Time
I sat in on a meeting the other day, and heard some discussion about late breaking requirements and whether or not these requirements should be addressed in a particular release of software. One of discussion participants voiced an opinion in the negative, citing as rationale that there was not sufficient time to generate a document with all of these requirements, generate a design document to discuss how these would be implemented, and then write the code according to this document.
This filled me with a strange wistfulness. I’m actually not kidding – I felt sad in a detached way that I can’t precisely explain. The closest that I can come is to translate this normal-seeming statement of process into real work terms. The problem and reason that a change couldn’t be absorbed was because there was no time to take the requirements, transpose them to a new document, write another document detailing exactly what to do, execute the instructions in the second document, and continually update the second document when it turned out not to be prescient. Or, more concisely, a lot of time was required to restate the problem, take a guess at how one would solve it, and then continually and exhaustively refine that guess.
I think the source of my mild melancholy was the sense that, not only was this wasteful, but it also kind of sucks the marrow out of life. If we applied this approach to cooking breakfast, it would be like taking a bunch of fresh ingredients out of the fridge, and then getting in the car with them and going to the grocery store to use them as a shopping list for buying duplicate ingredients. Then, with all the shopping prepared, its time to go home, get out the pots and pans, roll up your sleeves and… leave the kitchen to sit at your desk for an hour or two slaving over a written recipe. Once the recipe is deemed satisfactory in principle by your house guests, cooking would commence. This would involve flour, herbs spices, eggs, and of course — lots more writing. If you accidentally used a pinch instead of a dash, it’d be time to update the recipe as you cooked.
Kinda sucks the life right out of cooking, and it’s hard to convince yourself that things wouldn’t have gone better had you just cooked breakfast and jotted down the recipe if you liked it.
Why Do We Do This?
If you’ve never read Samuel Taylor Coleridge’s, “The Rime of the Ancient Mariner”, you’ve missed out on a rather depressing story and the origin of the idea of an “albatross around your neck” as something that you get saddled with that bogs you down. Long story short, during the course of this poem, the main character kills an albatross that he superstitiously believes to be holding him back, only to have the thing forced around his neck as both a branding and a punishment for angering spiritual entities with some clout. During the course of time wearing the albatross, all manner of misfortune befalls the mariner.
In the world of software development, (and ignoring the portion of the story where the mariner shoots the albatross), some of our documentation seems to become our albatross. These documents that once seemed our friends are very much our curse — particularly the design document. No longer do they help us clarify our vision of the software as it is supposed to look, but rather they serve as obligatory bottlenecks, causing us frequent rework and cruelly distracting us by whispering in our ears echoing chants of “CMMI” or “ISO”. Getting rid of them by simply ceasing to do them seems simple to the outsider, but is thoroughly impossible for us software mariners. We soldier on in our doomed existence, listlessly writing and doing our best to keep these documents up to date.
Let’s Just Not Do It
Things need not be this bleak. Here’s a radical idea regarding the design document — just don’t make one. Now, I know what you’re thinking — how are you going to have any idea what to do if you don’t lay it all out in a blueprint? Well, simple. You’ll use a combination of up-front whiteboard sketching and test driven development. These two items will result in both better documentation, and far less wasted time.
President Eisenhower once said, “Plans are nothing, planning is everything.” This philosophy applies incredibly well to software design. Capturing your design intentions at every step of the way is truly meaningless. Source control captures the actual state of the code, so who cares what the intentions were at a given moment? These ephemeral notions of intent are best written and left on whiteboards in the offices of developers to help each other collaborate and understand the system. Does the end-user care about this in the slightest? Of course not! Does anyone at all care about these once they become outdated? Nope. So, why capture and update them as you go? Capture reality when you’re done, and only as much as-is required by a given stakeholder. The more you document superfluously, the more documents you have that can get out of date. And, when your docs get out of date, you have a situation worse than no documentation — lying documentation.
The other main component of this approach is test driven development. Test driven development forces the creation and continuous updating of arguably the best form of documentation there is for fellow developers: examples. As Uncle Bob points out in the three rules of TDD, the target audience is developers, and given the choice between paragraphs/diagrams and example code, developers will almost without exception choose example code. And, example code/API is exactly what the by-product of TDD is. It’s a set of examples guaranteed to be accurate and current.
And, what’s more, TDD doesn’t just provide unit tests and an accurate sample of how to use the software — it drives good design. A TDD code base tends to be modular, decoupled and flexible simply by the emergent design through the process. This means that TDD as you go is likely to provide you with every bit as good a design as you could hope to have by rubbing your crystal ball and pretending to know exactly what 200 classes are going to be necessary up front.
Is it Really that Simple?
Well, maybe, maybe not. The solution can certainly be just that simple – ceasing to do something you’re in the habit of doing is excellent at forcing change. However, the whiteboard culture and the art of TDD certainly require some conscious practice. So, you may want to take both for a test drive before simply scrapping your diligent design documentation. But, personally, I’d say “jump in – the water’s fine!” I don’t think I’ve ever regretted not bothering with an ‘official’ design document. I’m happy to draw up documents to communicate the function of system at a given moment (instruction manuals, package diagrams, quick overviews, whatever), but creating them to be predictive of functionality and updating them from inception to the end of time… no thank you. The documents that we create are designed to promote understanding and help communication — not to serve as time-sucking millstones around our necks that we cite as reasons for not providing functionality to users.