Re: Action based undo or snapshot based undo?
Re: Action based undo or snapshot based undo?
- Subject: Re: Action based undo or snapshot based undo?
- From: Brock Brandenberg <email@hidden>
- Date: Wed, 29 Jan 2003 23:11:36 -0600
>
> While I don't have a solution for this problem, I too am affected by
>
> it like
>
> Alexander, and would like to see how others handle the issue.
>
>
>
> What Greg mentions is possible much of the time, but it is simply not
>
> possible to do in some situations like Alexander mentions. Many
>
> mathematical
>
> problems, like optimization problems, simply do not have an inverse and
>
> cannot be undone by registering undo invocations for every attribute
>
> change.
>
> The process may simply not be reversible, no matter how much one
>
> thinks that
>
> you can reverse each and every attribute change. Destructive and
>
> non-reversible actions can occur during an optimization that are not
>
> captured by the state of the objects, and hence, cannot be undone by
>
> simply
>
> invoking attribute changes in a reverse order.
>
>
Could you give an example of this difficulty?
>
>
I posit that any action which should be undoable results in one or more
>
attribute changes in the state of your model objects. If something is
>
destructive and non-reversible it is because you are not adding an undo
>
action when you should, or parts of your application 'state' are not
>
captured by the state of the model objects, which means you haven't
>
designed your model correctly.
>
>
"Optimization problems" is a pretty wide field, so obviously I have to
>
be very vague, but optimizing means finding the values of the variables
>
in the system that maximize (or minimize) some mathematical function,
>
given some constraints. It seems fairly straightforward to me to make
>
the variables be your model objects, and register an undo whenever one
>
of their values changes. Optimizing for some function and set of
>
constraints, then, results in zero or more changes to the values of the
>
variables, all of which are reversible, and thus undoable.
>
>
I'm currently working on OmniGraffle, a diagramming and graph layout
>
application. It includes a force-directed layout action, which uses
>
simulated annealing to position graph nodes based upon constraints
>
given by the edges of the canvas and the lines between the nodes (as
>
well as other constraints). This is a classic mathematical optimization
>
problem, simulated annealing is a well-known approach, and it is
>
obviously a non-reversible algorithm. But we have absolutely no issue
>
with being able to undo a layout action, because it just decomposes
>
into many, many position changes on individual nodes, all of which are
>
trivially reversible and undoable.
>
>
I'd very much like to understand the cases in which this kind of
>
solution are not possible.
Hi Greg.
I bet we have somewhat of a terminology or semantic issue here :) To
clarify, I'm trying to make a distinction between undo actions which simply
reverse user actions by sending the same message again with values that
would restore the previous state, and undo actions that send a different
message that result in restoration of a previous state. For example, actions
like a color change can be reversed by performing the same method over again
with different values. But other actions, like removing a node from a linked
list cannot always be undone by simply re-inserting a node. If the node has
children that maintain their properties due to the position and properties
of the parent node, then removing the parent node can have very destructive
effects on the linked list, and the list may need to be "restored" by
reverting the state of the list (or at least a significant subset of it). In
our case, we have too many inter-object dependencies to simply stitch a list
back together by calling methods to re-establish links and other properties.
Plus, we could lose precision by doing so due to the nature of floating
point math.
I'm assuming that your model objects actually do save some state when you do
a simulated annealing run for layout in OmniGraffle. I can't imagine that
the model objects undo each iteration of the run, which could potentially
result in hundreds of thousands, if not millions of attribute changes. It
wouldn't take long to choke the undo mechanisms, especially if you provided
live feedback by optimizing layout while the user dragged a particular
object. This live feedback with optimization between each UI change is the
type of behavior we have in our rule-based layout program. Out of curiosity,
would a "move 5 units to the right" method in your model be undone by a move
"5 units to the left"? You can see that this could have precision problems
in some cases and might not always be the best thing to do. It's this kind
of situation where I think about restoring state rather than reversing an
action.
The issue you mention of model design is a good point. I think many times,
models are not designed correctly, so it is difficult to construct proper
restoring actions/methods. We chose to keep much of our core model as
structures in C rather than objects with ivars and methods for speed reasons
(core engine works with a HUGE structure and pointer math, not Objective-C
messages), and we simply link piggyback Cocoa objects to the structures to
handle UI interactions and store additional data like strings. So in this
case, we have methods that can restore the underlying structure data when
actions need to be undone. It's a fuzzy definition of saving state since
numerous objects will save states and numerous messages get sent to restore
the state of the entire model.
So, I think some problems can only be undone by restoring state, but the
state may be restored by restoring the state of many individual objects
rather than performing actions with "reversing" values.
Did I manage to get that out clearly? :)
Brock Brandenberg
----- industrial design @ www.bergdesign.com ------
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.