Somewhere on Wiki, RalphJohnson mentioned that ExtremeProgramming is suitable for non-theory-heavy small-team projects. Where a project is theory heavy, that is, you don't understand your problem, or know that specs make sense without thinking them through, I have tended to use the approach mentioned in the title.
The idea is that even if you figure out what seems like a good general design, you will still have a lot to learn about the problem. So don't start by implementing "generic libraries" or other grandiose constructs. Start with something that is useful today, and use the general design (or theory, if you prefer) as a target.
In these projects, I have never been able to capture the design in the source code in any meaningful way. I try to get as close as possible, but beyond that, the sheer complexity of the data structures and dependencies means that a specification is far simpler to understand than code.
Also, "design up front" means "a reasonable amount of design up front", not the situation described in BigDesignUpFront.
-- AamodSane
... the sheer complexity of the data structures and dependencies means that a specification is far simpler to understand than code
With all due respect, when is this situation a recommendation for the use of "specification", and when does it argue for increased simplicity in data structures and dependencies? --RonJeffries
In some cases, you just cannot simplify further. Consider the internals of an OS: simplicity will often conflict with optimization. At that point, you do a specification, then say how the optimized code was derived from it, and why were the convolutions needed. You say this in a refinement. --AamodSane