72

Why do most applications have fairly limited 'undo' history functionality?

I've been caught out on multiple occasions (granted its technically my fault) where I've needed to undo a number of changes (be it in photoshop or whatever else) to be hit by a greyed out undo button - no further history available. I don't know about you, but potentially losing a lot of work because of this limitation results in a terrible user experience.

Is there a reason why applications can't just hold at least a full-session history? Surely a temporary file is all that's needed to store changes and said temporary file could be configured to the user's preferences (in terms of max size, etc)?

9
  • 41
    +1 I hate this in Windows' notepad application where it is limited to only one undo.
    – user371
    Oct 12, 2011 at 10:02
  • 1
    Good example, I forgot about notepad. Very true.
    – Anonymous
    Oct 12, 2011 at 10:08
  • 3
    MS Word used to have only one undo back in the 1990s. As long as you KNEW you only had the one undo it wasn't a big problem - you learnt to 'think before acting'. The problem has rather emerged now that some applications let you do a lot of undoing - and then you discover to your cost that others don't.
    – PhillipW
    Oct 12, 2011 at 13:37
  • 3
    @PhillipW - I don't think that is a logical way of looking at it. It sounds like you're saying that people should thoroughly think things through before each and every action in an application to ensure no more than a single mistake is made and reverted at a time. The way I understood your comment is similar to 'if oil runs out tomorrow, it will be a bad thing that we ever used combustion engines as now we have to do without them'.
    – Anonymous
    Oct 12, 2011 at 14:12
  • 3
    This is a great issue. From a UX POV, undo is vitally important ( and I hate systems that only have one undo ). It is technically complex often, but an important confidence boost. Oct 12, 2011 at 20:15

10 Answers 10

108

Trust me when I say this - undo/redo is one of the biggest implementation, testing and maintenance headaches in any significantly sized application.

Granted, it is a wonderful thing to be able to undo/redo something as it relaxes the user and lets them test and explore their environment without worry. However, the usefulness of an undo history starts to diminish right after the first undo. Slowly, mind - but surely.

Full kudos to those that do provide a full undo history, but it is almost certainly as a result of a well planned, well executed approach with a supporting frame work, implemented from day 1, and around which all functionality revolves.

If that framework is not introduced first, it's a major challenge to bolt it on afterwards, and it's easy to get bogged down in it.

The problems lie with:

  • The rapidly escalating complexity of testing undo/redo with any possible action in any possible sequence of changes of any size.
  • Ensuring that the state of the system after the undo of each step is the same as it was before it was originally done, - e.g. ready for the next undo, or the next redo
  • Correct consideration of what is an undoable action

In addition, it is almost universal that if you undo a string of actions and then make another change, you cannot redo all the steps you just undid, because the system has changed state and the redo may well not be valid.

Now one popular use of long undo/redo history is to go back and look at something how it was, and then to go forward again.

I would suggest that the annoyance of not being able to undo more than say 10 steps is not nearly as annoying as undoing 50 steps and then accidentally pressing a keyboard button which throws away the redo history so that you can't redo all that work you just did. I for one get very nervous when I've undone something over a lot of steps, and tend to save first as a fall back, and maybe therein lies the lesson: save often and save versions.

I totally agree that a full undo history is highly desirable - it's just not simple, and that's why it gets dropped down the feature list when tight time and budgetary constraints come into play.

14
  • 8
    Good answer, you brought some very valid, interesting points to light. Undo/redo history could easily get very complicated if there needed to be several branches of changes - it almost ends up becoming like source control if you made different revisions at different steps of undo's, each with it's own set of re-do's. I think what I have in mind for the 'perfect' history system would involve a GUI - bolt-on auto-committing tortoiseSVN for file states...
    – Anonymous
    Oct 12, 2011 at 10:28
  • 4
    @JohnGB It depends if it was designed in from day 1. If not, then the move from one undo to multiple undo is a major step, because of the need to also restore the state of the system in preparation for the next undo. The more complex the application and the greater the number of criteria which define the state of the system, the more you have to consider what to restore, and the more there is to go wrong. In actual fact that's the wrong approach, and the problem should be posed at day 1): how do you design your data model alongside a multiple undo framework which is system state independent Oct 12, 2011 at 10:55
  • 4
    This is basically it. Its limited for the needs of the programmers not the users. Oct 12, 2011 at 14:43
  • 4
    @RogerAttrill, your second to last paragraph mentions throwing out the entire redo history, which is itself a flaw of the standard linear undo pattern. The ideal would be a hierarchical history-state tree so that typing a character at revision #36 would create a new branch, rather than override the existing path. This historical-state tree is used all the time for users of version control. One of the major restrictions to these models ends up also being resources. If you're modifying an image that's 10MB, keeping the last 10 states might require 100MB of memory (ignoring compression of course)
    – zzzzBov
    Oct 12, 2011 at 15:17
  • 6
    @zzzzBov: keeping the last 10 states of a 10MB image wouldn't necessarily require 100MB of memory. It requires 10MB for the 1st and for each state thereafter, the difference or "delta" would be stored. Oct 12, 2011 at 20:52
12

There are both technical and business drivers for this problem.

Technically, undo/redo is very complex to implement for an application of any reasonble complexity. Not only does it need to handle the complexity of the app, but it requires tracking of state over time and the ability to reset that state. In some application spaces, notably graphical editing, true undo is not technically feasible, you can only take a snapshot after each action and return to the prior snapshot. If you insert a letter in notepad, undo can relatively easily delete that letter. If I apply some mathematical transform on a graphical image, I can't necessarily replay the reverse mathematical process and get the original image. Storing unlimited number of snapshots of both data and state will become resource limited.

From a business perspective, if I can apply 100 man days (as an example) to implement unlimited undo, or I can apply 100 man days to deliver 3 new requested user features, I may get a better return on my 100 days by implementing the 3 new features. This may be shortsighted, but we have certainly seen shortsighted business decisions before.

10

The book Design Patterns outlines how to implement undo/redo functionality (see the Command Pattern). It's a slick design, it'd be easy to test, and having unlimited undo's probably wouldn't be much of a problem. However, it comes at the cost of designing your entire system around the pattern and undo/redo looks like it might become incredibly difficult for complex data models.

However, simply storing all relevant application state, at each revision point, would be easy to design and implement. You could even add it to the application at later development stages without much effort. However, this easier strategy comes at the cost of memory, which you would probably manage with a limited number of undos/redos. ... hence the "limited 'undo' history functionality".

7

I would prefer versioning like e.g. Google Docs offers. You can jump between different versions of your document and revert to any of it. In my opinion this is often a more useful approach, although it might not be reasonable for all kind of applications to keep a complete history of changes.

2
  • 9
    I don't agree. Versioning involves taking a particular change point. I don't want that - I want to undo the last 10-15 things I have just done just now. Versioning is important for other forms of reversion, but not as a replacement. Oct 12, 2011 at 20:19
  • The question wasn't 'What would you prefer?', though. And if it was, that would justify the given closure reason. As-is, I'm not sure that's justified. Dec 29, 2016 at 8:27
5

Because your RAM is limited :-)

P.S - I know you have 8 GB of RAM today but still if you are using applications like Adobe Photoshop or perhaps 3D software, which save a lot of information if you have significant amount of changes, then this can be a huge resource hog.

6
  • 3
    There are numerous ways of approaching this - I mentioned temporary files in my original question that could easily be used to log changes to free up RAM and ensure the application performs as it should. This technique would just result in a few extra delays whilst the changes are called and executed... Correct me if I'm wrong. :P
    – Anonymous
    Oct 12, 2011 at 12:25
  • 1+ But, wouldn't it be slow to pull data off hard disk? (yeah of course just a couple of seconds) But it does make a difference. Right? But practically in this era of SSD and such huge memory chips it definitely is possible for most applications
    – Atif
    Oct 12, 2011 at 18:21
  • @atif089: as the user gets further away from a state, it is cached to HDD. As he gets closer, more of it comes into memory. Oct 12, 2011 at 20:54
  • 4
    It's a much more difficult engineering problem than 'just writing it out to the hard disk as a temporary file.' Virtual memory does that. Once you have 2 levels of undo, an arbitrary level of undos is usually a matter of resource constraints like RAM. A common phrase is "two is not a number" and comes from ideas like c2.com/cgi/wiki?ZeroOneInfinityRule
    – Jon Hess
    Oct 13, 2011 at 6:51
  • @JonHess I'm confused. Your comment seems to contradict itself on multiple levels. First you say "it's much more difficult than writing to disk", then you say "virtual memory does that" (which implies it's not difficult, in fact, it happens implicitly), then you say it's "a matter of resource constraints like RAM" which makes even less sense because you just said it can be written to disk which solves the RAM problem entirely. It's not like the full undo stack needs to be loaded into RAM at once; even with any "Undo All" button you could process the undo commands in segments, no?
    – Dan
    May 12, 2016 at 13:11
3

Proper undo for a complex application is hard to design in as an afterthought, and for many applications it's simply infeasible to implement efficiently in time (i.e. reasonable UI delays) or space (i.e. too much disk or memory storage usage). Video editors come to mind; but for many applications, much or all of the document in memory would need to be saved between every edit, and that gets expensive quite quickly. Just saving the changes is often very difficult, because it's a cross-cutting concern; every modification to the application state needs to be classified as to whether it is undoable or note, and needs to have an inverse (to perform the undo).

I got so fed up with lack of proper undo for text editing that I wrote my own notepad, which actually saves the entire log of edits along with the underlying text file. That way, my undo/redo persists across instances of the application. To avoid the whole "undo 50 steps, then accidentally lose redo history with a new action" problem, the undo log is strictly accumulative - if you start with foo, then undo and replace it with bar, it saves three versions - foo, blank, and bar, so you never lose a version.

2

There is no UX reason to limit undos. The reason undos are limited are due to hardware and software limitations (which were greater in the past than today).

1

There's absolutely no good reason aside from incompetence of developers. Good software usually has a solid undo/redo implementation since it is built upon design principles that separate actions from data and its presentation. I've done this myself and I have to disagree with the Roger's answer - it's certainly not terribly complex to test, at all, if the application is designed from the start with undo in mind.

4
  • 2
    No, that's not it. They capture every few seconds, not every single action that you make. Do you only do UI work or do you also code?
    – jcolebrand
    Oct 15, 2011 at 2:06
  • 2
    And there's the rub: many applications aren't built with undo in mind from the start. There could be several reasons for this. It could be that the application's requirements have shifted. It could be that requirements gathering missed a vital process. Or it could be that an iterative design model has stumbled upon an irreducibly complex problem. Also: a developer who tells you something will be time-consuming to implement and debug is not 'incompetent'. Not all data models lend themselves to simple undo diffs. Oct 15, 2011 at 3:31
  • 1
    Who's "they" in they capture every few seconds? I'm talking about the way undo is implemented in any decent application, and I've developed quite a few. There are articles about how to implement undo out there; none of them ever suggest polling the model every few seconds... proper undo implementation is based on implementing the Action/Command design pattern properly so that every action is reversible. In more complex situations you need an undo tree, rather than a simple list. Oct 15, 2011 at 9:52
  • 1
    @AssafLavie That seems to have been a misplaced comment intended for pgfearo's answer. Dec 29, 2016 at 8:35
0

In usability terms no you shouldn't be limited, but as has been well pointed out its not easy. In my experience Notepad++ has an excellent undo feature. I suspect its part of the Scintilla component that Notepad++ is based on. Its all open source so you might be able to figure out how they implement it.

0

MS Word, OneNote and Outlook 2010 have, under certain conditions, a more limited Undo History than most people realize.

Try this: Start a new Word doc and type in a line or two of text, then, press and hold the Backspace key to remove the last few words. Now, press Undo or Ctrl-Z...to get back that backspaced text, you'll find you've now lost not only this but most of the text you typed in!

The lesson here is that Undo is tough and you must have a sound test strategy. Even the big guys can get this terribly wrong.

4
  • 1
    No, that's not it. They capture every few seconds, not ever single action that you make. Do you only do UI work or do you also code?
    – jcolebrand
    Oct 15, 2011 at 2:06
  • @jcolebrand 1. I think you're disputing that a 'press-and-hold' action is the cause of the issue, in which case you're right, but I was not even suggesting this as the cause, just one common way of repeating the problem. The cause is related to using backspace at the very end of the text block! I reported the bug to MSFT and they've confirmed its repeatable - but haven't fixed it.
    – pgfearo
    Oct 16, 2011 at 15:16
  • @jcolebrand 2. Yes, I do code - I've just finished a 2 year project developing an XML/XSLT editor. My app uses a timed undo capture, but this is done several times a second, because certain editing actions are blocked if they're deemed accidental and render the XML invalid. The undo stack must also be split so it is XML-aware, so more frequent captures keep things simpler.
    – pgfearo
    Oct 16, 2011 at 15:26
  • Fortunately everything I write gets to live in someone else's stack so I no longer have to worry about such things. Ah the fortunes of web development.
    – jcolebrand
    Oct 17, 2011 at 16:19

Not the answer you're looking for? Browse other questions tagged or ask your own question.