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
This commit is contained in:
Fischlurch 2016-03-16 04:49:29 +01:00
parent 6404106f1a
commit 67054aa06c
2 changed files with 206 additions and 8 deletions

View file

@ -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.
</pre>
</div>
<div title="TreeMutator" creator="Ichthyostega" modifier="Ichthyostega" created="201503292115" modified="201602182152" tags="Model Concepts GuiPattern design draft" changecount="55">
<div title="TreeMutator" creator="Ichthyostega" modifier="Ichthyostega" created="201503292115" modified="201603160345" tags="Model Concepts GuiPattern design draft" changecount="63">
<pre>
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.
&amp;rarr; 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 &quot;generic side&quot; 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 &quot;cast towards the UI&quot;. There is a communication structure, the UI-Bus, which allows to &quot;cast&quot; 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.
</pre>
</div>
<div title="TreeMutatorEvolution" creator="Ichthyostega" modifier="Ichthyostega" created="201603160255" modified="201603160313" tags="Model Concepts design draft" changecount="5">
<pre>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 &quot;forgets&quot; 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 &quot;Objects&quot; / &quot;records&quot; &amp;rarr; mostly settled by now
!!!practical problems
//posed as of 5/2015...//
* still not sure how to design the generic data elements representing &quot;Objects&quot; / &quot;records&quot;
* 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
&amp;rarr; 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

View file

@ -1872,8 +1872,164 @@
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1456528424246" ID="ID_472044094" MODIFIED="1457742573583" STYLE="fork" TEXT="Selektor">
<linktarget COLOR="#7caed5" DESTINATION="ID_472044094" ENDARROW="Default" ENDINCLINATION="466;133;" ID="Arrow_ID_1253352795" SOURCE="ID_1406395599" STARTARROW="None" STARTINCLINATION="681;0;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1457741609884" ID="ID_1827838196" MODIFIED="1457741617108" TEXT="bin ich zust&#xe4;ndig?"/>
<node CREATED="1457741617655" ID="ID_1664250793" MODIFIED="1457741623179" TEXT="was ist ein &quot;match&quot;?"/>
<node CREATED="1457741609884" ID="ID_1827838196" MODIFIED="1457741617108" TEXT="bin ich zust&#xe4;ndig?">
<node CREATED="1458094312266" ID="ID_233521483" MODIFIED="1458094316157" TEXT="isApplicable"/>
<node CREATED="1458094316697" ID="ID_839136400" MODIFIED="1458094326204" TEXT="Festlegung:">
<node CREATED="1458094327095" ID="ID_306307671" MODIFIED="1458094334354" TEXT="nur auf Basis der spec"/>
<node CREATED="1458094334991" ID="ID_903070750" MODIFIED="1458094343401" TEXT="ohne Daten-Introspektion"/>
</node>
<node CREATED="1458094507048" ID="ID_1012976053" MODIFIED="1458094509755" TEXT="Problem">
<node CREATED="1458094510463" ID="ID_812427058" MODIFIED="1458094548146" TEXT="Spec bietet wenig Anhaltspunkte">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
streng genommen ist es nur erlaubt, das ID-Symbol auszuwerten
</p>
</body>
</html>
</richcontent>
<node CREATED="1458094562800" ID="ID_184244927" MODIFIED="1458094568467" TEXT="ID-Symbol"/>
<node CREATED="1458094569128" ID="ID_743935773" MODIFIED="1458094579369" TEXT="attribute / child"/>
</node>
<node CREATED="1458094599835" HGAP="24" ID="ID_1161622136" MODIFIED="1458095474973" TEXT="Zugang zum Payload-Typ" VSHIFT="10">
<icon BUILTIN="help"/>
<node CREATED="1458094616417" ID="ID_1013344827" MODIFIED="1458094632012" TEXT="Introspection / Switch-on-Type">
<icon BUILTIN="stop-sign"/>
</node>
<node CREATED="1458094634167" ID="ID_1794163270" MODIFIED="1458094672710">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Visitor bedeutet <b>zwei</b>&#160;Indirektionen
</p>
</body>
</html>
</richcontent>
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...und das ist nicht akzeptabel f&#252;r ein reines Selektor-Pr&#228;dikat!
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1458094716364" ID="ID_1749838430" MODIFIED="1458094731150" TEXT="eingeschr&#xe4;nkt auf Objekt-Typ">
<icon BUILTIN="help"/>
<node CREATED="1458094735673" ID="ID_1089998465" MODIFIED="1458094743492" TEXT="Semantischer Typ"/>
<node CREATED="1458094743960" ID="ID_1642238646" MODIFIED="1458094767704" TEXT="vs. Typisierung in der Sprache"/>
<node CREATED="1458094769365" ID="ID_855557799" MODIFIED="1458094773848" TEXT="pattern match"/>
<node CREATED="1458094823973" ID="ID_726480550" MODIFIED="1458094841971">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
denkbar nur bei Sub-<i>Objekten</i>
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1458094850490" ID="ID_39407126" MODIFIED="1458094856797" TEXT="d.h. bei Record-Daten"/>
<node CREATED="1458094864424" ID="ID_746601299" MODIFIED="1458094872787" TEXT="Record hat ein (semantisches) Typfeld"/>
<node CREATED="1458094922024" ID="ID_1616971769" MODIFIED="1458094954604">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
gilt f&#252;r <i>alle</i>&#160;praktischen Anwendungen
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1458094956636" ID="ID_1820565901" MODIFIED="1458095165033" TEXT="denn nur Objekt-Kinder machen Sinn">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
....auch wenn man zehnmal meinen k&#246;nnte,
</p>
<p>
Kinder eines reinen Wert-Typs w&#228;ren sinnvoll --
</p>
<p>
sie sind es nicht!
</p>
<p>
Jede sinnvolle <i>Entit&#228;t</i>&#160;hat mehr als ein Attribut<i>! </i>
</p>
<p>
denn es macht keinen Sinn, Entit&#228;ten und reine Wert-Elemente
</p>
<p>
auf der gleichen Ebene in der gleichen Sammlung zu mischen.
</p>
<p>
</p>
<p>
D.h., entweder man hat ein Objekt, das als Kinder z.B. eine Liste von Strings hat,
</p>
<p>
oder man hat eine Entit&#228;t, die z.b. zwei getypte Objekt-Kinder-Sammlungen hat,
</p>
<p>
wie z.B: eine Spur mit Labels und Clips
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1458095217737" ID="ID_824115387" MODIFIED="1458095461060" TEXT="um das zu unterst&#xfc;tzen...">
<icon BUILTIN="idea"/>
<node CREATED="1458095230175" ID="ID_995706334" MODIFIED="1458095239258" TEXT="m&#xfc;&#xdf;te DataCap helfen"/>
<node CREATED="1458095367701" ID="ID_1549321280" MODIFIED="1458095376400" TEXT="es g&#xe4;be dann einen Bottom-Wert"/>
<node CREATED="1458095240158" ID="ID_1884817792" MODIFIED="1458095284084" TEXT="Introspektions-Verbot etwas aufgeweicht"/>
<node CREATED="1458095304886" ID="ID_395248655" MODIFIED="1458095318800" TEXT="dieser Gebrauch ist aber mit dem Objekt-Typfeld schon angelegt"/>
<node CREATED="1458095320692" ID="ID_1203007776" MODIFIED="1458095332942" TEXT="die Bedeutung wird vom Client privat definiert"/>
<node CREATED="1458095409800" ID="ID_227738227" MODIFIED="1458095442503" TEXT="ebenso wird aber auch die Bedeutung der ETD lokal definiert"/>
<node CREATED="1458095443115" ID="ID_586715428" MODIFIED="1458095455459" TEXT="erscheint mir plausibel und vertretbar">
<icon BUILTIN="yes"/>
</node>
</node>
</node>
</node>
</node>
<node CREATED="1458095528224" ID="ID_109058224" MODIFIED="1458095539458" TEXT="falls nein...">
<node CREATED="1458095540807" ID="ID_225712554" MODIFIED="1458095553929" TEXT="&#xfc;bernimmt der n&#xe4;chste Onion-Layer"/>
<node CREATED="1458095554548" ID="ID_1745271000" MODIFIED="1458095566303" TEXT="scheitert am Ende die Diff-Anwendung"/>
<node CREATED="1458095567123" ID="ID_1135449086" MODIFIED="1458095593246" TEXT="das kann nicht sein">
<icon BUILTIN="ksmiletris"/>
<node CREATED="1458095599015" ID="ID_1548761670" MODIFIED="1458095611129" TEXT="denn Struktur wird per Diff aufgebaut"/>
<node CREATED="1458095611645" ID="ID_1917053068" MODIFIED="1458095623023" TEXT="und Diff wird von einer konsistenten Struktur generiert"/>
<node CREATED="1458095623563" ID="ID_1563236319" MODIFIED="1458095636789" TEXT="wenngleich es sich auch um eine funktionale Struktur handeln kann..."/>
<node CREATED="1458095660150" ID="ID_329824783" MODIFIED="1458095668777" TEXT="wir sind nicht tolerant bei der Diff-Anwendung"/>
<node CREATED="1458095669437" ID="ID_650500191" MODIFIED="1458095672801" TEXT="und das ist gut so."/>
</node>
</node>
</node>
<node CREATED="1457741617655" ID="ID_1664250793" MODIFIED="1457741623179" TEXT="was ist ein &quot;match&quot;?">
<node CREATED="1458094392679" ID="ID_238187527" MODIFIED="1458094396098" TEXT="matches"/>
<node CREATED="1458094428506" ID="ID_1753032814" MODIFIED="1458094435693" TEXT="darf Annahmen &#xfc;ber den Typ der Spec machen"/>
<node CREATED="1458094397350" ID="ID_1185807177" MODIFIED="1458094427326" TEXT="darf in die Payload der Spec schauen"/>
<node CREATED="1458094437249" ID="ID_1125952135" MODIFIED="1458094463529" TEXT="darf Methoden des Datenobjekts aufrufen"/>
</node>
</node>
<node CREATED="1457038643034" ID="ID_1057400532" MODIFIED="1457038646822" TEXT="abstrakte Position"/>
<node CREATED="1457038527402" HGAP="16" ID="ID_1909805079" MODIFIED="1457038617372" TEXT="Mutations-Primitive" VSHIFT="7">
@ -1993,8 +2149,7 @@
&#10233; <i>immer</i>&#160;Mitwirkung des Elements
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1457742547067" HGAP="33" ID="ID_410938096" MODIFIED="1457742727257" TEXT="Selector explizit bauen" VSHIFT="7">