We spent a lot of time optimizing Undo. I would estimate that the optimization cost about as much as three or four new features, or more if they were easy, like new tags. Now, we did have a special motive, to show that our simple Undo wasnt just a trick. We wanted to find out whether Undo really did spell doom for our incremental approach, and we found out that it did not.
But there is a lesson here for a real project, if not for the book project. Had we ignored the storage inefficiency of Undo for a while and shipped a version with a simple but working Undo, we could have put a more useful product in the hands of our users sooner. Optimizing Undo would still have to be done, but it could have been left for a later day. It would have been no more difficult later than it was. Maybe even easier, considering the number of stumbles I made.
As programmers we are sometimes accused of gilding the lily. Yet we fear leaving things till later, because they might be harder to do. And, of course, no one likes to do less than their best work. I believe, though, that if our code is well-structured and if our ideas are well-explained and well-encapsulated, optimizations like these can be done on customer time. They can be done when requested , and we can deliver more useful capability earlier.