The structure I prefer for a technical design document is like a three-layer onion.The first layer is the problem statement, goals, non-goals, and requirements, both functional and non-functional. The next layer is the functional specification, which describes precisely how the system will work from an external perspective. The third and final layer is the technical specification, which describes the internals.
Each section should follow from the previous. The design doc should justify to the reader (and author) that the problem is understood, the requirements are necessary and sufficient, the functional spec meets the requirements, and the technical spec implements the functionality and non-functional requirements.
As a corollary, if one section has a fatal flaw, there is no need to read on. If the problem is misunderstood, then the functional spec is likely wrong. If the functional spec doesn't meet the requirements, then the implementation is moot.
The issue I see very frequently is technical design documents that provide only the final section—a simple description of the system that will be built. As a design reviewer, there is limited feedback I can provide on such a design. Sure, it's a system, but will it solve the problem? Does the team even agree on the problem to be solved?
This +
Layer one also explicitly identifies stakeholders, and describes the current (AS-IS) situation with annonated screenshots so everyone quickly sees what we are talking about.
Layer two also lists alternative solutions considered and why not chosen.
Layer three is developers making a few notes on chosen tech design, most important is the choice reasoning here.
In all layers, add and use references. Less is more, a picture beats a wall of text.
Yes, agree with all of that. I don't think every design doc needs every possible section, but if readers would benefit from the background or the an enumeration of stakeholders, that belongs up front, before the design.
To add a little more color, each section also has a branch of possibilities. Given a problem, there are many possible functional specs that could solve it. Given a functional spec, there are many possible implementations. The act of choosing from among these possibilities is designing and the design doc should lay out the choices made (and sometimes the choices not made) and why.
Maybe also a section containing a reference implementation.
Or a formal proof, e.g. when discussing secure protocols.
Yes! Non-goals are SO important.
In IT, it's all virtual, so in theory anything is possible. Setting hard limits is necessary, or else the solution space is overwhelming, and the second system effect can kill your project (even in the first system!)
In mechanical or electrical engineering, some potential goals are blatantly physically or economically impossible and do not need to be mentioned as non-goals.