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

Reply via email to