Refactoring in code isn't overhead, any more than writing a first draft is overhead in writing a book. It's an inherent part of one of the best ways of producing good code, just as writing drafts is an inherent part of one of the best ways of producing a good book.
Just found this interesting parallel in Baetjer: SoftwareAndWriting.
NOTES
Your project is complete when it [is in ExtremeNormalForm?] includes all required functionality and the code quality meets standards. (I'm not going to define "meets standards" here, but it relates to the code being well-organized, robust, not excessively redundant, having the right number of comments, being easy to maintain.)
There is a spectrum of ways to get to this point. Two points in that spectrum are:
Code implemented to requirements that change is wasted in that (a) it has to be changed; (b) it gets in the way of maintenance up until that change.
Code built incrementally (a) doesn't get changed when requirements change before it got implemented; (b) doesn't get maintained because it isn't there.
When requirements change, incremental development comes out ahead because sometimes you didn't get around to doing it wrong.
Design is hard
Designs done on paper, in the context of all requirements, are hard to do and often even harder to implement. There is much detail ignored in the DesignPhase, so that often a comprehensive design isn't that good for actually implementing.
Building incrementally can give more rapid feedback on design quality, allowing less costly adjustments to the design.
Because design is hard, incremental development comes out ahead because you learn sooner, reducing the cost of correction.
Refactoring has code churn
Systems done with upfront design churn their code less and therefore there is less total coding done. Is this necessarily good?
Programmers using incremental development spend more time churning code than programmers working from upfront design. Is this necessarily bad?
Upfront design spends less time programming
Systems done with upfront design tend to have separate groups assigned to design and coding, tend to create and maintain more documents, tend to have higher communication overhead.
Systems done incrementally tend to be done with fewer people and the people they have tend to be able to spend more time actually producing the product.
-- RonJeffries
How does refactoring apply to test scripts?
-- CayteLindner
If you DoTheSimplestThingThatCouldPossiblyWork with each iteration, you will sometimes find that a later iteration requires something more flexible than what you've written. You need to introduce additional layers of abstraction. So you refactor -- doing things like adding new classes, and moving functionality into common base classes, making it polymorphic. You don't always lose code by doing this. And good UnitTests ensure that you don't break the code by moving it.
So the cost of "code churn" mentioned above is much lower than you might expect. And you have to weigh it against the risk and cost of long integration cycles that often occur at the end of non-iterative development projects. (Ever been to IntegrationHell?)
-- JeffGrigg