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