Two quotes that I keep on coming back to. The first is a tweet from Nicoll Hunt from 2014:
The first step of any project is to grossly underestimate its complexity and difficulty
The second is from a German field marshal by the name of Helmuth von Moltke (formulated in the 19th century):
No plan of operations extends with certainty beyond the first encounter with the enemy’s main strength
Which, in its more modern reconfiguration, is frequently referred to as “No plan survives contact with the enemy”.
Applied to design documents in the field of software engineering, one might say that “no design document survives contact with the codebase”. This has largely been true for myself, at least. Which doesn’t leave a lot of options.
The first one is to not write any design documents at all, and kind of discover-as-you-go. The code itself becomes the design document, hopefully by either being clear enough or by being well documented.
The second option is to write a document, and then keep on updating it as you’re discovering all the things that can only be discovered during the implementation.
The third option is to write a document, pretend that it accounts for every possible scenario, make an elaborate planning chart on how much time exactly the implementation phase will take, and then pretend to be surprised when the real numbers had little to do with that chart.
The fourth option is where the final implementation has nothing to do with the design document, and nobody bothered to spend any time updating that doc.
And the fifth option is to write a design document, do the implementation, and then write another design document that describes the actual implementation and compares the original approach with what actually worked. A post-mortem, if you will, on the original design document. What worked (probably nothing). What did not (probably everything). What can we learn for the next time (probably nothing, again).