Refactoring



Refactoring is a large topic with enough material to fill a few books. In fact, it has filled a few good books. Clearly we don't have room for all of that on an index card but at least we can provide some meta-guidance on the topic.

Done only with a green bar (all tests passing) never with failing tests. No matter how much you want to rename, extract, or modify the code you really should have green (even an ugly green) before you try to refactor.

Always run the tests before and after the refactoring steps. Make sure you know that the system worked before and after each step. Check before, so you aren't confused about origin of breakage, and after so that you know you've done a good job. Skip this at the peril of having to use debugging or having to revert a set of changes. Always have a single reason to fail.

Refactor incrementally: have only one reason to fail. This cannot be over-recommended. Michael Feathers describes programming in his book as "the art of doing one thing at a time", which has been a very good bit of advice through the years. There is a good reason that the refactoring book gives recipes of tiny steps. This incrementalism is worthwhile and hard-won habit.

Add before removing when you are replacing a line. For instance, if there is a complex calculation and you are replacing it with a function that calculates the same result, place the new call & variable assignment right after the old calculation. Run the tests. If the result is different, comment out the call and try again. Don't delete the original until you know for sure that the new code is equivalent.

If you move a method to a new class, you must move or create a test. Otherwise your tests become increasingly indirect. Indirect tests do not produce a good smell.

Changing functionality is not refactoring. That would be correction or implementation. Calling a functional change a "refactoring" is not entirely honest. Refactoring does not change what the code does, it only changes where the code is located.

Increasing performance is a story, not refactoring. This is another misuse of the term "refactoring." The point of refactoring is to improve the structure of the code. While performance can accidentally result from simplifying the code, it is the simplification and not the performance that is the object.

The books outlined above will give a better idea of how to perform refactoring. At least the index card can help remember the circumstances in which one should perform the task.

1 comment:

  1. Another bit of rationale for writing tests on a move is that it creates documentation for what is now publicly-exposed behavior.

    ReplyDelete

Note: Only a member of this blog may post a comment.