Legacy Code Change Algorithm
Source: Feathers, Michael. Working Effectively With Legacy Code, Prentice Hall PTR, 2005.
A simply-written technique is not always easily written. The best reference for this technique is Michael's book, of course. Second best is the paper available through Object Mentor's web page (Michael's published papers).
To identify change points is either very easy or very hard. Find the place where you want to make the next change in order to get a new feature added or to eliminate a bug.
The point of change may be nested too deeply inside other methods or into a long if/then/else case, or buried in classes referenced by other classes. Michael suggests that this effort is proportional to the the sickness of the code.
When you know where the code needs to be changed, you need to find test points . Michael calls them "inflection points." The inflection point is in the call tree where any change below it will either be evident or insignificant. The test point is often not the change point.
Break dependencies that make it difficult or impossible to start writing tests to get some coverage of the current behavior at the test point(s). It is normal, in a legacy code base, to do some "pre-factoring" to make testing possible. This is tricky territory, since you don't yet have test to protect you as you work. Expect to spend time running and manually validating basic functionality. You are of course better off if there are some tests that cover the test point.
Write tests to cover existing behavior at the test point. Remember your tests will need to comply with the F.I.R.S.T. principles.
Make changes and refactor the change point in the normal test-first manner, enjoying the test coverage you've built.