I believe that this experience indicates something but does not prove it. This is just an example, and it s possible to argue that somehow, as we were refactoring along, we accidentally pushed the design in a direction that just happened to be good for Undo, or maybe we even subconsciously did so, knowing that Undo was coming. Or, maybe I cheated somehow, by making design decisions that I knew were good for Undo, while giving other flimsy reasons for doing so, in an attempt to bamboozle you, pull the wool over your eyes, and flim-flam you. But would I do that? I don t think so, since I m trying to help, and I won t get paid extra if you get in trouble following my advice.
Therefore, I think those explanations are less compelling than this simpler one: Writing clean code and removing as much duplication as we can almost inevitably leads to a program where the thing we want to do next needs to be done in just one, or a very few, places. We have seen that happen throughout this book, and we have just seen it happen in one of the most challenging situations people can imagine: needing to put Undo into a program that wasn t designed for it.
That s important because when we worry that an unexpected change will be more expensive unless we prepare for it, we are really saying that we re worried that the change will have to be made in lots of places and that lots of code will have to be changed around. It seems quite plausible to me that this can happen only if an idea in our heads is represented in many places in the code and that idea needs to be changed. But our simple style of development focuses on putting every idea we have into the code and on removing all the duplication. The result is that the ideas tend all to be in just one place. So even if the idea is wrong, there tends to be only one place needing to be changed.
Ultimately, you need to do your own experimentation and make up your own mind. Build up skills in recognizing duplication and expressing ideas, and as you practice those skills, you can work on reducing how much up-front preparation you do in support of things you see coming. I m comfortable doing very little preparation, as a result of many years of general experience and around five years of working in this simple evolutionary style. Your point of balance will surely be different, but I m sure you ll find a balance that will let you focus a bit more on results for your customer and a bit less on preparing for a future that may never come.
One of my technical editors thinks that I m a bit too happy with the result so far. He points out that this marvelous Undo implementation is consuming memory madly, and that s just not good enough. True enough, it is using too much memory, but that is a matter that s internal to the implementation. We ll address that in a moment. My point here is that more design of the rest of the editor was not needed to put Undo in the right place. I m happy because no matter what happens next, we did not have to redesign the whole program to support Undo, and now it s clear that we will not need to do so.
Another editor points out that there is something a bit odd about using the TextModel as the object that gets pushed on the stack of the TextModel. It is a bit asymmetric or something. In particular, the Undo stack of the pushed TextModels never gets used. This is a good observation: we have two ideas here tied up in one object. One idea is holding the text that is being edited, and the other is holding the stack of things to be undone. When one object has two functions, the code is not expressing our ideas as well as it should. I didn t see that issue while writing the code, and neither did my pairs. No excuses, sir. It would have been better another way. I hope this is the worst mistake I ever make in the rest of my life. However, because at this writing I know what is coming up, I am sorry to say that a bigger mistake is coming.
Finally, one of my editors points out that all this was made much easier because the editor s data is primarily stored in a model class that is part of the application, not just a graphical control (TextBox). This is certainly true, true enough that I consider it a necessary design step for every system: separate model from view. You recall that we did this way back in Chapter 4, Extracting the Model.
Now please read on about optimizing this effective but inefficient Undo and the problems that came up as we did it.