From 67054aa06c5f184ab45a1d2cff47bbdbbde69217 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 16 Mar 2016 04:49:29 +0100 Subject: [PATCH] design the properties of the selector within TreeMutator ...and write down some insights about the architecure and design of tree binding and tree description related to the TreeMutator. When reading my notes from last year, it became clear to me that the design of the TreeMutator has evolved significantly, and became quite something different than I'd imagined at start --- wiki/renderengine.html | 51 +++++++++++- wiki/thinkPad.ichthyo.mm | 163 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 206 insertions(+), 8 deletions(-) diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 7b6aa77ef..b8d2e2253 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -8199,7 +8199,37 @@ On receiving the terms of this "diff language", it is possible to gene i.e. a ''unified diff'' or the ''predicate notation'' used above to describe the list diffing algorithm, just by accumulating changes. -
+
+
+The TreeMutator is an intermediary to translate a generic structure pattern into heterogeneous local invocation sequences.
+within the [[diff framework|TreeDiffModel]], this is a crucial joint, since here the abstract, generic, ~DOM-like ExternalTreeDescription meeds opaque, local and undisclosed data structures.
+
+→ see TreeMutatorEvolution for an extensive discussion about the principles and architecture, which gradually leads to the final design of the ~TreeMutator, as realised now in code.
+
+!Motivation
+on a very large scale within the Lumiera application, disjoint subsystems are collaborating based on the notion of a //shared conceptual structure.//
+This means, we do not share a data model -- rather we exchange ''diff messages'' with respect to this assumed, common, conceptual structure. In practice, this kind of very loose coupling is realised with the help of a ~DOM-like notation based on a small selection of primitive base types, plus an ~object-like //record// made from such base elements. Based on these elements represented as [[generic nodes|GenNode]], we can build up a symbolic representation of shared structures, which we term the ExternalTreeDescription. In fact, this is not mean and not used as actual implementation data structure -- rather it is used to derive and validate the diff messages handled within our [[diff framework|TreeDiffModel]].
+
+//But --// if this symbolic representation is not meant for implementation -- how are we then able to relate it in any useful way to actual implementation data structures? The answer is two fold. For one, and most importantly, we do not collaborate on a shared data model, which means that the implementation data structures are always an implementation detail confined within some subsystem or even part of an subsystem. And this implementation layer can then -- secondly -- expose an adapter or intermediary, which offers a "generic side" for the diff framework to attach to. This adapter is the TreeMutator.
+
+!Definition
+;interface
+:the tree mutator is an interface providing a set of virtual functions, the ''mutation primitives''
+;adapter
+:the implementation of this interface acts as adapter, to translate ''verbs of the diff language'' into invocations on opaque, private data structures
+;binding
+:this adapter is //created// by binding those opaque, private data structures into some generic implementation patterns for the TreeMutator
+;builder interface
+:the TreeMutator offers a builder interface to build up those bindings, with the help of closures provided by the client, which is the private, opaque data structure
+
+So, from the usage side, some kind of implementation data structure will build a TreeMutator and tie itself into its binding Then, by exposing this {{{TreeMutator}}} implementation, this client data structure gets the ability to receive diff messages, which means this local and undisclosed data structure can be attached to and  collaborate with some other subsystem; it can be altered, extended and reshaped remotely, without the need to share implementation details.
+
+Incidentally, the ''diff language'' itself is meant to be readable and expressive. On the //sending side,// typically diff messages will be constructed direcly in code. To this end, the GenNode offers a constructor and mutator syntax specifically crafted to allow writing clear and compact diff messages. Since the tree diff language embedds a simple list diff language as a subset, it is possible to generate structural changes by observing changes on data collections. Such //detected diffs// may be embedded within explicitly written diff message sequences.
+
+The cannonical example are changes to the editing session. After maybe running some resolution steps, an actual effective change is determined within the session. At this point, a minimal diff message to describe this effective change will be created. This diff message can be logged, to make the change persistent. And then this message will be "cast towards the UI". There is a communication structure, the UI-Bus, which allows to "cast" such a message towards an element only known and designated by its ID. In fact, this receiver element will be a widget within the UI, and this widget exposes a custom configured TreeMutator to consume this message and effect the corresponding changes within the widget structure of the UI.
+
+
+
The TreeMutator is an intermediary to translate a generic structure pattern into heterogeneous local invocation sequences.
 
 !Motivation
@@ -8244,13 +8274,26 @@ So this looks similar, but indeed now we create //operation bindings// up front,
 
 This construction pattern can be extended to offer several optional extension hooks for the clients to supply. Extended even by offering more generic hooks to deal with recursive changes to whole sub-trees or collections of children of a specific type. Facing towards the diff application, the generated TreeMutator will expose a standardised interface to support implementing all the diff verbs necessary to describe structural and data changes. Operations, attributes and properties not outfitted by the client with actual bindings will be supplemented as ~NOP-implementation, silently ignoring any changes targeted towards the corresponding structures. This is the remaining loophole: if a client "forgets" to install a binding for some part of the structure, any changes directed towards this part will pass by unnoticed.
 
-!!!practical problems {{red{to be solved 5/2015}}}
-* still not sure how to design the generic data elements representing "Objects" / "records" → mostly settled by now
+!!!practical problems
+//posed as of 5/2015...//
+* still not sure how to design the generic data elements representing "Objects" / "records"
 * how to translate the {{{add}}} operation of tree diff into a native invocation
-* how to integate the recursive invocation properly
+* how to integrate the recursive invocation properly
 * how to deal with collections of children
 * how to integrate typed children
 
+→ largely, these problems are settled {{red{as of 3/2013}}}
+;objects
+:...are repesented within the fixed structures of the [[ETD|ExternalTreeDescription]], that is as combination of [[generic node elements|GenNode]]
+;binding
+:...between generic diff operations and native invocations happens with the help of pattern like building blocks, which are layered on top of the {{{TreeMutator}}} interface
+;recursive tree mutation
+:...means to build a //sub-//mutator for some part of the opaque, private data structure -- which in turn means to build a {{{TreeMutator}}} subclass into a provided buffer, as polymorphic value
+;collections of children
+:...are just one (actually the most important) building pattern, and we provide a template to handle ~STL-collections of children
+;typed children
+:...are integrated into this onion like layering of building blocks with the help of a //selector// to decide which building block is responsible for some concrete sub structure
+
 !!!working with children
 Handling tree structured object data imposes some additional constraints, in comparision to generic changes done to a flat list. One notable difference is that there are pre-existing //attributes,// which can not be added and deleted, are known by-name, not by positional order. Another point worth noting is the fact that child objects may be segregated into several collections by type. Since our goal is to provide an intermediary with the ability to map to arbitrary structures, we need to define the primitive operations necessary for implementing the concrete structural operations represented in the form of a diff
 * add a child
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 8408b3351..e371f2e40 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -1872,8 +1872,164 @@
 
 
 
-
-
+
+
+
+
+
+
+
+
+
+  
+    
+  
+  
+    

+ streng genommen ist es nur erlaubt, das ID-Symbol auszuwerten +

+ + +
+ + + + + + + + + + + + + + +

+ Visitor bedeutet zwei Indirektionen +

+ + +
+ + + + + +

+ ...und das ist nicht akzeptabel für ein reines Selektor-Prädikat! +

+ + +
+
+ + + + + + + + + + + +

+ denkbar nur bei Sub-Objekten +

+ + +
+
+ + + + + + + + +

+ gilt für alle praktischen Anwendungen +

+ + +
+
+ + + + + + +

+ ....auch wenn man zehnmal meinen könnte, +

+

+ Kinder eines reinen Wert-Typs wären sinnvoll -- +

+

+ sie sind es nicht! +

+

+ Jede sinnvolle Entität hat mehr als ein Attribut! +

+

+ denn es macht keinen Sinn, Entitäten und reine Wert-Elemente +

+

+ auf der gleichen Ebene in der gleichen Sammlung zu mischen. +

+

+ +

+

+ D.h., entweder man hat ein Objekt, das als Kinder z.B. eine Liste von Strings hat, +

+

+ oder man hat eine Entität, die z.b. zwei getypte Objekt-Kinder-Sammlungen hat, +

+

+ wie z.B: eine Spur mit Labels und Clips +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1993,8 +2149,7 @@ ⟹ immer Mitwirkung des Elements

- - +