These two patterns deal with times that you’ve got a requirement to be able to undo work. There’s Memento, which is a pattern of limited use (if only because a lot of the classic implementations are already available for you to use), and Command, which is one of the most criminally under-used patterns in the whole book.
Memento
Let’s deal with Memento first. Personally, I think most of the problem with Memento is its name. It’s a checkpoint. You store checkpoints as you’re working, and you restore back to a checkpoint if something doesn’t work. A good design for a limited set of use cases. Why aren’t you going to need this very often:
- Because you’re using a transactional system such as a database and can use the transactions directly.
- Because you’ve followed good design principles and avoided having a lot of mutable state in your code.
- Because your reversibility concerns are handled by using the command pattern.
If you’re wondering how on earth you could implement this behaviour without mutable state, try taking a look at Eric Lippert’s post on immutable stacks. Usually, an approach like this is likely to be a better solution.
An interesting example where it is (probably) used is Prince of Persia: Sands of Time. In the game, you can hit a button that reverses time. By storing the state of every actor in recent frames, it can just as easily rewind them. The example also highlights the importance of keeping the mementos small: if it, for instance, chose to serialize the walls every frame, the game would grind to a halt.
Command
Let’s be clear: the command pattern is stone cold brilliant. I know I’ve just been going on about the Memento pattern. Now it’s time to wake up. Also every UI you create, every workflow you implement, has a Command pattern in it. Well actually, it doesn’t, because you don’t know the Command pattern and it’s not obvious. But it should.
Here’s the basic form of the command pattern:
interface ICommand { void PerformAction(); }
Now, in itself, this isn’t that interesting. So far, we’ve managed to represent an action (code) as an object (data). As such, it might as well just be a function delegate. However, where things get interesting is in the principal variation to the pattern.
Undo Command
To add reversibilty, we can extend the interface like this:
interface ICommand { void PerformAction(); ICommand UndoCommand(); }
We’ve got something much more interesting. All of a sudden we’ve got a pattern that you should be implementing in every GUI you ever write. This is the answer to how Word allows you to undo multiple operations. If we return to the Prince of Persia example, each monster would have a currently executing command, and the command object would need to provide additional information should as animation frames. (Don’t worry, I’m not about to start blogging about how to write a computer game.)
The reason this is so hugely important is that you need it from Day One. Adding undo features to a design that doesn’t implement the command pattern can be an exercise in frustration. Obviously, the undo command of an undo command should be a redo command. Generalizing further, you get to concepts such as the layers in PhotoShop, where you keep track of your action history on an object and can insert and replace actions.
You’ll note that GMail generalizes this concept in a couple of interesting ways:
- A “following command” concept. This is usually undo, but can be something else. For instance “send an email” has a following command of “view the email you just sent”.
- Actually, sometimes there are multiple following commands. This enables such functionality as “Invite this user to gmail”.
- Certain commands cannot be undone, and the UI supports highlighting those exceptions. (You could just implement this by returning null for the Undo command, but that would prevent you from specifying behaviours when reversibility is lost.)
Serializing Commands
It’s often an excellent idea to make your command objects serializable, both in the sense of supporting .NET serialization and also in the more general sense of being able to round-trip the object to the database. You can do the following
- Provide a complete audit log of your user’s actions
- More, be able to replay a user’s session.
- Analyze usage patterns to spot common behaviours.
- Distribute your application across multiple servers, probably by using a publish/subscribe network such as nServiceBus.
Using Commands to make Transactions
Obviously, one obvious model for implementing rollback is the Memento pattern. However, it’s also possible to use the Command pattern for this purpose. The following code illustrates how:
void PerformTransaction(IEnumerable<ICommand> commands) { Stack<ICommand> executedCommands = new Stack<ICommand>(); foreach (var command in commands) { try { command.PerformAction(); } catch { command.PartialUndo().PerformAction(); foreach (var commandToRollback in executedCommands) { commandToRollback.UndoCommand().PerformAction(); } throw; } executedCommands.Push(command); } }
Summary
We’ve covered the two main patterns to implement reversibility. In practice, the Memento pattern is often quite brittle. Changes in the behaviour of related objects could lead to changes in what has to be stored. This is less likely to happen with the Command pattern, since it separates out the responsibility for reversibility into the relevant transitions. Furthermore, command objects can be extended in further directions, taking in permissions, interruptibility, batching, to name but a few.
So, why isn’t it more heavily used? Why is it that I always see UIs that desperately try to solve the problems the Command pattern solve in ad hoc and incomplete ways? I think the problem is that it’s quite hard to refactor to use this pattern: there’s just too many parts of your code affected by pulling the command concerns together. This makes it all the more important that you design in Commands right from the start of your project.