"The time to take counsel of your fears is before you make an important battle decision. That's the time to listen to every fear you can imagine! When you have collected all the facts and fears and made your decision, turn off all your fears and go ahead."
-- George Patton
I know, I know -- what in the world did Patton know about refactoring?
Nothing. But he knew a hell of a lot about getting things done. He knew that there is a time for planning and a time for acting, and he knew that if you prepared when it was time to prepare, you should feel confident in your actions because you've done your homework ahead of time. Had he lived to witness Agile development, he would have had the following advice about refactoring:
Patton knew that no battle was ever won without proper preparation. For him, that meant training, discipline, and strategic planning. We could learn a few things from him.
- Training. It's important to know the technology you're working with. This shouldn't be a news flash, but you won't be effective unless you are fluent in the development language and architecture in use. Please also be comfortable with development best practices such as those from McConnell.
- Version Control. This had better be another no-brainer. In fact, if you don't have your code in an SCC system, give up now and go into sales. You're not going to make it in software development.
- Unit tests. Make sure you have them, and make sure they're really exercising the system. It's sometimes difficult to hit 100% code coverage, but if you're not at 80% or better, you're not trying very hard, and you're badly exposed to regression bugs. You'll deserve whatever sad fate awaits you.
- Objective. Patton knew the value of planning. In this case, you need to clearly understand what you're trying to accomplish with your refactoring. Maybe there's a pattern that isn't being followed consistently. Maybe there's functionality that should be extracted into an object or component. Whatever - just make sure you know exactly what you're trying to get done. When you start to work, you'll find it easy to be distracted - there's always something else to fix or improve. While Patton also understood the value of tactical flexibility, losing sight of your objective is the best way to ensure that you'll fail.
Now you're ready to work, so crank up the chain saw. Now is not the time to be timid - you've planned for this, so make it happen. While you're in there,
- Don't leave dead code -- commented dead code is useless. It's available in SCC if you need it. You don't buy a book and expect to see all the edits. Outtakes can be funny, but not in the middle of the movie. You want your live code to be living -- not a monument to your past sins. You already decided that your old code needed to be refactored, so don't chicken out now. An agile methodology thrives on having frequent builds that are as near to production-ready as possible. You wouldn't want to ship with dead code in your project, so get rid of it.
- Don't half-refactor. You're probably going to want to try to reach some interim stable points where you can build and run some unit tests, but beyond that, try not to stop until you're done. When you are refactoring, this is your chance to apply a consistent thought process, design, and coding style across the project. Future developers will thank you if you manage not to leave a Frankenstein-style mishmash of source code.
- Keep notes. If you find additional areas that need work, make a note somewhere where you'll follow up.
- Test. You need to see clean unit tests before you're done. Remember, commenting the test out doesn't count. If you can, run through some UI-level or System testing, too.
As always, scale the process to match the task - small refactoring jobs move through planning and refactoring in seconds, but large efforts can take considerable time. Remember, though, that source code control is never optional, and if you skip unit tests, you're really asking for trouble.
What other refactoring tips do you have?