Documentation is where the thinking happens
The advice to document your code is usually given as hygiene — a thing you do afterwards, for other people, like washing up. I want to argue for something narrower and more selfish: writing the document first is the cheapest debugging tool I have, and it operates on the design rather than the code.
The test
The rule on VECTOR is that a component needs a document arguing for its existence before it gets built. Not describing it. Arguing for it — what it is responsible for, why that responsibility cannot live somewhere that already exists, and what would have to be true for it to be the wrong idea.
Roughly a third of the time, writing that document is how I find out the component should not exist. The responsibility turns out to belong to something that is already there, or the thing it was going to solve turns out to be a symptom.
The economics are absurd in my favour. Forty minutes of writing against a week of building, plus the maintenance of a thing that should never have existed, plus the much worse cost of only discovering it when the architecture has grown around it.
Why afterwards does not work
Documentation written after the fact describes what exists. It cannot do anything else — the decisions are made, the code is there, and the honest options are to describe it or lie. So you describe it, and the description is accurate and worthless, because the part a future reader needs is the part that is gone: the alternatives, and why they lost.
The failure mode
It can become a way of avoiding the work. Documents are pleasant to write. They feel like progress and cost nothing to be wrong about, and it is entirely possible to spend a week architecting something that would have taken two days to build and discover empirically.
The heuristic I use: write the document when the cost of being wrong is structural. A component that other things will depend on, a decision that is expensive to reverse, anything touching the authority boundary — document first. A utility function, a formatting change, anything I can delete in an afternoon — just build it and see.
Getting that boundary wrong in the cautious direction is slow. Getting it wrong in the other direction is how you end up maintaining a system nobody decided on.
The part my classmates find funny
I once spent an entire evening writing a document arguing for a component, and concluded that the component should not exist. The evening produced no code, no commits and nothing to show anyone. It was one of the most productive evenings I have had, and explaining why to someone who does not already agree is genuinely difficult.