Three attempts at implementing the same idea, and each one fails. Why did I stick to this idea so long? My only explanation is that I had done all that design on it, and I was confident that it should work. Even when the signs arose again and againexamples of perfectly common cases that the design didnt handleI kept trying to hammer it into shape.
My colleagues Kent Beck and Martin Fowler coined the notion of code smells, characteristics of the code that tell us that it needs refactoring. As I have a very sensitive sense of smell, the term bothers me. But if a couple of lines of code duplication are a smell, then what you have just read surely reeks. Three tries , over a number of days, to do the same thing, and all come to nothing. What were the signs that I should have seen? What are the signs that you and I should look for as we go forward? Here are a few ideas:
Lack of confidence in tests. Many times in this chapter, I feel and express that the tests arent helping. Yet I never really go to work on the tests. Instead I put it off.
Long periods between green bars. Instead of going for a few minutes without my tests running, I went for hours. If the tests arent running, we really dont know whether we are writing good or bad code.
Sun setting on bad code. Sometimes I even stopped a session with the tests not running. This is never a good idea. If I cant figure it out today, tomorrow isnt likely to be better, since I will have lost the picture by then. Its true, sometimes when we get up from the machine, we see our mistake. But its wiser to get to the green bar, even if we have to do it by removing todays code.
Large editing steps. There were some very big edits in this series of sessions. Instead of a couple of lines at a time, I was putting in whole classes, whole interfaces, in a blob. This is taking a big risk. Because Im a smart programmer, that kind of risk often pays off. Because Im a stupid programmer, instead of pretending it didnt happen, Im telling the world about it.
Console printing. Sometimes it does make sense to print out some information to find out whats going on. There was a lot of instrumentation in this chapter, more than I even showed. The need for tracing printouts and the like is a clear sign that we dont understand our own program. How is it going to work if we dont understand it?
Debugging. The same is true of debugging. Spending time in the debugger tells us that were confused . I even remember one time during this debacle where I started thinking that I should learn more of the debuggers features! Wrong! Better not to need it, and the rest of this book tells me that I know how to program, and do better without it.
Some of our best lessons come from our worst times, and thats why I decided to leave this part in the book. It would have been easy enough to move from the simple Undo to the nifty optimized one, and to drop this material right out. Truth be told, we see here some real examples of why I try to work in the style this book talks about. When I work in tiny, simple steps, supported by tests, things go smoothly, easily, and well. When I work in bigger chunks , even supported by more up-front design, things dont go so well.
What is most interesting to me is that the way this effort went isnt much different from how my workand perhaps yourshas often gone in the past. Long, dark times, punctuated by small successes, and finally, through sheer effort and intelligence, we make something work. Im proud of all the things I have made workand work wellover the years . And Im more proud of having learned some better ways to work.
Now if I can just remember to stick to them...
Go now, and sin no more. Ill try to do the same.