openscd / open-scd

A substation configuration description editor for projects using SCL IEC 61850-6 Edition 2 or greater
https://openscd.github.io
Apache License 2.0
101 stars 31 forks source link

Upload existing OpenSCD architecture documentation #1200

Open Sander3003 opened 1 year ago

Sander3003 commented 1 year ago

As a (potentail) developer I would like to know the exsisting architecure decissions So I can understand why choices are made and base my decision on these choices or challenge them.

Acceptance criteria: Upload existing documentation of @ca-d to a docs folder in this repository.

Sander3003 commented 1 year ago

General architecture can uploaded to .github

ca-d commented 1 year ago

This is the original architecture proposal (not exactly what was implemented) from summer of 2020, converted to markdown format. Please feel free to use this as you wish.

Markdown source ```md > Any comment is welcome!!! Architecture Proposal ===================== The Web Platform ---------------- The web platform is the most ubiquitous and battle-tested technology available for user interface implementation today. Because its user interfaces may be declared using dialects of `XML`, it runs in browser environments containing the world's most reliable and optimized [`XML` parser and `DOM` API](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser) implementations. We propose to use this readily available technology throughout the next version of the `OpenSCD` `XML` editor. Proposed Architecture --------------------- ### Overview This is a cartoon representation of the proposed architecture of each individual [WebComponent](https://developer.mozilla.org/en-US/docs/Web/Web_Components) representing a part (e.g. editor pane, editable element, user interface element, plugin etc.) of the `OpenSCD` app, which is at the top level itself a WebComponent making use of (i.e. rendering as parts and delegating updates to) its WebComponent children: . ----- action : Event <---- / \ | | v | update(action) : void render(model) : HTML Node | ^ | | \ / ---> model : XML Node ---- The proposed architecture is inspired by `Flux`, the `Elm` architecture, `cycle.js`'s "Model, View, Intent" architecture, and reactive user interface design in general (`React`, `RxJS` etc.) . Of these, it is closest to `Elm`'s "Model, View, Update" functional architecture, the major caveat being our effectful manipulation (`update`) of the mutable state (`model`) encapsulated in WebComponent properties and attributes instead of functionally producing new immutable state as a function of old immutable state and incoming action. > The view (represented above by `render,` a function of the `model`) represents the "query" part of **CQRS**, presenting relevant parts of the model to the user without modifying anything in the model. > > The `update` function above represents the "command" part of **CQRS**, modifying the model in response to user triggered events without modifying anything about the view. `OpenSCD` would achieve modularity and encapsulation through pervasive use of [`LitElement`](https://lit-element.polymer-project.org/) WebComponents. Each WebComponent consists of an entire `model` -> `render` -> `action` -> `update` cycle -- importing, containing, and using other web components as needed (`1 to n` "has-a" relationships). The top level container element is the `` `LitElement`. ### Model We store the model of each WebComponent entirely in the component's properties and attributes. Our top level (``) model is at its core just a regular **`XMLDocument`** we get from the browser's `DOMParser` Web API by parsing the `SCL` file to be edited upon opening it, decorated with a bit of extra user interface state like: * Which editing actions have taken place so far (`undo`/`redo` **history**) ? * Which view of the editor are we showing at the moment (**active tab**) ? * Which error, warning, and info messages have been shown and seen thus far (**error log**) ? * Which XML node is currently being edited (**focus**) ? Models of individual editor components (e.g. editor panes, modules, plugins) similarly consist chiefly of collections of `XML` `Node`s representing parts of the parent element's model. ### View (`render`) The view of each WebComponent is defined in its `LitElement` `render()` method depending exclusively on the element's attributes and properties (what would otherwise be function parameters in an Elm-like `FRP` approach). It gets called automatically whenever relevant attributes or properties change and returns the updated view in the form of pure `HTML` and `CSS`. ### Action A user action is a semantic event representing some user intention (e.g. "change bay name") that is emitted by the WebComponent upon any one of a set of browser events (e.g. `click`, `keydown`, `touch`) and handled by the element's `update` event handler (or selection of event handlers). ### Update Each user action `Event` is handled by an event handler appropriate to the event type (e.g. `onnamechange` handling `NameChangeEvent`s). These event handlers defined on each WebComponent with the corresponding faculty are represented in above architecture cartoon by the `update` function. Helpful patterns ---------------- These patterns promoted by the team behind `LitElement` should prove helpful in development: * _view as a function of data_: Keep a `currentView` property in the top level component keeping track of the view currently being rendered. * _lazy loading of components_: Use a `lazyLoad` directive for importing both "internal" editor modules (e.g. views) and "external" plugins dynamically when needed. * _[pending state protocol](https://github.com/justinfagnani/pending-state-protocol)_: Use "pending state" events in long-running component updates to allow the app to notify the user of progress. * _CachedTask helper_: Cache the results of async work (like loading a `WASM` schema validator) to enable synchronous rendering of components upon completion. * _data down, events up_: The top-level app Component is responsible for data mutation (command transactor) and receives commands as events from its children. Resultant data is automatically communicated downward to descendants. ```

Any comment is welcome!!!

Architecture Proposal

The Web Platform

The web platform is the most ubiquitous and battle-tested technology available for user interface implementation today. Because its user interfaces may be declared using dialects of XML, it runs in browser environments containing the world's most reliable and optimized XML parser and DOM API implementations.

We propose to use this readily available technology throughout the next version of the OpenSCD XML editor.

Proposed Architecture

Overview

This is a cartoon representation of the proposed architecture of each individual WebComponent representing a part (e.g. editor pane, editable element, user interface element, plugin etc.) of the OpenSCD app, which is at the top level itself a WebComponent making use of (i.e. rendering as parts and delegating updates to) its WebComponent children:

.          ----- action : Event <----
         /                            \
        |                              |
        v                              |
update(action) : void      render(model) : HTML Node
        |                              ^
        |                              |
         \                            /
           ---> model : XML Node ----

The proposed architecture is inspired by Flux, the Elm architecture, cycle.js's "Model, View, Intent" architecture, and reactive user interface design in general (React, RxJS etc.) . Of these, it is closest to Elm's "Model, View, Update" functional architecture, the major caveat being our effectful manipulation (update) of the mutable state (model) encapsulated in WebComponent properties and attributes instead of functionally producing new immutable state as a function of old immutable state and incoming action.

The view (represented above by render, a function of the model) represents the "query" part of CQRS, presenting relevant parts of the model to the user without modifying anything in the model.

The update function above represents the "command" part of CQRS, modifying the model in response to user triggered events without modifying anything about the view.

OpenSCD would achieve modularity and encapsulation through pervasive use of LitElement WebComponents. Each WebComponent consists of an entire model -> render -> action -> update cycle -- importing, containing, and using other web components as needed (1 to n "has-a" relationships). The top level container element is the <open-scd> LitElement.

Model

We store the model of each WebComponent entirely in the component's properties and attributes.

Our top level (<open-scd>) model is at its core just a regular XMLDocument we get from the browser's DOMParser Web API by parsing the SCL file to be edited upon opening it, decorated with a bit of extra user interface state like:

Models of individual editor components (e.g. editor panes, modules, plugins) similarly consist chiefly of collections of XML Nodes representing parts of the parent element's model.

View (render)

The view of each WebComponent is defined in its LitElement render() method depending exclusively on the element's attributes and properties (what would otherwise be function parameters in an Elm-like FRP approach). It gets called automatically whenever relevant attributes or properties change and returns the updated view in the form of pure HTML and CSS.

Action

A user action is a semantic event representing some user intention (e.g. "change bay name") that is emitted by the WebComponent upon any one of a set of browser events (e.g. click, keydown, touch) and handled by the element's update event handler (or selection of event handlers).

Update

Each user action Event is handled by an event handler appropriate to the event type (e.g. onnamechange handling NameChangeEvents). These event handlers defined on each WebComponent with the corresponding faculty are represented in above architecture cartoon by the update function.

Helpful patterns

These patterns promoted by the team behind LitElement should prove helpful in development:

Sander3003 commented 1 year ago

Thanks @ca-d!