When should you refactor? When do you say the time has come to put new features on hold while you clean up and get a handle on your legacy code? There are several possible answers to this question, and they are not mutually exclusive.
The first time to refactor is before any redesign. If your site is undergoing a major redevelopment, the first thing you need to do is get its content under control. The first benefit to refactoring at this point is simply that you will create a much more stable base on which to implement the new design. A well-formed, well-organized page is much easier to reformat.
The second reason to refactor before redesigning is that the process of refactoring will help to familiarize developers with the site. You’ll see where the pages are, how they fit together in the site hierarchy, which elements are common across pages, and so forth. You’ll also likely discover new ideas for the redesign that you haven’t had before. Don’t implement them yet, but do write them down (better yet, add them to the issue tracker) so that you can implement them later, after the refactoring is done. Refactoring is a very important tool for bringing developers up to speed on a site. If it’s a site they’ve never previously worked on, refactoring will help teach them about it. If it’s a site they’ve been working on for the past ten years, refactoring will remind them of things they have forgotten. In either case, refactoring helps to make developers comfortable with the site.
For similar reasons, you should consider refactoring before any major new project that builds on top of the old one. For example, if you’re going to implement one-click shopping, make sure the old shopping cart makes sense first. If the legal department is making you add small print at the bottom of every page, find out whether each page has a consistent footer into which you can easily insert it. You don’t have to refactor everything, but do make those changes that will help you more easily integrate the new content into your site.
Perhaps the new functions are on completely new pages, maybe even a completely new site. If there’s still some connection to the old site, you’ll want to look at it to see what you can borrow or reuse. Styles, graphics, scripts, and templates may be candidates for reuse. Indeed, doing so may help you keep a consistent look and feel between the old parts and the new parts of the site. However, if the old parts that you want to reuse have any problems, you’ll need to clean them up first.
Finally, you may wish to consider semicontinuous refactoring. If you find a problem that’s bothering you, don’t wait for an uninterrupted two-week block during which you can refactor everything. Figure out what you can do to fix that problem right away, even if you don’t fix everything else. To the extent possible, try to use agile development practices. Code a little, test a little, refactor a little. Repeat. Although many projects will be starting from a large base of crufty legacy code, if you do have a green-field project try not to let it turn into a large base of crufty code in the first place. When you see yourself repeating the same code, extract it into external templates or stylesheets. When you notice that one of your hired HTML guns has been inserting deprecated elements, replace them with CSS (and take the opportunity to educate the hired gun about why you’re doing that). A stream of many small but significant changes can have great effect over time.
Whatever you do, don’t let the perfect be the enemy of the good. If you only have time to do a little necessary refactoring right now, do a little. You can always do more, later. Huge redesigns are splashy and impressive, but they aren’t nearly as important as the small and gradual improvements that build up over time. Make it your goal to leave the code in better shape at the end of the day than at the beginning. Do this over a period of months, and sooner than you know it, you’ll have a clean code base that you’ll be proud to show off.