DEV Community

Unpublished Post. This URL is public but secret, so share at your own discretion.
Cover image for Basic Vue/Omb Component Composition Comparison

Basic Vue/Omb Component Composition Comparison

Article: Basic Omb/Vue Component Composition Comparison


Note: Omb is experimental. What things are called and wow code is structured will change.

I use a sample of vue code as a starting point. It shows creating a component and reuse of it in another component. I then show how the corresponding functionality is coded in Omb, that uses a organ=mind+body structure. I also discusses some properties, implications and possibilities of the Lib Omb solution.

Sample Code

Vue Sample Code

// based on https://vuejs.org/v2/guide/components.html
  Vue.component('button-counter', {
    data: // reactive data 
      function () {
        return {
          count: 0
        }
    },
    template: // template with access to the reactive data 
      '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
  }); // define new component

  new Vue({ el: '#components-demo' }) // make and mount
Enter fullscreen mode Exit fullscreen mode
<div id="components-demo"> <!-- another way of defining a new component -->
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>
Enter fullscreen mode Exit fullscreen mode
Enter fullscreen mode Exit fullscreen mode

Omb Sample Code


const BC = // ButtonCounter
  { mind:    // State Constructor
    { '_'   : 0                       // INIT
    , '>'   : Int                     // Substate
    , '!'   : { INC: ( x ) => x + 1 } // Transition 
    } // sample state: 0 | 5 | 42 
  , body:    // DOM Constructor
    ooButton
      ( 'ButtonCounter'    // Use this class for CSS layout
      , o_onclick( 'INC' ) // Bind event to transition
      )
      ( `You clicked me ${ ooShow( 'ui' ) } times` 
      )
  }
;

const TC = // ThreeCounters
  { mind: // a mind can only be composed of minds
      [ BC.mind
      , BC.mind
      , BC.mind
      ]   // Sample state: [ 0, 5, 42 ]
  , body: // a body can only be composed of bodies
      ooDiv( 'ThreeCounters' )
        ( ooSlot( 0 )( BC.body ) // The children of ooSlot will be able to look only at this branch of tha state
        , ooSlot( 1 )( BC.body )
        , ooSlot( 2 )( BC.body )
        )
  }
;

mount( TC )( '#app' ); // make and mount
Enter fullscreen mode Exit fullscreen mode

Some notes on organic composition in Lib Omb

A note on organ composition

Note how the composition is not a composition of sub-organs into a super-organ,
but in stead the sub-minds are composed into a super-mind and the sub-bodies are composed into a super-body, and then the super-organ is composed of a super-mind and a super-body.

A note on the relation between the mind and the bodies of an organ

The assumption that there is a one-to-one relationship between the data and the template of a component is not generally correct. In Lib Omb, there can be any number of bodies defined for a a mind. Imagine for example data (total state) that describes a type of product in a web-shop. This description can have a product image, or an images per product-variant, a thumbnail image, a name, a short description, a detailed description, a table of technical facts etc. Now imagine all the places in which this mind is represented by different bodies, and at different levels of concretization. In the medium overview, products are embodied as cards with image, product-name, short description, price, some buttons. In the Shopping cart it is embodied as thumbnail, product-name and price. In a panoramic view, it might appear as just the thumbnail, in a list as just the product-name etc. Also, when the user is logged in with admin right, and the product appears in an edit-product page, additional options may be available. When the same page is shown but the user log-in has expired, the product embodiment might be the usual customer-view + a log-in-to-edit link. Also, if the site supports multiple languages, an y given body might show the textual content in the appropriate language.

Thus, in real world examples it becomes very clear that a one-body-policy cannot possibly suffice. In stead, the component system can support multiple bodies depending on the context of observation.

A precise definition of "context of observation"

From a dynamic perspective, or from the viewpoint of the "mind", the logical space of any embodiment is defined solely by its linearization path, that is the sequence of key chosen under free dispatch up to a given location. Assuming a fully static web page, this location will span the whole document. Assuming, on the other hand a highly dynamic web page, the location might just span e.g. a single change of a button label, or a css class.

A note on system-supported approaches to the multi-body problem

One might imagine up a system under which the bodies can be defined either in terms of exact linearization paths or as patterns that are matched against the concrete linearization paths, and the most specific embodiment is chosen. From a validation perspective, any valid embodiment is valid, since the data it depends on is defined byt the linearization path under free dispatch. The design work can the progress from general embodiments of the minds to production level specificity. What is of importance here is to design such a system so that it guarantees that all necessary needs for specific embodiments are covered by the implementation and no missing bodies can be left to be discovered after deployment. One ide might be to decide during design exactly what different embodiments are needed and let the system enforce that such embodiments do exist.

Composition in Lib Omb

Here is the same code as above, but with more reflective comments:

    /**
     * module: ButtonCounter.js
     * -- An integer state that can be incremented and observed
     */ 
    const mind =
      { '_'   : 0          // allow atomic states, interpret `x` as [ x ]
      , '>'   : Int
      , '!'   : { INC: ( x ) => x + 1 }  
      }
    ; 
    // sample state: 0 | 5 | 42 | 271
    const body = 
      ooButton
        ( 'ButtonCounter'
        . o_onclick( 'INC' )
        ( `You clicked me ${ ooShow( 'ui' ) } times` )
      ; // just one default UI provided for ButtonCounter

    const organ = { mind, body }; // aggregate ButtonCounter organ
    export default organ;         // export ButtonCounter organ
Enter fullscreen mode Exit fullscreen mode
  /**
   * module: ThreeCounters.js
   * -- Demo of reusable organ definitions
   * -- Note how the mind is aggregated from the subminds
   * -- and the body from the subbodies
   */

  import organ as BC from './ButtonCounter.js';

  /** 
   * ThreeCounters.mind
   * Three atomic integer states are assmebled into a composit array state
   * Sample state: [ 0, 5, 42 ]
   */

  const mind = 
    [ BC.mind
    , BC.mind
    , BC.mind
    ] // array form of orthogonal states 
  ;   

  /** 
   * ThreeCounters.body
   * Three counter bodies are assembled into a juxtaposition layout
   */

  const body = 
    ooDiv( 'ThreeCounters' ) // class included for formatting purposes
      ( ooSlot( 0 )( BC.body )
      , ooSlot( 1 )( BC.body )
      , ooSlot( 2 )( BC.body )
      )
    ; // just one default UI provided for ThreeCounters

  const organ = { mind, body }; // aggregate ThreeCounters organ
  export default organ;         // export ThreeCounters organ
Enter fullscreen mode Exit fullscreen mode

A note on BEM support

This organ could be structured after BEM principles. In that case, the top level exports would be headless blocks, responsible only for their inner layouts, while the insertion places would be slot elements responsible only for their outer layout.

Violations

Interestingly, some css properties violates the separation of concerns enforced by this usage of BEM: namely display with values such as inline-grid, or inline-flex. These cannot be used by a Block. The reason is that the grid or flex parts belong solely to the Block, while the existence or omission of inline belongs solely to the corresponding Slot.

Possible solutions

The properties could be assembled from partial definitions contributed by the Slot and the Block respectively. Separation of concerns can and must be enforced by the system for compliance with lib-omb. Besides avoiding unintended and confusing layout-collisions, an important additional benefit of having the system enforce necessary constraints is that what might have been mere usage turns into learning.

Summary

We observed how a composition of components in Vue could be defined in Lib Omb. While doing that we observed some properties, constraints and possibilities of the MOB composition principles.

One of several observation was that while components front-end frameworks are represented as a tuple of one data definition and one template definition, this does not generalize beyond very simple examples. In stead, the general case is that one mind can need different embodiments in different contexts.


Document History

  • 2020-12-09 Created
  • 2020-12-09 Published at rekreanto.com
  • 2020-12-10 Rebranded from lib-mob to lib-omb
  • 2020-12-10 Rebranded from Lib Mob to Lib Omb, or just Omb

Note

Please do not copy this content. Link to this page in stead.

Discussion (0)