There is a problem with these metaphors: activities that work against technical debt are often dependent on the skill and experience of the programmers involved. You often get no long term benefit from doing them.

I write code in a specific fashion, which involves a lot of TDD and a lot of refactoring. I've been doing it a long time and have refined it to the point where I expect to get payback in less than 1 week. But it is naive to expect that someone else will use the same techniques and achieve the same benefits right away (I have been, very, very naive in this respect at times :-( ).

For example, non-mocking TDD forces a particular set of design decision to be made up front. It also forces the creation of specific API entry points. Mocking TDD allows you to defer design decisions and makes it cheap to explore large design spaces. It forces you concentrate on your interfaces. The choice of which to use in various situations dramatically affects how well you can refactor. With non-mocking unit tests, you can get buried in the details of setting up contexts. With mocking unit tests, you tests can become very brittle. It also allows/encourages you to make some pretty horrifying design choices.

Even when people do TDD and have lots of tests, they often make poor choices and end up with code that they can't (or don't want to) refactor. The thing that people often do not understand is that unit tests and/or TDD will usually not provide much of a payback (in terms of productivity) alone. It is the refactoring that leads to simple design, reduces complexity, reduces code duplication, makes it easy to reason about changes, etc. Unit tests (and TDD in general) simply give you a framework for making refactoring easier.

The problem, from my perspective, is not about judging risk of upfront payback versus long term payback. When done well, the activities around reducing technical debt pay off so quickly and so dramatically that there are almost no cases where they are inappropriate. The problem is that using the techniques poorly often leads to no payback at all! In fact, sometimes you inherit a project with a rat's nest of crazy tests and the first thing you do to improve your productivity is delete the tests -- on the principle that less code means less complexity that you need to deal with.

Although my own personal style involves TDD and refactoring, I believe that the same can be said for other styles of development that are geared toward reducing technical debt. In my career I've done BDUP (1000 page requirement and design docs FTW!), I've done rapid prototyping (build 20 to throw away!), and a few other techniques. They can all work, but IMHO require even more skill to do well.

This is one of the things I wish someone told me at the beginning of my career. At the moment my current feeling is that there are virtually no cases where tolerating/embracing technical debt will lead to even short term gains. However, the alternative is not straight forward. Young teams must expend considerable effort finding expertise to help guide them forward. More importantly, everybody on the team needs to be aligned to the style that will be used. How you achieve that alignment is yet another can of worms.