< PreviousChapter 6: Solution170 lastname orgUnit { name } } }`, { id: id }).then((data) => { let name = `${data.user.firstname} ${data.user.lastname}` cs(this, “model”).value(“dataName”, name) cs(this, “model”).value(“dataOrg”, data.user.orgUnit.name) }) The pro of this approach is that it combines the flexibility of arbitrary data extrac-tion and traversal with a convenient inline approach. The con of this approach is that there is no clean Separation of Concern from a puristic architecture point of view.For a Data Binding which updates the Presentation Model not just once, but whenever the Business Model changes, the one-time Promise (then) has to be fur-ther replaced with a multi-time Subscription (subscribe): /* foo.ctrl.js */ graphql(`query ($id: ID) { [...] }`, { id: id }).subscribe((data) => { [...] })6.10.5 Model Read/Write Operations and Binding UpdatesSimilar to the “Model Read/Write Operations and Binding Updates” on page 168, for the Data Binding mechanism to work, the same three aspects have to be taken into account here, too: ■Track Read and Write Operations: read and write operations to both the Presentation Model and Business Model have to be tracked on the basis of Presentation Model fields and Business Model entities and fields. For this, the Presentation Model and Business Model usually support the Observer pattern [Gamma et al. 1994]. ■Match Write and Read Operations: for each write operation, all related read operations are checked. If a write and read operation pair overlap in their Presentation Model field or Business Model entity and fields, the write op-eration is considered to outdate the read operation. ■Trigger Repetition of Read Operations: for each outdated read operation, the operation is repeated to transfer the underlying (new) value. From the (non-authoritative) Presentation Model to the (authoritative) Business Model, a Controller Component is usually notified and then semi-automat-ically handles the transfer and potentially occurring conflicts. From the Data Binding of Business Model171(authoritative) Business Model to the (non-authoritative) Presentation Model, a framework is usually used to fully automatically handle the (con-flict-free considered) transfer.The important aspect is how the underlying Data Binding mechanism knows in particular when to re-fetch the information from the Back End and then re-call the subscribe callback in the Front End. For this, the Back End tracks all its read and write operations on its Business Model and for each write operation it has to check whether it potentially out-dates the result set of any previously subscribed read operations. An operation can be encoded with the following small Domain-Specific Language (DSL):access ::= (source “->”)? operation “->” destination source ::= type:id “#” instance:uuid “.” attribute:id operation ::= action “(“ arity “)” action ::= “create” / “read” / “update” / “delete” arity ::= “one” / “many” / “all” destination ::= type:id “#” “{“ (instance:uuid (“,” instance:uuid)*)? “}” “.” “{“ attribute:id (“,” attribute:id)* “}” id ::= /^[a-zA-Z_][a-zA-Z0-9_]*$/ uuid ::= /^[\da-f]{8}-(?:[\da-f]{4}-){3}[\da-f]{12}$/Then, whenever a write operation occurs, the following three distinct cases are checked in the Back End to detect whether the Front End has to be notified to re-fetch the corresponding read operation. ■Case 1: modified entity (of arbitrary direct access): the read operation like read(*)->Item#{1}.{id,name} is outdated by a write operation like up-date/delete(*)->Item#{1}.{name}. ■Case 2: modified entity list (of direct query): the read operation like read(many/all)->Item#{*}.{id,name} is outdated by a write operation like create/update/delete(*)->Item#{*}.{name}. ■Case 3: modified entity list (of relationship traversal): the read operation like Card#1.items->read(*)->Item#{2}.{id,name} is outdated by a write operation like update(*)->Card#{1}.{items}.The updating/mutating of the authoritative Busi-ness Model is a sensitive aspect and in practice cannot be done fully au-tomatically by a frame-work.Chapter 6: Solution172CVVMMMCCVMCVMVMCVMCVMCVFigure 6.29: Component Pattern: Reusable Widget: V-MCVVMMMCCVMCVMVMCVMCVMCVFigure 6.28: Component Pattern: Alternative View: (V+V)-MComponent Tree Structure Patterns1736.11 Component Tree Structure PatternsPay attention to the intricate patterns of your existence that you take for granted. — Doug DillonEven if the Model-View-Controller/Component-Tree (MVC/CT) pattern (see Subsec-tion 6.8.5 on page 156) by definition consists of three Components of role View, Model, and Controller, this structure pattern can occur in some variants in practice. Each variant has a certain purpose and has a distinct name.6.11.1 Alternative View: (V+V)-MSometimes an alternative View Component is required, which creates a so-called Alternative View sub-pattern of MVC/CT (see Figure 6.28 on page 172).For instance, to provide both a desktop and mobile variant of a View Mask, in case the CSS-based Responsive Design approach is not sufficient, two (or more) al-ternative View Components can be used. All those View Components use the same shared Model Component and hence show more or less exactly the same informa-tion, just in different ways. Another classical example is an Excel-style UI where the same information is displayed twice side-by-side: once in a textual form and once in a graphical form.A Standalone Controller (see Subsection 6.11.3 on page 175) then usually de-cides which single View Component actually ato ctivate during run time. The num-ber of alternative View Components actually can be arbitrary, although in practice one usually sees just two or three of them.6.11.2 Reusable Widget: V-MAs only the Controller Components have a contextual view of the Component Tree and perform specific provisioning and actioning (compare MVC/CT in Subsection 6.8.5 on page 156), true reusable Widgets can be formed out of MVC/CT by split-ting it into a Reusable Widget sub-pattern (see Figure 6.29 on page 172) and leave the orchestrating Controller Component separately. A Reusa-ble Widget pattern usually is used for generic User Interface Fragments whose multiple instances differ just by their values in the Model Compo-nent.For instance, to implement a reusable List UI Fragment, the Reusable Widget pattern should be used. The difference between all List UI Fragments are just the Controller-provisioned labels of the List items, while the View Mask structure and Presentation Model is kept the same.CoReusable Widget is the most prominent struc-ture sub-pattern of the MVC/CT pattern.Chapter 6: Solution174As reusability of UI Fragments is one of the primary objectives of the Hierar-chical Dialog Composition (see Section 6.7 on page 147), the Reusable Widget pattern is one of the most important patterns and should be explicitly strived for. CVVMMMCCVMCVMVMCVMCVMCVFigure 6.31: Component Pattern: Headless Pair: M-CCVVMMMCCVMCVMVMCVMCVMCVFigure 6.30: Component Patttern: Standalone Controller: CComponent Tree Structure Patterns1756.11.3 Standalone Controller: CIn case of a Reusable Widget or other plain orchestration scenarios, a Standalone Controller sub-pattern is used where MVC/CT collapses to just a single Controller Component (see Figure 6.30 on page 174).For instance, in the List UI Fragment scenario, the Standalone Controller provi-sions the List item labels and performs the actions upon interaction with the List items.Beside the Reusable Widget scenario, the root Component of a Component Tree often is also a Standalone Controller. However, a leaf Component of a Compo-nent Tree never is a Standalone Controller, because it has no purpose to provision nothing and perform an action on nothing. 6.11.4 Headless Pair: M-CIn case a Controller Component is combined with a Model Component in order to be a shared information and orchestration hub for a group of (usually Full Tri-ad based) User Interface Fragments, the MVC/CT pattern collapses to a so-called Headless Pair sub-pattern (see Figure 6.31 on page 174).This sub-pattern usually occurs just in the middle of Component Trees and al-ways has two or more sub-trees or it would serve no purpose. A typical example is a “wizard” User Interface Dialog. Here multiple strongly related User Interface Frag-ments have to be orchestrated, and all share a certain amount of information.Figure 6.32: Component Pattern: Full Triad: V-M-CCVVMMMCCVMCVMVMCVMCVMCVChapter 6: Solution1766.11.5 Full Triad: V-M-CFinally, in case the MVC/CT pattern is used with View, Model and Con-troller Components in their regular usage, the resulting pattern in the Component Tree more specifically is called a Full Triad sub-pattern (see Figure 6.32 on page 175).This is the default Component Tree Structure Pattern. An entire application could be designed in a consistent and fully consequent way entirely out of just Full Triads, although it is strongly advised to also leverage from the other MVC/CT sub-patterns to reduce the amount of necessary boilerplate code and to avoid useless “flow-type heater” Components in the Component Tree, which do nothing more than simply transfer data.6.12 Component Tree Behavior PatternsYou must reward the kind of behavior that you want. — James MattisDriving the Model-View-Controller/Component-Tree (MVC/CT) pattern on a Com-ponent Tree results not just in a certain structure, but also certain behaviors regu-larly occur. Each distinct behavior is treated as a pattern with a certain name.6.12.1 Controller-Created DescendantsAccording to the Component Knowledge (see Subsection 6.8.3 on page 152), there is a Black-Box view of the Controller Component onto its Model and View Components. When instantiating MVC/CT Full Triad into the Component Tree, the Separation of Concerns architecture principle mandates that the ancestor Components should only create the Controller Component instance of the Full Triad. And this Controller Component then in turn and autono-mously creates the Model Component and View Component instances. Otherwise, the ancestor Component would need to have an understanding of the particular MVC/CT structure (sub-)pattern.In other words: only Controller Components should be allowed to create other descendant Components in the Component Tree, and this way form the Controller-Created Descendants behavior pattern.6.12.2 Interaction Event ValuesAs a consequence of the strict layout of the Model-View-Controller/Component-Tree (MVC/CT) pattern, it is not allowed that View Components directly perform Consequently, using just Full Triads only will lead to unnecessary boiler-plate code.The Controller Compo-nents also control the dy-namic Component Tree creation.Component Tree Behavior Patterns177any actioning towards the Service tier in case of interaction events in the View Mask.Instead, the View Component has to just transform interaction events into event values in the Model Component. The Controller Component then has to per-form the actioning towards the Service tier. This two-step process forms the Inter-action Event Values behavior pattern.6.12.3 Presentation State LogicPresentation state is represented by State Values in the Model Component (com-pare Subsection 6.8.8 on page 158). As explained in Subsection 6.8.11 on page 163, the Presentation Logic is also part of the Model Component. The Presenta-tion Logic aspect is exclusively used for calculating any State Values. This forms the Presentation State Logic behavior pattern.6.12.4 Common Ancestor CommunicationThe architecture principle Separation of Concern is central to HUICA. A Component is only allowed to communicate with other Components along the Component Tree paths and only to those it knows about.As a consequence, in order to communicate information from a source Component to a target Component in a sibling sub-tree of the Component Tree, the information has to first flow from the source Com-ponent to a common ancestor Component and then from the common The Common Ancestor Communication pattern is one of the most impor-tant in practice.VVMMCCVMCVVMMCCVMCCommon Ancestor Communicationwith Events/ServicesCommon Ancestor Communicationwith Model ValuesFigure 6.33: Component Pattern: Common Ancestor CommunicationChapter 6: Solution178ancestor Component to the target Component. This forms the Common Ancestor Communication behavior pattern.The communication itself can be performed in two distinct ways (see Figure 6.33 on page 177): First, one can use two explicit Event publishing operations or Service calls. Second, one can use a Model Value on a common ancestor Model Component. The advantage of Events and Services is that the information can be transformed between the sub-trees. The advantage of the Model Value is that it requires no extra code in the common ancestor Model Component.A classical example of Common Ancestor Communication is a Master-Detail User Interface where the user clicks onto a list item in the Master UI Fragment, and this should result in an update of the list item’s details in the Detail UI Fragment.6.12.5 Own Descendant CommunicationThe architecture principle Separation of Concern is central to HUICA. A Component is only allowed to communicate with other Components along the Component Tree paths and only to those it knows about.As a consequence, in order to communicate information from a source Com-ponent to one or more target Components in the same sub-tree of the Component Tree, the information has to be delivered without actually knowing the particular target Components. For this, an Event can be spread into the sub-tree. This forms the Own Descendant Communication behavior pattern.A classical example of Own Descendant Communication is a Dialog with many UI Fragments where the user clicks on a “Reset” button. This then leads to a “re-set” event spread onto all Components in the same sub-tree and let the individual Components decide how to reset themselves. An alternative would be to use a “Reset” Command Value in a descendant Model component. Both approaches are compliant to the Own Descendant Communication behavior pattern, as the source and target Components do not have to know each other and the communication is along the Component Tree path only.User Interface Run-Time Monitoring1796.13 User Interface Run-Time MonitoringWe leave traces of ourselves wherever we go, on whatever we touch. — Lewis ThomasDuring run time of a HUICA based application, the Components in the Component Tree are dynamically created, transitioned in state and destroyed. Two aspects are of interest here: the real-time visualization of the Component Tree for development purposes and the tracing of Component communication for architecture purposes.6.13.1 Real-Time Component Tree VisualizationAs explained in Subsection 6.4.2 on page 123 about the Component Tree, there are two ways of visualizing the Component Tree: drawing it in the “natural” direc-tion with the root at the bottom and drawing it in the “classical” Computer Science direction with the root at the top. Both visualizations should be provided by the Component System during run time.For a ComponentJS-based sample application Architecture Fundamentals (see Figure 6.34 on page 179) the resulting run-time Component Tree visualizations you can see in Figure 6.35 on page 180 and Figure 6.36 on page 180.Figure 6.34: Sample Application “Architecture Fundamentals”Next >