Trello, Kanban & Cycle.js

Nicolas Carlo

We do

Cumulative Flow Diagram
(CFD)

Lead Time

Cycle Times

WIP

Existing solutions…

No freemium plan
(free trial period)

Missing Kanban metrics

= use-case for side-project!

Dive into FRP

Functional
Reactive
Programming

Functional Programming concepts

  • First-class functions
  • Higher order functions
  • Pure functions
  • Function composition
  • Immutability

Reactive Programming explained

// This is inside the Foo module

function onNetworkRequest() {
  // ...
  Bar.incrementCounter();
  // ...
}
// This is inside the Bar module

Foo.addOnNetworkRequestListener(() => {
  _incrementCounter();
});

Why so passive?

  • Bar is responsible for itself
  • Find where Foo is listened to understand usages
  • Find where Bar is called to understand usages
  • Foo tells which modules are affected

Default paradigm

Paradigm shift

Let's talk about streams

Events ongoing through time

myStream.addListener({

  next(event) {
    // do something with `event`
  },

  error(error) {
    // do something with `error`
  },

  complete() {
    // do something when it completes
  }

});

Working with streams

Libraries to manipulate Observables with operators

> Rx.js, Bacon.js, xstream…

Working with streams

Marble Diagrams

--a---b-c---d---X---|->

a, b, c, d are emitted values
X is an error
| is the 'completed' signal
---> is the timeline
  clickStream: ---c----c--c----c------c-->
                    map(c becomes 1) 
               ---1----1--1----1------1-->
                        scan(+)
counterStream: ---1----2--3----4------5-->

Meet Cycle.js

What is Cycle.js?

A functional and reactive JavaScript framework for cleaner code

The MVI model

The MVI model

A cyclic architecture

  • App logic lies in main()
     
  • Side effects are isolated in re-usable drivers
     
  • main() is a pure, reactive dataflow

Explicit dataflow

function main(sources) {
  const decrement$ = sources.DOM
    .select('.decrement').events('click').mapTo(-1);

  const increment$ = sources.DOM
    .select('.increment').events('click').mapTo(+1);

  const action$ = xs.merge(decrement$, increment$);
  const count$ = action$.fold((x, y) => x + y, 0);

  const vtree$ = count$.map(count =>
    div([
      button('.decrement', 'Decrement'),
      button('.increment', 'Increment'),
      p('Counter: ' + count)
    ])
  );
  return { DOM: vtree$ };
}

Composable

Demo Time

Thanks!

Strongly recommended reading:
> The whole future declared in a var

Made with Slides.com