Chapter 15. Putting It All Together

by Kent Beck

Now you have all the pieces of the puzzle. You’ve learned the refactorings. You’ve studied the catalog. You’ve practiced all of the checklists. You’ve gotten good at testing, so you aren’t afraid. Now you may think you know how to refactor. Not yet.

The list of techniques is only the beginning. It is the gate you must pass through. Without the techniques, you can’t manipulate the design of running programs. With them, you still can’t, but at least you can start.

Why are all these wonderful techniques really only the beginning? Because you don’t yet know when to use them and when not to, when to start and when to stop, when to go and when to wait. It is the rhythm that makes for refactoring, not the individual notes.

How will you know when you are really getting it? You’ll know when you start to calm down. When you feel absolute confidence that no matter how screwed up someone left it, you can make the code better, enough better to keep making progress.

Mostly, though, you’ll know you’re getting it when you can stop with confidence. Stopping is the strongest move in the refactorer’s repertoire. You see a big goal—a host of subclasses can be eliminated. You begin to move toward that goal, each step small and sure, each step backed up by keeping all the tests running. You’re getting close. You only have two methods to unify in each of the subclasses, and then they can go away.

That’s when it happens. You run out of gas. Maybe it’s getting late and you are becoming fatigued. Maybe you were wrong in the first place and you can’t really get rid of all of those subclasses. Maybe you don’t have the tests to back you up. Whatever the cause, your confidence is gone. You can’t make the next step with certainty. You don’t think you will screw anything up, but you’re not sure.

That’s when you stop. If the code is already better, integrate and release what you’ve done. If it isn’t better, walk away. Flush it. Glad to have learned a lesson, pity it didn’t work out. What’s on for tomorrow?

Tomorrow or the next day or the next month or maybe even next year (my personal record is nine years waiting for the second half of a refactoring), the insight comes. Either you understand why you were wrong, or you understand why you were right. In any case, the next step is clear. You take the step with the confidence you had when you started. Maybe you’re even a little abashed at how stupid you could have been not to have seen it all along. Don’t be. It happens to everyone.

It’s a little like walking along a narrow trail above a one-thousand-foot drop. As long as the light holds, you can step forward cautiously but with confidence. As soon as the sun sets, though, you’d better stop. You bed down for the night, sure the sun will rise again in the morning.

This may sound mystical and vague. In a sense it is, because it is a new kind of relationship with your program. When you really understand refactoring, the design of the system is as fluid and plastic and moldable to you as the individual characters in a source code file. You can feel the whole design at once. You can see how it might flex and change—a little this way and this is possible, a little that way and that is possible.

In another sense, though, it is not at all mystical or vague. Refactoring is a learnable skill, the components of which you have read about in this book and begun to learn about. You get those little skills together and polished. Then you begin to see development in a new light.

I said this was a learnable skill. How do you learn it?

Get used to picking a goal. Somewhere your code smells bad. Resolve to get rid of the problem. Then march toward that goal. You aren’t refactoring to pursue truth and beauty (at least that’s not all there is to it). You are trying to make your world easier to understand, to regain control of a program that is flapping loose.

Stop when you are unsure. As you move toward your goal, a time may come when you can’t exactly prove to yourself and others that what you are doing will preserve the semantics of your program. Stop. If the code is already better, go ahead and release your progress. If it isn’t, throw away your changes.

Backtrack. The discipline of refactoring is hard to learn and easy to lose sight of, even if only for a moment. I still lose sight more often than I care to admit. I’ll do two or three or four refactorings in a row without rerunning the test cases. Of course I can get away with it. I’m confident. I’ve practiced. Boom! A test fails, and I can’t see which of my changes caused the problem.

At this moment you will be mightily tempted to just debug your way out of trouble. After all, you got those tests to run in the first place. How hard could it be to get them running again? Stop. You are out of control, and you have no idea what it will take to get back in control by going forward. Go back to your last known good configuration. Replay your changes one by one. Run the tests after each one.

This may sound obvious here in the comfort of your recliner. When you are hacking and you can smell a big simplification centimeters away, it is the hardest thing to do to stop and back up. But think about it now, while your head is clear. If you have refactored for an hour, it will take only about ten minutes to replay what you did. So you can be guaranteed to be back on track in ten minutes. If, however, you try to move forward, you might be debugging for five seconds or for two hours.

It is easy for me to tell you what to do now. It is brutally hard to actually do it. I think my personal record for failing to follow my own advice is four hours and three separate tries. I got out of control, backtracked, moved forward slowly at first, got out of control again, and again, for four painful hours. It is no fun. That’s why you need help.

Duets. For goodness’ sake, refactor with someone. There are many advantages to working in pairs for all kinds of development. The advantages work in spades for refactoring. In refactoring there is a premium on working carefully and methodically. Your partner is there to keep you moving step by step, and you are there for him or her. In refactoring there is a premium on seeing possibly far-ranging consequences. Your partner is there to see things you don’t see and know things you don’t know. In refactoring, there is a premium on knowing when to quit. When your partner doesn’t understand what you are doing, it is a sure sign that you don’t either. Above all, in refactoring there is an absolute premium on quiet confidence. Your partner is there to gently encourage you when you might otherwise stop.

Another aspect of working with a partner is talking. You want to talk about what you think is about to happen, so the two of you are pointed in the same direction. You want to talk about what you think is happening, so you can spot trouble as soon as possible. You want to talk about what just happened, so you’ll know better next time. All that talking cements in your mind exactly where the individual refactorings fit into the rhythm of refactoring.

You are likely to see new possibilities in your code, even if you have worked with it for years, once you know about the smells and the refactorings that can sterilize them. You may even want to jump in and clean up every problem in sight. Don’t. No manager wants to hear the team say it has to stop for three months to clean up the mess it has created. And, well, they shouldn’t. A big refactoring is a recipe for disaster.

As ugly as the mess looks now, discipline yourself to nibble away at the problem. When you are going to add some new functionality to an area, take a few minutes to clean it up first. If you have to add some tests before you can clean up with confidence, add them. You’ll be glad you did. Refactoring first is less dangerous than adding new code. Touching the code will remind you how it works. You’ll get done faster, and you’ll have the satisfaction of knowing that the next time you pass this way, the code will look better than it did this time.

Never forget the two hats. When you refactor, you will inevitably discover cases in which the code doesn’t work right. You’ll be absolutely certain of it. Resist temptation. When you are refactoring, your goal is to leave the code computing exactly the same answers it was when you found it. Nothing more, nothing less. Keep a list (I always have an index card beside my computer) of things to change later—test cases to add or change, unrelated refactorings, documents to write, diagrams to draw. That way you won’t lose those thoughts, but you won’t let them mess up what you are doing now.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset