Never Use a Warning When You Mean Undo
alistapart.com
alistapart.com
Okay, so version control deals with TEXT, but applications deal with internal states that have innumerable interactions. For every one of those crazy subversion errors there are lots of data corruptions that could occur--and once they do, you've stuck your user with something potentially unsolvable through manual intervention.
A simple example would be: User deletes event at 3:00 - 3:30. User adds event at 3:00 - 3:30. User undeletes event at 3:00 - 3:30. Fairly easy to resolve, seemingly:
1. Undelete selected. 2. Check conflict. 3. [possible actions]: a) Announce conflict. b) Override new event. c) Allow multiple events at same time. (Hmm...was this allowed through normal interractions.) d) Prevent undelete, but allow the user to delete new event.
...that sort of thing can balloon uncontrollably. Suddenly, for every "undo" you have a tree of options for every possible conflict that may have arrisen from system state changes.
No, a better way would be:
1) Generic undo selected. 2) New event undone. 3) Generic Undo selected. 4) Old event restored.
...but then you have a system-wide "version control" system to deal with.
Next step (I'll call this B, below) is keeping a linear undo history, which you can navigate one step at a time, like most text editors today. This doesn't bring any of the complications you mention here.
One way to get more sophisticated is exposing a linear undo history a la Photoshop, from which you can remove intermediate old steps. This seems to work for Photoshop, but in general it sounds like a can of worms, for the reasons you mention.
Another path up from B is to keep an undo history tree, with the following properties:
- You can display the tree explicitly somehow, and navigate it. So, e.g., selecting a node shows you the state of your content at that time.
- You never delete nodes or branches. To undo a bad decision, you go back to the last good node and start a new branch from there.
- You can still move data between nodes. For example, in a text editor I would be able to cut text in a discarded branch to incorporate it to my current one.
Does this make sense to you?
I don't understand the problems you mention with subversion, but aren't those implementation issues? Or do you mean that these are inherent limitations in the undo concept?
Re: implementation, it of course depends on the application. The key difficulty is having an inverse (undo) for every mutating operation you have. This may get tricky to do efficiently for some applications (video editing comes to mind). An additional complication may come from, e.g., undoing every word rather than every keystroke. So you need some provision for gathering 'small' actions that you don't care for saving separately in history.
The history itself is nothing more than a list.
Now, I understand how it can be very hard to retrofit this functionality in an app that was made without this in mind. I'm redoing a hobby project from scratch because of this.
Anyway, care to give details on the complications you've found? I'm not trying to convince anyone it's easy; I'm trying to help, and maybe gain a better understanding of the problems in the process.
The fact that they are only available for a short time is a design decision. If your point is that sometimes it doesn't make sense, design wise, to provide undo, then I agree.
To copy text, even.
-- Alex