Ron Jeffries started an interesting topic on the XP mailing list. He said, "I think sometimes there's too much refactoring, and refactoring in the wrong places. ... How can we find a balance between too much refactoring and too little?"
I thought this was a great topic. Test-Driven Development gets all of the attention, but I think merciless refactoring is the part of XP that has all of the subtleties, and where the coolest stuff happens. Imagine! Do this right, and your code gets cheaper to modify over time! That's so amazing, most people don't even think it's possible. Some even go out of their way to ridicule and belittle those who suggest it could be.
Here are the most common refactoring problems I see with XP teams:
Teams that don't refactor enough. They limit themselves to localized micro-refactorings that don't improve the big-picture design. Individual classes are well-programmed but the overall structure contains duplication and doesn't hang together well.
Teams that refactor in clumps. They "save up" refactorings (by writing them on cards, whiteboards, etc.) and then schedule them like stories. Every so often, they take a whole iteration off to work on refactoring.
Teams that rewrite. Not really an XP issue... I see it most often when a team is trying to switch to "a better way" and decides that the way to go is to use their new process to rewrite their existing system.
The rewrite becomes a millstone around their neck once the switch-over starts and the people realize that the true costs and risks of the rewrite are unknown. Pressure mounts, people get frazzled, and XP (and any semblance of process) goes out the window.
These three issues aren't mutually exclusive and may reinforce each other.
So what I would like to see is teams that do intraclass micro-refactorings every hour, do interclass refactorings multiple times per pair-week, and identify big-picture "architectural" refactorings every 2-12 months. I'd like to see teams take time out, a few times a week, to talk around the whiteboard about their big-picture design and how the latest batch of stories fits in.
I'd like to see teams identify one or two (max) architectural refactorings that are based on (a) reflecting on problems in the existing design and (b) how to improve the existing design; and use that architectural direction to guide their intra- and inter-class refactorings. I'd like the architectural to incrementally improve as stories are implemented, with ocassional bursts (a few hours here and there) of dedicated refactoring for the sake of consistency or when making tough changes.
I'd like all of this to happen constantly, as naturally as typing, talking to your pair, writing tests, and running the build. Every time a code smell is identified, I'd like the pair to make a decision to "fix" or "not fix" (within an hour or so, max) depending on how big of an improvement it is, how much it would cost to fix, how much time they've spent refactored already today (literally today) and whether the iteration plan is ahead or behind schedule. If the decision to "not fix" is made, I'd like the pair to leave it alone, not writing it down, not creating a "To Do" comment, confident that if the smell is truly an issue, it will be spotted again and fixed when it is valuable to do so... probably by a pair that's learned more in the meantime and come up with a better/cheaper/simpler way of fixing it.