Declarative UI Programming

What is Declarative?

State your intent !

Why does it matter?

  • nobody knows what they want:

    • stakeholders use vague language that doesn't nail down the problem

    • programmers use strict language that could, but:

  • programmers prefer working on everything else

What tangible problem are we trying to solve?

Iterate better UX with less effort.

What is UI?

  • the software, from the user perspective

  • a nightmare, from the developer perspective

Model/View Split

  • Pro: business rules and presentation are separated; new UI can be built on top of existing models
  • Con: you now have a new problem, i.e. consistency

Model View C...

  • ...ontrollerfest
  • ...atastrophy

Countless attempts to fix it:

HMVC, MVP, MMVC, MVVM

Do they though?

Much ado for nothing

  • anemic domain model
  • dense controller jungle
  • fragile presentation layer

MVC fail at Docler

  • camgirls website with 35m daily visitors (market leader)
  • video + chat component (UI centric) was written in flash and ported to Haxe
  • result: 6MB JS file with barely more than core functionality and tons of bugs delivered

What went wrong?

  • real time video streaming on browsers is a mess
  • strict, dogmatic use of Spring like MVC + IOC architecture on all levels of abstraction
  • attempts to stay decoupled backfired

We made Rick Astley proud!

Begin with what's most important: UI

What if we would start over?

React: UI is a function of State

class Counter extends React.Component {
  state = { count: 1 };
  render() {
    return <button onClick={handleClick}>
      {this.state.count}
    </button>
  }
  handleClick = () => this.setState({ 
    count: this.state.count + (this.props.step | 1) 
  })
}

<Counter step={10} />
<Counter />

All internal state is in the state object and setState updates and schedules redraw.

Comparison to classical views

  • Same: State change invalidates component, which then updates.

  • Different: A React view uses the same code for creating and updating a component (via vdom diffing).

     

Composition: Lifting State Up

Single temparature input:

What if we need multiple ones?

class TemperatureInput extends React.Component {
  state = { value: 0 }
  render() {
    <label>
      <input 
        type="number" 
        value={this.state.value} 
        onChange={e => this.setState({ value: e.target.valueAsNumber })} 
      />
      °C
    </label>
  }
}

Step 1: externalize state

It's all in the props now.

class TemperatureInput extends React.Component {
  render() {
    <label>
      <input 
        type="number" 
        value={this.props.value} 
        onChange={e => this.props.onChange(e.target.valueAsNumber)} 
      />
      {this.props.unit}
    </label>
  }
}

Step 2: let it trickle down

class Converter extends React.Component {
  state = { kelvin: 293.15 };
  render() {
    return <div>
      <TemperatureInput
        value={kToF(this.state.kelvin)} unit="°F"
        onChange={(value) => this.setState({ kelvin: fToK(value) })}
      />
      <TemperatureInput
        value={kToC(this.state.kelvin)} unit="°C"
        onChange={(value) => this.setState({ kelvin: cToK(value) })}
      />
      <TemperatureInput
        value={this.state.kelvin} unit="K"
        onChange={(value) => this.setState({ kelvin: value })}
      />
    </div>
  }
}

Problems

  • The whole subtree invalidates

  • The root has both business and presentation logic

Solution: state containers

  • Purely functional: Redux

  • Object oriented: MobX

Redux

typedef Reducer<State, Action> = State->Action->State;

Congratulation, you've reinvented state machines \o/

Usage: Create pure view functions and perform occult ceremonies to connect them to the store.

ProTip: it's a useful pattern in moderation.

MobX

Model your data as objects.

Decorate models with @observable and @computed

and views with @observer.

While rendering, views subscribe to changes of the data they rendered and update accordingly.

Full Frameworks

  • Vue (the new hype)
  • Svelte (much like Vue, but cleverer)
  • Imba (much like svelte, but with its own language)
  • coconut (pure Haxe goodness)

React has made it beyond hype

  • Funded by Facebook
  • React Native project for native iOS and Android UI
  • Microsoft just published React Native Windows
  • It has decent Haxe bindings!

React is usually fast enough

React + MobX + custom renderer

So,
what's
Coconut?

A Search for the Holy Grail of UI Programming

What I though I was getting myself into

High level overview

Full React Interop

  • Can use React components within coconut and coconut views as React components
  • Access to vast React ecosystem, e.g. material-ui
  • Can target React Native
  • Switched to React at Docler for interop with other teams:

89 files changed, 376 insertions(+), 427 deletions(-)

Hello, TodoMVC

  • 28 KB minified
  • outscales preact on preact's benchmark

Some more numbers

Other backends

  • OpenFl: exists merely as tutorial for now, but once Haxe FeathersUI is public, it's going to be a thing!

  • HaxeUI: waiting for "new-component-method" branches to be merged
  • Pixi.js or Heaps / h2d / DomKit: hopefully by Mark Knol
  • native Android: as soon as genjvm works!
  • whatever you want ;)

Time
for a
Demo ...

Declarative UI

By Juraj Kirchheim

Declarative UI

  • 1,903