As far as I am aware, the best-known implementation for Undo is to have the program create a centralized list of edit actions, or commands, that retain enough information to undo the action. To be honest, I can t think of another good way to do it. Chet and I talked on the phone this morning about how this might be implemented. I wish he were here pairing with me, because frankly I m a bit scared that this could be tricky, but I feel the need to get started even though I ll be on my own. Well, the worst that can happen is that I ll learn something, and I promise to tell the truth about what happens in this chapter.
In XP, we like to ask, sb What is the simplest thing that could possibly work? and in fact I often like to do the simplest thing that could possibly work. The original question is intended to get us thinking simply, while I have adopted a general strategy of actually doing something very simple, given that it just might work. I have wanted to learn what happens when we push simple design plus refactoring to the limit. So far, my experience has been that it works just fine. In that spirit I suggested the following implementation of Undo in my phone call with Chet: OK, on every keystroke, we make a copy of the entire contents and cursor location of the TextBox and save it away. Then for Undo, we just go back through the list, slamming the entire contents back.
I was concerned that doing it that way would seem like cheating. No one would really do Undo by saving a copy of a whole file on every keystroke. I was worried that you would miss the lesson that incremental design works because you might feel that the solution wasn t realistic. Chet felt that it might be OK to do it that way. There s no evidence that it would be overly costly in real cases, though of course it wouldn t take long to come up with a test that showed it was too much. He wasn t worried about the solution not seeming fair, and he reminded me of that great line in Paul Newman s movie, Judge Roy Bean , where the judge shoots a would-be attacker, Dirty Bad Bob the Albino, in the back. The observers say, He never had a chance. Judge Bean replies, If he wanted a chance, he should have gone somewhere else.
Still, we do want the book to be credible. So we talked a bit further, and I came up with some observations that might be useful, while thinking about how awful the copy everything solution is. Imagine that the user is typing along, and we re duly copying the whole text buffer and cursor position every time. Generally speaking, the text buffer doesn t change much ”usually only by one character. Maybe we could reduce the storage burden by doing some kind of diff on each pair of buffers, to see what happened .
Almost always, on every keystroke, one character is inserted into the text. Sometimes a character is deleted (on backspace or Delete), and sometimes a character is replaced , when the TextBox is in overstrike mode. That would collapse the recorded action down from something the size of the whole document to something more like the size of a single character. But the differencing could be difficult.
But wait. Most of the time as the user edits, what s really happening is something like this:
...
With cursor at 20, user types "H";
With cursor at 21, user types "e";
With cursor at 22, user types "l";
With cursor at 23, user types "l";
With cursor at 24, user types "o";
...
That makes me think that we might be able to compress the stream of actions into something quite livable. It might possibly work, so we ll do it.