Top Banner
Functional Reactive Programming : Делаем жизнь проще Parcsis MoscowJS Meetup 19 Trdat Mkrtchyan
35

"FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

Jul 14, 2015

Download

Software

MoscowJS
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

Functional Reactive Programming:

Делаем жизнь проще

Parcsis

MoscowJS Meetup 19

TrdatMkrtchyan

Page 2: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

2

Часть I :

( Функциональная )

Page 3: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

33

Page 4: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

4

( Плюсы (( Иммутабельные данные )( Отсутствие состояния )( Лень, как стратегия вычислений )( Частичное применение и карринг ))

Получаем декларативный подход

Page 5: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

5

( Минусы (( Производительность )( Комьюнити слишком маленькое )( Состояние есть, но оно скрыто ))

Page 6: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

6

Часть II :

( Реактивная )

Page 7: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

7

reactivemanifesto.org

● Responsive

● Scalable

● Resilient

● Event-driven

Page 8: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

8

reactivemanifesto.org

● Responsive

● Scalable

● Resilient

●Event-driven

Page 9: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

9

асинхронность+

дерево состояний

непредсказуемость

Page 10: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

10

Page 11: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

11

Callback hell

Page 12: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

12

arr = [1, 2, 3, 4]

.map(square)

.filter(moreThan3LessThan10)

.reduce(add)

Page 13: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

13

FRP >= FP

Источник данных – это поток событий

Page 14: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

14

FRP > FP

Page 15: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

15

Часть III :

( Программирование )

Page 16: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

16

( RxJS ( Microsoft Reactive Extensions )

github.com/Reactive-Extensions/RxJS )

● Большое комьюнити

● Подробная документация

Page 17: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

17

( Bacon ( Juha Paananen @raimohanska )

github.com/baconjs/baconjs )

● Простое API

● Ясная документация

Page 18: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

18

( Kefir ( Roman Pominov @rpominov )

github.com/pozadi/kefir )

● Высокая производительность

● Активно развивается

Page 19: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

19

( Warden.js ( Trdat Mkrtchyan @zeffirsky )

github.com/zefirka/Warden.js )

( ProAct ( Nickolay Tzvetinov @ntzvetinov )

github.com/proactjs/proactjs )

Page 20: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

20

var timer;

input.addEventListener('keydown', function(event){ if(event.keyCode == 13){

clearTimeout(timer);timer = setTimeout(function(){

doSomething(); }, 500);

}});

Debounce в императивном варианте

Page 21: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

21

Bacon.fromEventTarget(input, 'keydown').filter(function(event){

return event.keyCode == 13}).debounce(500).onValue(doSomething);

Debounce в FRP

Page 22: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

22

События

var clicks = Bacon.fromBinder(function(sink) { document.addEventListener('click', sink);});

Ответы сервера

var responses = Bacon.fromBinder(function(sink) { $.get('path/to', sink);});

Таймер

var ticks = Bacon.fromBinder(function(sink) {setInterval(sink, 1000);

});

Все что угодно – это stream

22

Page 23: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

23

События

var clicks = Bacon.fromBinder(function(sink) { document.addEventListener('click', sink);});

Ответы сервера

var responses = Bacon.fromBinder(function(sink) { $.get('path/to', sink);});

Таймер

var ticks = Bacon.fromBinder(function(sink) {setInterval(sink, 1000);

});

Все что угодно – это stream

23

Page 24: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

24

События

var clicks = Bacon.fromBinder(function(sink) { document.addEventListener('click', sink);});

Ответы сервера

var responses = Bacon.fromBinder(function(sink) { $.get('path/to', sink);});

Таймер

var ticks = Bacon.fromBinder(function(sink) {setInterval(sink, 1000);

});

Все что угодно – это stream

24

Page 25: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

25

// пусть получаем данные из сокета в форме// {player : [Object] , score : [Integer] }

var totalScore = 0;

function calculateScore(data){if(data.player.status == 'A'){

totalScore += data.score}

}

socket.on('score', calculateScore);

Вычисления в императивном стиле

Page 26: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

26

var totalScore = socket.stream('score').filter(function (data){

return data.player.status == 'A';}).map('.score').reduce(function (sum, score){

return sum + score;})

FRP упрощает вычисления

+ Вычисления не производятся, если они не нужны

+ Состояние чистое

+ Можно переиспользовать функции-обработчики

Page 27: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

27

( Интеграция )

Page 28: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

28

( Angular )

Page 29: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

29

Controllerapp.controller('someCtrl', function ($scope, frp){

$scope.users = [];$scope.query = '';

frp.toStream($scope, 'query').debounce(500).map('.newResult') // привет $watch.filter(notEmpty).onValue(function(query){

frp.http.get('search:users', { query: query }).assign($scope, 'users');

});}

+ В духе Angular

- Вынуждены оборачивать службы Angular в FRP

Page 30: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

30

Controllerapp.controller('someCtrl', function ($scope, frp){

$scope.users = [];$scope.query = '';

frp.toStream($scope, 'query').debounce(500).map('.newResult') // привет $watch.filter(notEmpty).onValue(function(query){

frp.http.get('search:users', { query: query }).assign($scope, 'users');

});}

+ Никаких ng-change в разметке

- Неявные $watch и $apply

Page 31: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

31

Page 32: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

32

( Чуть больше магии, но видно,как это работает )

( Все побочные действия – это setState )

( Отлично встраивается во FLUX )

( React )

32

Page 33: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

33

( React )

componentDidMount: function(){this.streamFrom(document, 'mousemove')

.map(function(event){return {

x: event.clientX,y: event.clientY

}}).onValue(this.setState.bind(this));

},

render: function() {return <h1> X: {this.state.x}, Y: {this.state.y}</h1>

}

Page 34: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

34

И это только начало

Page 35: "FRP — делаем жизнь проще", Трдат Мкртчян, MoscowJS 19

35

Trdat Mkrtchyan

Twitter: @zeffirsky

Github: zefirka

MoscowJS Meetup 19 (26. 02. 2015)