Øredev 2017

# Dr Gleb Bahmutov PhD

C / C++ / C# / Java / CoffeeScript / JavaScript / Node / Angular / Vue / Cycle.js / functional

JavaScript ninja, image processing expert, software quality fanatic

# Get the slides

## Example problem

``````var numbers = [3, 1, 7]
var constant = 2
// 6 2 14``````

## given an array of numbers, multiply each number by a constant and print the result.

``````var numbers = [3, 1, 7]
var constant = 2
for (var k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
}
// 6
// 2
// 14``````

## Imperative code

``````var numbers = [3, 1, 7]
var constant = 2
for (var k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
}
console.log('k =', k)
// 6
// 2
// 14
// k = 3``````

## Always something unexpected

``````var numbers = [3, 1, 7]
var constant = 2
for (let k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
}
console.log('k =', k)
// console.log('k =', k)
//                    ^
// ReferenceError: k is not defined``````

## ES6 "let" 👍

``````var numbers = [3, 1, 7]
var constant = 2
for (let k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
constant = 10
}
// 6
// 10
// 70``````

## Source code should reflect what really happens

``````var numbers = [3, 1, 7]
const constant = 2
for (let k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
constant = 10
}
// 6
// index.js:13
//  constant = 10
//           ^
// TypeError: Assignment to constant variable.``````

## ES6 "const" 👍

``````standard --verbose --fix 'src/**/*.js'

standard: Use JavaScript Standard Style
(https://standardjs.com)
index.js:13:3:
'constant' is constant. (no-const-assign)``````

## Static code linting 👍

``````const numbers = [3, 1, 7]
const constant = 2
for (let k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
}``````

## Let's make "numbers" constant too

``````const numbers = [3, 1, 7]
const constant = 2
numbers[0] = 100
for (let k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
}
// 200
// 2
// 14``````

## JavaScript "const" is a liar

`const X = Y`

X cannot point at anything else but Y

``````const immutable = require('seamless-immutable')
const numbers = immutable([3, 1, 7])
const constant = 2
numbers[0] = 100
// index.js:4
// numbers[0] = 100
//            ^
// TypeError: Cannot assign to read only
//   property '0' of object '[object Array]'``````

## JavaScript 3rd party libraries are awesome

``````const immutable = require('seamless-immutable')
const numbers = immutable([3, 1, 7])
const constant = 2
for (let k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
}``````

Finally, imperative code that means what is says, and says what it means

# Testing

``````it('prints numbers', () => {
const sinon = require('sinon')
sinon.spy(console, 'log')
require('./index.js')
console.assert(console.log.calledWith(6), 'printed 6')
console.assert(console.log.calledWith(2), 'printed 2')
console.assert(console.log.calledWith(14), 'printed 14')
})``````
``````mocha src/**/*spec.js

6
2
14
✓ prints numbers (154ms)

1 passing (163ms)``````
``````it('prints numbers', () => {
const sinon = require('sinon')
sinon.spy(console, 'log')
require('./index.js')
console.assert(console.log.calledWith(6), 'printed 6')
console.assert(console.log.calledWith(2), 'printed 2')
console.assert(console.log.calledWith(14), 'printed 14')
})

it('does nothing', () => {
console.assert(console.log.calledWith(6), 'printed 6')
console.assert(console.log.calledWith(2), 'printed 2')
console.assert(console.log.calledWith(14), 'printed 14')
})``````
``````mocha src/**/*spec.js

6
2
14
✓ prints numbers (178ms)
✓ does nothing

2 passing (187ms)``````

# Tests lie

``````it.only('does nothing', () => {
console.assert(console.log.calledWith(6), 'printed 6')
console.assert(console.log.calledWith(2), 'printed 2')
console.assert(console.log.calledWith(14), 'printed 14')
})``````
``````mocha src/**/*spec.js

1) does nothing

0 passing (11ms)
1 failing

1) does nothing:
TypeError: console.log.calledWith is not a function
at Context.it.only (spec.js:12:30)``````

# Tests are brittle

``````const sinon = require('sinon')
beforeEach(() => {
sinon.spy(console, 'log')
})
afterEach(() => {
console.log.restore()
})
it('prints numbers', () => {
require('./index.js')
console.assert(console.log.calledWith(6), 'printed 6')
console.assert(console.log.calledWith(2), 'printed 2')
console.assert(console.log.calledWith(14), 'printed 14')
})``````

# Reset spies

require is a problem

`require('./index.js')`
• `Loads source from "index.js"`
• `Evaluates the source`
• `Puts result into "require.cache"`
``require('./index.js')``
``````6
2
14``````
``require('./index.js')``
``````
``````
``cache['./index.js'] =``
``// unchanged``
``cache = {}``
``require('./index.js')``
``````6
2
14``````
``require('./index.js')``
``````
``````
``cache['./index.js'] =``
``cache['./index.js'] =``
``cache = {}``

Side effects

``````const immutable = require('seamless-immutable')
function multiplyAndPrint () {
const numbers = immutable([3, 1, 7])
const constant = 2
for (let k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
}
}
module.exports = multiplyAndPrint``````

# Defer execution

``````const multiplyThenPrint = require('./index')
it('prints numbers', () => {
multiplyThenPrint()
console.assert(console.log.calledWith(6), 'printed 6')
console.assert(console.log.calledWith(2), 'printed 2')
console.assert(console.log.calledWith(14), 'printed 14')
})
it('prints numbers again', () => {
multiplyThenPrint()
console.assert(console.log.calledWith(6), 'printed 6')
console.assert(console.log.calledWith(2), 'printed 2')
console.assert(console.log.calledWith(14), 'printed 14')
})``````
``````6
2
14``````
``````6
2
14``````

prints numbers

prints numbers

again

``````function multiplyAndPrint () {
const numbers = immutable([3, 1, 7])
const constant = 2
for (let k = 0; k < numbers.length; k += 1) {
console.log(numbers[k] * constant)
}
}
module.exports = multiplyAndPrint``````

Side effect

Testing this code

Mocking this code

# Mocking smell

multiply

console.log

``````function multiplyAndPrint (cb) {
const numbers = immutable([3, 1, 7])
const constant = 2
for (let k = 0; k < numbers.length; k += 1) {
cb(numbers[k] * constant)
}
}
module.exports = multiplyAndPrint``````
``````module.exports = multiplyAndPrint
if (!module.parent) {
// "app"
multiplyAndPrint(console.log)
}``````
``````const sinon = require('sinon')
const multiplyThenPrint = require('./index')
it('produces numbers', () => {
const cb = sinon.spy()
multiplyThenPrint(cb)
console.assert(cb.calledWith(6), 'produced 6')
console.assert(cb.calledWith(2), 'produced 2')
console.assert(cb.calledWith(14), 'produced 14')
})``````

# Improve Testability

``````function multiplyAndPrint (cb) {
const numbers = immutable([3, 1, 7])
const constant = 2
for (let k = 0; k < numbers.length; k += 1) {
cb(numbers[k] * constant)
}
}
module.exports = multiplyAndPrint``````

multiplyAndPrint is testable, but still produces a side effect

``````const T = () => true
const I = (x) => x``````

pure functions

``````setTimeout(...)
new Promise(...)
window.location = ...``````

not pure

``````const HelloWorld = ({name}) => {
return (
<div>Hello {name}</div>
)
}``````

pure function

``\$el.innerHTML = ...``

not pure

``````const h = require('virtual-dom/h')
const render = ({name}) =>
h('div', {}, [`Hello \${name}`])``````

pure function

``````function main (console) {
return function inner () {
console.log('Hello')
}
}
const app = main(console)
app()``````

# Note: a pure function can return impure function

### pure

defer execution!

require executes code ➡ export a function

log ➡ return a function that logs

Setup a function that will do side effect

But let someone else call it

# Imperative vs Declarative

``````function multiplyAndPrint (cb) {
const numbers = immutable([3, 1, 7])
const constant = 2
for (let k = 0; k < numbers.length; k += 1) {
cb(numbers[k] * constant)
}
}``````
``````function multiplyAndPrint (cb) {
const numbers = immutable([3, 1, 7])
const constant = 2
const byConstant = x => x * constant
const log = x => cb(x)
numbers.map(byConstant).forEach(log)
}``````

imperative

declarative

# Elegant, simple,

``numbers.map(byConstant).forEach(log)``

# Curried functions

``````const mul = x => y => x * y
const constant = 2
const byConstant = mul(constant)
// byConstant = y => constant * y
[1, 2, 3].map(byConstant)
// [2, 4, 6]
``````
``````const {multiply, unary} = require('ramda')
function multiplyAndPrint (cb) {
const numbers = immutable([3, 1, 7])
const constant = 2
const byConstant = multiply(constant)
const log = unary(cb)
numbers.map(byConstant).forEach(log)
}
module.exports = multiplyAndPrint``````

## JavaScript 3rd party libraries are awesome

``````function multiplyAndPrint (K, numbers, cb) {
const byConstant = multiply(K)
const log = unary(cb)
numbers.map(byConstant).forEach(log)
}``````
``````if (!module.parent) {
const numbers = immutable([3, 1, 7])
multiplyAndPrint(2, numbers, console.log)
}``````

# Use Inputs

``````const numbers = immutable([3, 1, 7])
multiplyBy(2, numbers)
.forEach(unary(console.log))``````

# Finally, pure "multiplyBy"

``````function multiplyBy (K, numbers) {
const byConstant = multiply(K)
return numbers.map(byConstant)
}``````

# Inputs ➡ Output

``````const numbers = immutable([3, 1, 7])
multiplyBy(2, numbers)
.forEach(unary(console.log))``````

# Can we make this logic pure?

``````function main () {
const numbers = immutable([3, 1, 7])
multiplyBy(2, numbers)
.forEach(unary(console.log))
}
main()``````

# Can we make this logic pure?

``````function main (print) {
const constant = 2
const numbers = immutable([3, 1, 7])
return function dirty () {
multiplyBy(constant, numbers).forEach(print)
}
}
const app = main(unary(console.log))
app()``````

# Return function to do dirty work

### pure

Push side-effects away from the core

Pushing side-effects in ServiceWorkers

# Gleb Bahmutov

## The future belongs to you (and your JavaScript)

Friday, 14.20 Room: Homo Agitatus

# Going beyond arrays

``````const numbers = [3, 1, 7]
multiplyBy(2, numbers)
.forEach(unary(console.log))
// 3
// 1
// 7
numbers.push(100)``````

nothing happens

# Reactive streams

``````const Rx = require('rxjs/Rx')
function main (print) {
const constant = 2
const numbers = Rx.Observable.of(3, 1, 7)
return function dirty () {
multiplyBy(constant, numbers).forEach(print)
}
}
main(console.log)()``````
``````6
2
14``````

prints multiplied numbers

# Reactive streams

``````const Rx = require('rxjs/Rx')
function main (print) {
const constant = 2
const numbers = Rx.Observable.interval(1000)
return function dirty () {
multiplyBy(constant, numbers).forEach(print)
}
}
main(console.log)()``````
``````0
2
4
6
...``````

prints multiplied seconds

``````function main (print) {
const constant = 2
const numbers = Rx.Observable.of(3, 1, 7)
return function dirty () {
const seconds = Rx.Observable.interval(1000)
const numberPerSecond = Rx.Observable.zip(
numbers,
seconds,
(number, seconds) => number
)
multiplyBy(constant, numberPerSecond)
.forEach(print)
}
}``````
``````6
2
14``````

prints a multiplied number

every second

``````// numbers -3-1-7-|------------->
// seconds -0---1---2---3---4--->

// zip: (number, second) => number

// num/sec -3---1---7-|--------->

// map: x => 2 * x

// result  -6---2---14-|-->``````
``````6
2
14``````

# Marble diagrams

prints a multiplied number

every second

``````function main (print) {
const constant = 2
const numbers = Rx.Observable.of(3, 1, 7)
const seconds = Rx.Observable.interval(1000)
const numberPerSecond = Rx.Observable.zip(
numbers,
seconds,
(number, seconds) => number
)
return function dirty () {
multiplyBy(constant, numberPerSecond)
.forEach(print)
}
}``````

### pure

Creates stream "subscription"

Starts event flow

``````function main (print) {
const constant = 2
const numbers = Rx.Observable.of(3, 1, 7)
const seconds = Rx.Observable.interval(1000)
const numberPerSecond = Rx.Observable.zip(
numbers,
seconds,
(number, seconds) => number
)
return function dirty () {
multiplyBy(constant, numberPerSecond)
.subscribe(print)
}
}``````

### pure

Creates stream "subscription"

Starts event flow

### impure

When you connect pipe system, it is all clean.

It only gets dirty after the first flush.

``````function main () {
const constant = 2
const numbers = Rx.Observable.of(3, 1, 7)
const seconds = Rx.Observable.interval(1000)
const numberPerSecond = Rx.Observable.zip(
numbers,
seconds,
(number, seconds) => number
)
return multiplyBy(constant, numberPerSecond)
}
main().subscribe(console.log)``````

### impure

In reactive program, we don't need to return a second function to push out side effects. Just return a cold Observable

# Defer execution

``````function main (print) {
return function dirty () {
print()
}
}
const app = main(console.log)
app()``````
``````function main () {
return Observable...
.map(...)
.filter(...)
.zip(...)
}
const app = main()
app.subscribe(console.log)``````

### impure

``````it('multiplies numbers', done => {
this.timeout(2500)
const app = main()
const numbers = []
app.subscribe(x => numbers.push(x), null, () => {
console.assert(equals(numbers, [6, 2, 14]))
done()
})
})``````

direct side effect into the test result

# Testability

``````it('tests second number', done => {
main()
.skip(1)
.take(1)
.subscribe(x => console.assert(x === 2), null, done)
})``````

test second number

lazy-evaluate

# Reactive Console App

``````const readline = require('readline')
if (process.stdin.isTTY) {
process.stdin.setRawMode(true)
}
function getKeys () {
const key\$ = Rx.Observable.fromEvent(
process.stdin, 'keypress')
const enter\$ = key\$.filter(s => s === '\r')
return key\$.takeUntil(enter\$)
}``````

stream of keyboard presses

# Reactive Console App

``````const constant = 2
const key\$ = getKeys()
const app = main(constant, key\$.map(Number))
app.subscribe(console.log, null, () => {
console.log('done with keys')
process.exit(0)
})``````

multiplies user numbers

We pushed input and output streams outside of "main" function

Synchronize

everything

vs

Concurrent

events

# Reactive Web App

``````const h = require('virtual-dom/h')
const constant = 2
const numbers\$ =
Rx.Observable.fromEvent(\$input, 'input')
.map(event => event.target.value)
const app = main(constant, numbers\$)
.map(x => h('div', {}, [x]))
app.subscribe(vdom => {
patchDOM(vdom)
})``````

stream of values from DOM

stream of output virtual doms

# Cycle.js

A functional and reactive JavaScript framework for predictable code

# Cycle.js

``````function main({DOM}) {
const decrement\$ = DOM
.select('.decrement').events('click')
.map(ev => -1)
const increment\$ = DOM
.select('.increment').events('click')
.map(ev => +1)
...``````

Decrement

-1

-1

-1

-1

Increment

1

1

1

intent

# Cycle.js

``````function main({DOM}) {
...
const action\$ =
Observable.merge(decrement\$, increment\$)
const count\$ =
action\$.startWith(0).scan((x,y) => x+y)``````

-1

-1

-1

-1

1

1

1

-1

-1

-2

-1

0

-1

0

0

model

action\$

count\$

# Cycle.js

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

view

# Cycle.js

``````Cycle.run(main, {
DOM: CycleDOM.makeDOMDriver('#app')
})``````

See in action at glebbahmutov.com/draw-cycle/

start app from main

# Cycle.js on the server

``````server.use(function (req, res) {
run(main, {
DOM: makeHTMLDriver(html => res.send(html))
})
})
server.listen(process.env.PORT)``````

Isolated rendering ➡ simple to render into HTML and send to the client

# Conclusions

## Defer execution

• return impure function for someone else to call
• return Observable for someone else to start

# Conclusions

## Build reactive functional apps

• Use Observables as arguments / return value
• Process events in the pipeline using small simple callbacks

# Thank You  👏 Øredev

slides.com/bahmutov/fp-apps

mention @bahmutov

when it comes out ...

bahmutov.com

everyone