ViewSpec: analysis of design alternatives

looks like I'm trapped with the choice between a convoluted API design
and an braindead and inefficient implementation. I am leaning towards the latter
This commit is contained in:
Fischlurch 2018-06-15 01:51:10 +02:00
parent f55a8f606b
commit 2e8bc9227a
3 changed files with 140 additions and 31 deletions

View file

@ -96,16 +96,15 @@ namespace model {
virtual ~ElementAccess () { } ///< this is an interface
template<class TAR>
using Result = lib::Result<TAR>;
/* == Access by Location == */
template<class TAR>
Result<TAR&> access (UICoord const& destination);
lib::Result<TAR&> access (UICoord const& destination);
template<class TAR>
Result<TAR&> access_or_create (UICoord const& destination, size_t limitCreation = LUMIERA_MAX_ORDINAL_NUMBER);
lib::Result<TAR&> access_or_create (UICoord const& destination, size_t limitCreation = LUMIERA_MAX_ORDINAL_NUMBER);
UICoord allocate (UICoord const& destination, size_t limitCreation = LUMIERA_MAX_ORDINAL_NUMBER);
protected:
@ -142,7 +141,7 @@ namespace model {
struct ElementAccess::TypeConverter
: RawResult::Visitor
{
Result<TAR&> result{"not convertible"};
lib::Result<TAR&> result{"not convertible"};
template<typename X> // note the "backward" use. We pick that base interface
using canUpcast = std::is_convertible<TAR*, X>; // into which our desired result type can be upcast, because
@ -155,7 +154,7 @@ namespace model {
if (pb)
result = *dynamic_cast<TAR*> (pb);
else
result = Result<TAR&>{"access returns empty answer"};
result = lib::Result<TAR&>{"access returns empty answer"};
}
};
@ -173,7 +172,7 @@ namespace model {
* and convertible to `bool(false)`
*/
template<class TAR>
inline ElementAccess::Result<TAR&>
inline lib::Result<TAR&>
ElementAccess::access (UICoord const& destination)
{
return access_or_create<TAR> (destination, 0);
@ -188,7 +187,7 @@ namespace model {
* and convertible to `bool(false)` (or raises an exception on attempted access)
*/
template<class TAR>
inline ElementAccess::Result<TAR&>
inline lib::Result<TAR&>
ElementAccess::access_or_create (UICoord const& destination, size_t limitCreation)
{
TypeConverter<TAR> converter;

View file

@ -9917,7 +9917,7 @@ In addition to querying the interpretation of a given coordinate spec with respe
__Navigation mutations:__ //In theory,// it would even be possible to extend the path by creating suitable child components; but actually this would require all &quot;elements&quot; to implement a suitable mutation interface -- which in the case of //generic elements// might be far beyond the common ground. For this reason, we keep mutation of the backing environment outside of a path mutator's scope and rather keep mutation limited to the path itself.
</pre>
</div>
<div title="UILowLevelAccess" creator="Ichthyostega" modifier="Ichthyostega" created="201804062255" modified="201804150051" tags="spec draft GuiPattern" changecount="4">
<div title="UILowLevelAccess" creator="Ichthyostega" modifier="Ichthyostega" created="201804062255" modified="201806142339" tags="spec draft GuiPattern" changecount="7">
<pre>//Cross cutting access to elementary UI structures.//
We have several orthogonal identification and access schemes within the UI. A naively written UI application just attaches the core logic below some widgets and controllers -- not only does this lead to a hard to maintain code base, this approach is even outright impossible in our case, due to the strict decoupling between core and GUI, which places us into the situation to connect a self contained core with a self contained UI. This is a binding, which, as a sideline, also generates a control structure of its own. We can indeed write code dealing with a generic UI element -- but there needs to be some place where this kind of generic designation is translated into internal structures of the UI toolkit (GTK in our case), to obtain a direct (language) reference to some implementation widget finally.
@ -9930,6 +9930,9 @@ At the time of this writing, it is not really clear if we need such a facility a
* so effectively an access request will drill down the real UI topology, following the path of the given UI Coordinates.
* the result can then be packaged into a {{{lib::Variant}}} and use a //variant visitor// (double dispatch) to invoke the apropriate {{{dynamic_cast}}}
* together, this mechanism allows us to return direct language references to actual implementation widgets
!Extend UICoord to an opaque concrete {{{UILocation}}} handle?
This is a possible different turn in the design, considered as an option {{red{as of 6/2018}}}. Such would complement a symbolic coordinate specification with an opaque handle pointing to an actually existing UI widget. Access to this widget requires knowledge about its actual type -- basically a variant record tacked onto the UICoord representation, packaged into a subclass of the latter. The obvious benefit would be to avoid drilling down into the UI widget tree repeatedly, since there is now a way to pass along hidden //insider information// regarding actual UI elements. However, such a design bears a &quot;smell&quot; of being implementation driven, and undercuts the whole idea of a entirely symbolic layer of location specifications. Building such an extension can be considered sensible only under the additional assumption that this kind of //location token// is to be passed over various interfaces and indeed becomes a generic token of exchange and interaction within the UI layer implementation -- which, right now is not a given.
</pre>
</div>
<div title="ViewConnection" modifier="Ichthyostega" created="201105221854" modified="201501091154" tags="def Model SessionLogic" changecount="3">

View file

@ -11474,36 +11474,19 @@
<node CREATED="1525567420608" ID="ID_1865194597" MODIFIED="1525567450407" TEXT="erscheint sinnvoll vom API her">
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1525567432127" ID="ID_1190994966" MODIFIED="1525567453224" TEXT="aber d&#xe4;mlich von der Implementierung her">
<node CREATED="1525567432127" ID="ID_1190994966" MODIFIED="1528992332480" TEXT="aber d&#xe4;mlich in der Implementierung">
<icon BUILTIN="smily_bad"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1525567474513" HGAP="136" ID="ID_492657286" MODIFIED="1528988453047" TEXT="ElementAccess-API umbauen" VSHIFT="5">
<icon BUILTIN="pencil"/>
<node CREATED="1529016810234" ID="ID_190701762" MODIFIED="1529016835751" TEXT="M&#xf6;glichkeiten">
<node CREATED="1528988155980" ID="ID_425314989" MODIFIED="1528988170052" TEXT="Variante-1">
<icon BUILTIN="full-1"/>
<node CREATED="1528988234950" ID="ID_1668042554" MODIFIED="1528988252512" TEXT="UI-Coord zur&#xfc;ckliefern"/>
<node CREATED="1528988289119" ID="ID_1881432398" MODIFIED="1528988440865" TEXT="tricky conversion">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...wenn ich es irgendwie schaffe,
</p>
<p>
doch auch noch UI-Coord als R&#252;ckgabewert
</p>
<p>
da &quot;hineinzuw&#252;rgen&quot;...
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1528988263818" ID="ID_480404928" MODIFIED="1528988286380" TEXT="Element-Cache"/>
<node CREATED="1528988263818" ID="ID_480404928" MODIFIED="1529016940289" TEXT="Element-Cache?"/>
<node CREATED="1529016904083" ID="ID_1517114370" MODIFIED="1529016934839" TEXT="API erweitern"/>
</node>
<node CREATED="1528988317699" ID="ID_1560503454" MODIFIED="1528988323954" TEXT="Variante-2 ">
<icon BUILTIN="full-2"/>
@ -11512,6 +11495,130 @@
<node CREATED="1528988379946" ID="ID_131306130" MODIFIED="1528988391702" TEXT="brauche anderweitige Abstraktion"/>
<node CREATED="1528988369596" ID="ID_1174830872" MODIFIED="1528988376583" TEXT="Allokator erzeugt anderweitig"/>
</node>
<node CREATED="1529016988678" ID="ID_1209500762" MODIFIED="1529016994968" TEXT="Variante-3">
<icon BUILTIN="full-3"/>
<node CREATED="1529017028938" ID="ID_359770283" MODIFIED="1529017068647" TEXT="Opaque Location Representation"/>
<node CREATED="1529017070019" ID="ID_57519695" MODIFIED="1529017101538" TEXT="Allocator-API darauf umstellen"/>
<node CREATED="1529017279135" ID="ID_707219104" MODIFIED="1529017285322" TEXT="(down)cast-Mechanismus"/>
</node>
<node CREATED="1529018080237" ID="ID_776753961" MODIFIED="1529018319679" TEXT="Variante-3b">
<icon BUILTIN="full-4"/>
<node CREATED="1529018093267" ID="ID_389715312" MODIFIED="1529018099078" TEXT="Hybrid-L&#xf6;sung"/>
<node CREATED="1529018100234" ID="ID_1628139323" MODIFIED="1529018119792">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
als <i>Subklasse</i>&#160;von UICoord
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1529018125015" ID="ID_740978949" MODIFIED="1529018137465" TEXT="f&#xfc;gt den Variant-Record und den Konverter hinzu"/>
</node>
</node>
<node CREATED="1529016854248" ID="ID_1664191705" MODIFIED="1529016857972" TEXT="Abw&#xe4;gung">
<node CREATED="1529016871262" ID="ID_957194065" MODIFIED="1529017825322" TEXT="Variante-2 verschiebt das Problem">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...denn das eigentliche Problem ist,
</p>
<p>
da&#223; ich noch keinerlei Implementierung schreiben kann.
</p>
<p>
Mithin schiebe ich mir Platzhalter von der linken in die rechte Tasche
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1529017693432" ID="ID_70956393" MODIFIED="1529018209759" TEXT="Variante-3 verwendet zwei Repr&#xe4;sentationen f&#xfc;r die gleiche Sache">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
und zwar f&#252;r die abstrahierte GUI-Location
</p>
<ul>
<li>
einmal symbolisch als UI-Koordinaten
</li>
<li>
einmal opaque als eingekapselte L&#246;sung
</li>
</ul>
<p>
Und sowas ist verwirrend und verlockt gradezu, die Schachtel aufzumachen
</p>
<p>
und an der Implementierung zu kleben
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1529018409007" ID="ID_1460094266" MODIFIED="1529018714798" TEXT="Variante-3b w&#xe4;re nur interessant als eigenst&#xe4;ndige Entit&#xe4;t">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...was <i>bis jetzt</i>&#160;nicht gegeben ist!
</p>
<p>
Bis jetzt haben wir einen &quot;Durchlauf-Erhitzer&quot;: letztlich will man nur die Referenz
</p>
<p>
auf das GUI-Element haben, und die dazwischenliegende symbolische Schicht
</p>
<p>
dient nur der Konfiguration und L&#246;sungs-Suche.
</p>
<p>
</p>
<p>
Wenn allerdings sp&#228;ter mal diese <b>UILocation</b>&#160;== bereits decodierte UI-Koordinaten
</p>
<p>
ein eigenst&#228;ndiges Token wird, welches &#252;ber mehrere Schnittstellen hinweg geschoben wird,
</p>
<p>
<i>dann und nur dann</i>&#160;w&#252;rde die zus&#228;tzliche API-Komplexit&#228;t Sinn machen.
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1529019621707" ID="ID_537306231" MODIFIED="1529019680878" STYLE="fork" TEXT="Beschlu&#xdf;">
<font NAME="SansSerif" SIZE="12"/>
<node CREATED="1529019899294" ID="ID_514740736" MODIFIED="1529019930053" TEXT="Variante-3b wird als Option f&#xfc;r sp&#xe4;ter festgehalten"/>
<node CREATED="1529019931210" ID="ID_963819454" MODIFIED="1529019961969" TEXT="Variante-1 mit API-Erweiterung ist naheliegend"/>
<node CREATED="1529019962989" ID="ID_1964052993" MODIFIED="1529019985410">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
die <b>verfickte</b>&#160;Performance wird ignoriert
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1523752571241" ID="ID_1806352950" MODIFIED="1523752593134" TEXT="Anzahl Instanzen herausfinden">