In this chapter, we demonstrated the following points:
Refactoring allows the design of the code to improve by following a series of simple steps. For example, in this chapter we went from bad procedural code to a cleaner object-oriented implementation ” while staying close to the green bar and without a large-scale rewrite. When you write your code, we expect you will refactor as you discover the need for it (not when it s too late and the code is so messed-up that it is more appealing just to throw it away and write it anew). The more paranoid you are about all the little problems in the code, the more proactive you will be in correcting them when you notice them rather than waiting until you have a big job on your hands.
There was no mention of a debugger. Due to the small steps and the ability to verify them with the tests, you will not have to spend as much time debugging the software because changes can easily be rolled back to the previous state.
The ability to do refactoring is a benefit that you receive from your investment in tests. The tests provide the safety net that enables the routine maintenance of the program. These tests allow you to alter the code without worrying about whether or not you have broken it. Without the tests, you would not be able to move as quickly or as incrementally through this problem. In fact, you probably would have scrapped the whole thing and rewritten it.
You should not turn your pragmatic paranoia into a morbid obsession . Your goal, after all, is to write software efficiently and not get stuck tweaking existing code into unattainable perfection . When do you stop refactoring? There is no simple and fast rule here that we can offer. The general rule of thumb is that you need to refactor whatever code duplication you discover and move toward code that clearly communicates your intentions. And if you have some amount of code duplication that serves the goal of clearly communicating your intentions, it is all right to keep it.
Last, the order in which we did the refactorings is only an example. There are many other ways this code could be refactored and many other possible implementations . The main point driven home by the series of steps is that the code is the primary feedback mechanism for possible future refactorings.