Skip to content

Architecture

Brendan Hulme edited this page May 31, 2020 · 2 revisions

The basics

The basic app architecture in Ignitor is similar to Flux, in that Components fire off Actions that are Handled by code (business logic) which then updates State.

When the State is updated, Components are notified and reload the changed State (possibly causing a re-render).

So:

  1. A Component loads and requests its state data.
  2. The Component displays its state.
  3. the User interacts with the Component, such as changing a text field.
  4. An Action is triggered with data about the user change or interaction
  5. The Action is dealt with by a Handler (which could be dedicated class or just a function in the Component for simple code flows).
  6. The Handler updtaes the State.
  7. The State notifies the Component and we repeat from step 2.

Basic Architecture

Going further

In order to maintain this one-way circular flow through the app several requirements are enforced:

  • Access to the State is split into Read and Update. Typically a Component will get a State reader via the .GetState() method, whereas an Action handler may want a State updater (via .GetUpdater()).
  • All data in the State is Immutable. You might read data out of the state, and try to change but you can't. You can only change the state, by using the Update mechanism.
  • All data on the move shoud be considered Immutable. By on the move, we mean moving from the Component to the Action handler, the Action handler to the State, and the State to the Component. This includes the actual State data and any Action or Event objects.
    • In addition, code should try to leave the data in an Immutable (read-only) state as much as possible.
  • You can mutate (change) data as much as you like in the Component or the Action handler. Don't worry about your changes, the data is isolated and won't affect anything else until you want it to.
  • The State (and View) models are created using simple object constructs and kept as flattened as possible. No deep object graphs please.
    • This means:
      • One-dimensional Arrays rather than Lists
      • Dictionary's should become their own state where possible
      • All models are concrete - no interfaces please
      • All models are read/write - might seem counter intuitive, but Immutability is handled outside of the model.
      • All models have parameterless constructors
      • Self-referenced objects and recursive object graphs are prohibited. Turn the links into Id's and give them their own state

The architecture of Ignitor allows for contextual state to be maintained at a component level. This means one or more components can define a shared state that is isolated from the Global Application State.

In fact the whole circular flow operates conceptually at both the Component context level as well as the whole application level.

Advanced Architecture

Immutability and Data Isolation

Data in an application shouldn't just change. If we need it to change it should be due to either an interaction from the user or some other event (such as a timer or a websocket update from backend API services).

In Ignitor data is changed in the State via the Update method. This method naturally updates the State, but also transforms the given update data into an Immutable object.

This new Immutable object in the State is now the source of truth for any Components and any associated logic that is interesting in it.

If we need to interact with this Immutable state we have two options. We can either Read the data or we can create a copy of the Immutable that we can modify. If we modify the copy, well, that doesn't matter as we can't change the original Immutable.

Clone this wiki locally