Partly it boils down to the sort of problem you're trying to solve.
I find that if your problem is not very domain-specific; ie if you can strip out the labels, and consider what you're doing as manipulations of relatively abstract objects; rearranging lists and graphs and so on - then up-front thinking is repaid many times over.
There tend to be lots of corner cases (what if this list is empty, what if this graph has no nodes, ...) and accidental infinite loops you can fall into. Thinking about it and specifying the algorithm up front forces you to take a coherent view on your problem domain.
If you approach this sort of thing iteratively (well, if I approach this sort of think iteratively) I tend to find that even if I can get my initial usecase working quickly, I haven't got the problem well enough established in my own mind, so I end up fixing things in an ad-hoc manner, squashing bugs in one corner case only to find 5 or 6 cropping up elsewhere because eg in half the code I assume X can never be 0 while in the other half I've been using 0 as a marker value for invalidity.
Solving that sort of problem I find is much better done by thinking hard about it before hand and working out what you're trying to do. Of course, in any case, you should surround your method with lots of testcases documenting what it's doing as well.
This is very different I think from the argument of agile development against waterfall-style development. The hard thinking in this case is at most a few hours - it fits in entirely with agility.
I find that if your problem is not very domain-specific; ie if you can strip out the labels, and consider what you're doing as manipulations of relatively abstract objects; rearranging lists and graphs and so on - then up-front thinking is repaid many times over.
There tend to be lots of corner cases (what if this list is empty, what if this graph has no nodes, ...) and accidental infinite loops you can fall into. Thinking about it and specifying the algorithm up front forces you to take a coherent view on your problem domain.
If you approach this sort of thing iteratively (well, if I approach this sort of think iteratively) I tend to find that even if I can get my initial usecase working quickly, I haven't got the problem well enough established in my own mind, so I end up fixing things in an ad-hoc manner, squashing bugs in one corner case only to find 5 or 6 cropping up elsewhere because eg in half the code I assume X can never be 0 while in the other half I've been using 0 as a marker value for invalidity.
Solving that sort of problem I find is much better done by thinking hard about it before hand and working out what you're trying to do. Of course, in any case, you should surround your method with lots of testcases documenting what it's doing as well.
This is very different I think from the argument of agile development against waterfall-style development. The hard thinking in this case is at most a few hours - it fits in entirely with agility.