Intelligently synchronizes any source of JSON data with rich observable Domain Models

Intelligently synchronizes any source of JSON data with rich observable Domain Models

The reactive-domain-objects library intelligently synchronizes any source of JSON data with rich observable Domain Models, providing a bridge from an Imperative programming model of stateful objects to a Reactive programming model of observables, data streams, and reactive user interfaces.

Reactive Domain Graphs

Overview

The reactive-domain-objects library intelligently synchronizes any source of JSON data with rich observable Domain Models, providing a bridge from an Imperative programming model of stateful objects to a Reactive programming model of observables, data streams, and reactive user interfaces.

A primary use case is connecting GraphQL client libraries (such as ApolloGraphQL) to reactive client libraries (such as React) with Observables (such as MobX).

See below for an introduction to the library, and Full Technical/Usage Documentation for a detailed description of all the functionality, configuration options, and additional usage examples.

The Problems Being Solved

The problems being solved primarily revolve around consuming and using JSON data in TypeScript/JavaScript client applications:

  • The Encapsulation Problem: Most modern state management frameworks rely on plain JavaScript object trees. This makes encapsulation (of data, logic, and behavior) difficult which, in turn, makes managing complexity in large codebases or complex business domains much more challenging

  • The Denormalization Difficulty: When working directly with plain JavaScript trees of any non-trivial complexity, denormalization (and corresponding normalization) is usually required for efficient graph traversal. This adds additional complexity and maintenance requirements

  • External Data Sync: Many client UI frameworks, such as React, rely on referential equality of state data. Results returned from external data sources, including REST and GraphQL, will never be referentially equal, even if their structures and values are actually the same. Extensive memoization code, or poor performance result

Key Features

  • Automatic synchronization of Reactive Domain Object Graphs with an external data-source
  • Automatic Change tracking, of external data-sources, with Reactive Domain Object Nodes only being updated only where changes are detected. When combined with Observable properties, this is a very powerful feature that reduces or eliminates the need for memoization code in dependent UI code
  • Convention, Configuration, or Code options for specifying the construction of Reactive Domain Object Graphs
  • Automatic Creation of Observable Domain Model Objects, (base on configuration settings)
  • Emits Node Change Events, which can be subscribed to via the GraphSynchronizer object
  • Rdo Synchronization Lifecycle Hooks, which can be implemented via interfaces
  • Performance Optimized, with sub 0.3 millisecond synchronizations for a medium sized graph (as measured on a 2015 quad-core laptop. Performanc test available for local performance verification)
  • One way data flow paradigm: Actions --> External Data Source --> State
  • Custom Collection Types, to support easy graph traversal, and reduce the need for denormalization of data

Installation

    // npm
    npm i @ablestack/rdo, @ablestack/rdo-apollo-mobx-connector --save

    // yarn
    yarn add @ablestack/rdo, @ablestack/rdo-apollo-mobx-connector

Abridge Usage Example

// DEFINE REACTIVE DOMAIN GRAPH
class FooSimpleDomainGraph {
  public bar = new BarRDO(); //*1
}

export class BarRDO {
  public id: string = '';
  public name: string = '';
}

// INSTANTIATE DOMAIN RDO AND GRAPH SYNCHRONIZER
const fooSimpleRDO = new FooDomainGraphSimple();
const graphSynchronizer = new GraphSynchronizer(/* Config Options Here */);

// SYNC
graphSynchronizer.smartSync({ rootRdo: fooSimpleRDO, rootSourceNode: { bar: { id: 'bar-1', name: 'Original Name' } } });

// Make any changes to the source data

// RESYNC
graphSynchronizer.smartSync({ rootRdo: fooSimpleRDO, rootSourceNode: { bar: { id: 'bar-1', name: 'New Name' } } });

Full Documentation

  • See Full Documentation for a detailed description of all the functionality, configuration options, and additional usage examples.

Definitions

Reactive Domain Object

A Reactive Domain Object (RDO) is any object which satisfies the following conditions:

  1. Contains state, and optionally behavior and logic, relating a discrete entity in a program domain
  2. Internal state is automatically synchronized with changes in an external data-source
  3. Action methods are provided for all acceptable state mutations
  4. Follows a one-way data-flow paradigm, from: Action-Method --> External Data Source --> Internal-State (though synchronization)
  5. Observable Public Properties (optional but recommended)
  6. Child nodes exposed as Maps for efficient graph traversal (optional but recommended)

Notes

Known Issues & Limitations

  • Source & Target Structural Similarity. While field names can be adjusted, by configuration, the overall 'shape' and nesting structure of the graph must match between the source and target graphs. This library does not, yet, have the capability of automatically manipulating the shape of a graph during the synchronization process
  • Array and Set collections types in RDOs are more processing intensive. It is suggested that they are avoided for collections that may contain a large number of elements (100+)

Disclaimers

This code was initially developed for use in a single commercial project. It is being shared in case useful to others, and as a contribution to the development community and the great tools and libraries that already exist.

Refinements and Enhancements Needed

  • Open to suggestions
  • Find a clever way to provide a default mechanism to instantiate Domain Objects without the need for user configuration to provide these. Will probably require some kind of TypeScript reflection, as in 'empty domain collection' scenarios, an instance will not be available, and nor will type runtime type information
  • Provide decorators that can be applied to the Domain Types to perform useful functions in lieu of configuration options, such as 'ignore'

Companion Libraries

This library is part of a collection of companion tools and libraries under the AbleStack umbrella. All of these libraries share the common goal:

Helping small teams and solo-developers build big ideas rapidly and affordably

To achieve these goals, the following principles are applied:

  • Selectively leverage existing open source tools and libraries, where, high quality, open source tools and libraries where possible
    • Curate usage examples, and guidance where available, and create where not available
  • Prioritize technology choices that embrace open source
    • TypeScript over C#, and Node over .Net an example of this
  • Avoid technology choices that could result in hosting vendor lock-in
    • ApolloGraphQL over AWS Amplify is an example of this
  • Automate wherever possible, from development, through testing, to deployment, monitoring, and maintenance
    • Codegen from strongly types schemas is a good example of this.
  • Where needed, develop high quality, open source tools and libraries to augment and automate existing open source tooling and libraries

Alternative Solutions

While this library solves several challenges relating to client-side JavaScript development, it was developed to solve some very specific use cases, and might not be the right solution for everyone. It is definitely worth checkout out these alternative solutions before making your choice:

  • MobX-state-tree is similar in many respects to this library. reactive-domain-objects is designed to solve similar problems, but is less opinionated, less complicated, but also less sophisticated. For more advanced features and a more opinionated solution, MobX-state-tree is definitely worth checking out

  • Vanilla MobX. Many of the benefits reactive-domain-objects come from the integration with the great MobX library. For small and even mid-sized solutions, the same result can be achieved with MobX alone. The primary added benefit that reactive-domain-objects provides is automating the synchronization of data with external data sources. The point at which that task becomes more complex or tiresome than adding another dependency, or learning another library, is the right point at which to get reactive-domain-objects in the mix

Release Notes

Notes 0.1.0

  • Initial release

Notes 0.2.0 - 0.3.0

  • Performance updates

Notes 0.4.0

  • Refactorings for improved maintainability

Notes 0.5.0

  • Added auto-Rdo creation functionality
  • Added GraphSynchronizer EventEmitter. This broadcast all node change event to any subscribers

Download Details:

Author: ablestack

Source Code: https://github.com/ablestack/reactive-domain-objects

react reactjs javascript

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

How native is React Native? | React Native vs Native App Development

Article covers: How native is react native?, React Native vs (Ionic, Cordova), Similarities and difference between React Native and Native App Development.

Increase Performance of React Applications Via Array JavaScript Methods

Increase Performance of React Applications Via Array JavaScript Methods. We will create a simple event management application in the react to add, update, and delete an event.

Routing in React without React-Router

I have been using React JS in my projects for quite some time now and am used to managing routing in my app using the react-router package. I have always been keen on having as little dependencies in my apps as possible, so, I always felt perturbed by the use of this particular package in simpler apps which did not have complex routes.

The Ugly Side of React Hooks

In this post, I will share my own point of view about React Hooks, and as the title of this post implies, I am not a big fan.

ReactJS: The Javascript Developer’s Guide

This article will walk you through the concepts you would need to know to step into the world of widely used ReactJS.