Le 31 oct. 2010 à 20:59, Eric Wasylishen a écrit :
>> For merging an old operation, Mark and Retrace (or Address Space
>> Transformation) doesn't compute/derivate a new operation that is valid in
>> the current context (the OT way), but simulates an adjusted context in which
>> the old operation can be executed. I use 'context' (e.g. the position of the
>> objects in an array) as a synonym for 'space'.
>> It sounds simpler than OT, no need to support the complex transpose
>> operation. I'm not yet sure that the Mark and Retrace approach as the same
>> flexibility than OT. Various recent papers discusses how to improve it
>> though. Recent ones include:
>> -
>> http://research.microsoft.com/en-us/um/redmond/groups/connect/cscw_10/docs/p159.pdf
>> - http://www.scientific.net/AMR.97-101.3314 and
>> http://www.computer.org/portal/web/csdl/doi/10.1109/CSCWD.2009.4968039 (I
>> haven't read these)
>> The last ones are about a CAD app, so it might be interesting to see how
>> they cope with the complexity of such an application.
>
> Cool.
> Btw, this is the technique I'm currently implementing for doing live
> collaboration: http://neil.fraser.name/writing/sync/
> I really like this one; I think it's easy to convince yourself that it works.
> :-)
I'll take a look and let you know if I'm convinced :-)
> One thing I experimented with was writing a copy operation that uses the
> model description to do a smart copy. Here's a version I sketched out: (it's
> in ProjectDemo, but I haven't really tested it)
>
> - (id)copyWithZone: (NSZone*)zone
> {
> COObject *newObject = [[[self class] alloc] initWithModelDescription:
> _description context: _ctx];
> for (ETPropertyDescription *propDesc in [[self modelDescription]
> allPropertyDescriptions])
> {
> if (![propDesc isDerived])
> {
> id value = [self valueForProperty: [propDesc name]];
> if ([propDesc isComposite])
> {
> id valuecopy = [value copyWithZone: zone];
> [newObject setValue: valuecopy forProperty: [propDesc name]];
> [valuecopy release];
> }
> else
> {
> [newObject setValue: value forProperty: [propDesc name]];
> }
> }
> }
> return newObject;
> }
Looks very elegant :-)
> It copies only non-derived properties, does a recursive copy on properties
> which are 'composite', and just copies the pointer to other properties.
> (although, I see one problem - we usually want to treat primitive objects
> (NSString NSNumber etc) as part-of the object, so a copy should be made of
> the,.)
A partial solution is to check whether the property description is an attribute
or a relationship. See below…
> To me, it seems like the natural way to write -copy.. and makes me think that
> trying to implement copy as either "deep copy" or "shallow copy" is a hack
> for people who don't have a metamodel. :-)
I like the idea, but I think the problem is much more complex in real use
cases.
A basic issue is that imo it's better to avoid accessors to do a copy
(initialization or serialization too). When model objects are simple (roughly a
property list), it's ok. But when the accessors starts to become not so dumb
and rely on the object state, the complexity grows quickly in -copyWithZone:…
You have to ensure the accessors work as expected with various partially
initialized object states, these special object states usually won't occur
outside of -copyWithZone:. To make things worse, reordering the method calls in
-copyWithZone: can break something when the same reordering would work just
fine outside of -copyWithZone:. The reordering just introduces new partially
initialized object states the accessors have to take in account.
A good example of this kind of complexity is the GNUstep NSScrollView archiving
code, I have fixed several bugs in it, but I'm not sure it is not buggy,
because checking the accessor correctness in NSScrollView, NSClipView,
NSScroller and related classes against all the partially initialized object
states is not easy.
I have also observed cases where I changed an accessor and by doing so broke
the serialization code, although the change was completely unrelated (this was
introducing new object states only in the scope of the serialization code).
The real trouble is that serialization bugs such as the previous one are easy
to miss. For a widget, the bug might prevent a single boolean to be serialized
correctly, but this won't be visible until someone serialize/deserialize this
widget again. I mean… a nib can be deserialized each time its application is
tested, but the bug won't occur until the UI is edited (and thereby serialized
again).
Though I'm pretty sure I don't need to convince you about serialization issues
;-)
To come back to the copy support… When I started working on the item tree
cloning in EtoileUI a while ago, I realized how bad is the copying support in
most languages/frameworks. I'm still suprised nobody has really tackled this
problem seriously.
For EtoileUI, I had to implement basically something that looks similar like a
mini-serialization mechanism (post copy phases/hooks and a map to track
original vs copy in each object graph to set the relationships correctly in the
copy), it's doable without too much complexity because each item is almost like
a sandbox (e.g. controllers are aspects and hence copied too). To give an
example… For a button target that was set to a parent controller, in the new
item tree the target has to point to the controller copy and not the original.
I haven't worked on it, but what I have been thinking about is to generalize
this model, then build copy and serialization support on the same base. What
what would be nice is to leverage the EtoileSerialize ability to introspect
objects at runtime and provide a special ETCopier class along ETSerializer and
ETDeserializer. This way we can use the same code to introspect objects, manage
the reference adjustments and provide similar or identical hooks. In many cases
we can probably prevent the duplicated logic between serialization and copying.
I have no proof, but I think it's doable, specially if we leverage the
metamodel, and largely worth the investment in the long run :-)
Few days ago, I wrote some NSKeyedArchiver code to archive the metamodel and I
was surprised to discover it was pretty much trivial :-) So as you suggest I'm
pretty sure we can leverage the metamodel to support both serialization and
copying. An interesting thing could be to make EtoileSerialize uses the
metamodel when requested, to get an automatic serialization close to the keyed
archiving result, in the sense it's less vulnerable to the upgrade problem
(e.g. renaming a non-transient ivar and forgetting to update the serialization
code. If we use the metamodel and makes it explicitly serializes the property
ivars, the metamodel could automatically check each property description
corresponds to a concrete property).
I'm getting tired, so I'm not sure what I wrote in the last sentence makes
totally sense :-p
Cheers,
Quentin.
_______________________________________________
Etoile-dev mailing list
[email protected]
https://mail.gna.org/listinfo/etoile-dev