We are doing a research project as civil engineering students at our university. It will be like a CAD program capable of doing things like SAP2000. It's under the process of development. And we want to implement an undo function which can take the action back to 20-25 steps. We are thinking of making a reverse function for each of the functions in the whole program to do that. But it still seems complicated and the code will not be very clean. I'd like to ask you what is the idea behind such a function, what's the standart way of doing it in a CAD program? Actually we're programming in C# but since I think the question is very general, I am posting this question here. If you shed light to the matter and maybe give some information as to where we need to search for and so on, it will be much appreciated.
Thanks in advance,
There are several different approaches for solving this problem. I'll try to explain them and pass through all cons and pros of each approach.
The first one is the simplest. Suppose you've got some "Document-View" architecture (that means that you've got a "Document" holding all your current data and one or more "Views" which are subscribed to the document and display the data in various ways. See more here: http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professiona
Each time you perform some action, you may save the state of all the document (in a stack), and once you want to undo the last action, you just take the state of the document from the stack and set this state to your current Document. This is also called "Memento" design pattern in the mentioned above book (GOF).
The problem with this solution is that if the document size is too big, then saving it every action may be too heavy. Of cause, you may implement some "diff" mechanism to save space, but you'll load CPU.
Another solution is to use a "Command" design pattern (from the same book). Then you can implement "do" and "undo" actions for each command and save all commands you want to be able to undo later in a stack. So when you'll want to execute "undo", you'll take the last command from the stack and will call "undo" on it.
The problem with such solution is that "undo" of some commands is not always trivial and commands may be very complex to implement.
I was thinking about another solution that might help you. You may implement your "Document" as a set of some items, and to use "Command" design pattern for executing commands. Each command will save a list of "items" that were changed during command execution. And each item will hold a stack of "Mementos" of the desired depth. Each time you'll want to undo a command, you'll just pass through a list of changed items and will call "undo" on each item. Each item will update its state from that from the top of its stack.
The only drawback of this solution is a need to implement "save memento" and "restore memento" methods for each one of the items.