Про реактивное программирование уже написаны сотни статей. Фронтенд не смог избежать этого тренда, но интерес к теме до сих пор очень и очень высок. Поэтому мы просто не могли не взять интервью у одного из наших будущих докладчиков.

Итак, прошу любить и жаловать, Виктор Русакович. Родом из Минска, работает в компании GP Software.travel.
Виктор последние пять лет занимается (в основном) фронт-енд разработкой. Ну а начинал, как и большинство из нас, с jQuery.

Потом был backbone, angular v1. Последние полгода он работает в проекте на Redux/React.js (часто их путают с RxJS, но это немного другое).



В твоем проекте активно используется реактив. Можешь объяснить, что это такое и с чего это движение началось? Сейчас у всех на слуху RxJS, RxJava, RxPython, RxBasic, ну и разве что RxBrainfuck нет.



Действительно, один из моих предыдущих проектов был насквозь пронизан использованием библиотеки RxJS. Все AJAX-запросы, работа с DOM-событиями, порой просто обработка статичных данных — всё это проходило через RxJS.

Для начала пара слов о «реактивном программировании» как таковом. Например, в жизни с «реактивностью» вы сталкиваетесь в Excel:



Как видите, для автоматического вычисления суммы были созданы ячейки с формулами. На языке реактивного программирования это можно изобразить в виде двух потоков данных, gross и taxes, и третьего потока net, который будет собирать данные из gross и taxes и аггрегировать их по нашей формуле, превращая в итоговое значение.
Я буду пользоваться очень удобным онлайн-редактором, чтобы показывать все свои примеры. Этот редактор хорош тем, что прямо в брузере рендерит результат работы приложения. Ну и самая классная фича радактора в том, что потом все сниппеты останутся доступными по прямой ссылке. Мой первый пример тут.

var gross = Rx.Observable.just(5000)
var taxes = Rx.Observable.just(13)
var net = gross.combineLatest(taxes, (g, t) => g - t / 100 * g)

net.subscribe(money => document.getElementById('out').value = money)


В интернете можно найти много вариантов определения «реактивного программирования»: в Википедии, здесь, на Хабре. Тема серьёзная, даже существует специальный манифест, который можно подписать, если вы согласны с его идеями — только зачем? Лично мне все эти определения не нравятся, и я придумал свое:
Реактивное программирование — это когда ты вместо обработки событий по одному объединяешь их в поток и затем работаешь уже только с ним.
(Дата, Подпись, Печать).




Если же говорить о том, как все это зародилось, то история появления RxJS такая.
Году в 2010-2011 ребята из Microsoft, которые работали c .NET, решили, что неплохо было бы и для JS сделать реактивную библиотеку. Дело в том, что в .NET уже достаточно давно был популярен LINQ. Например, вот так с помощью LINQ можно подсчитать количество вхождений определенного слова в строке.

       string searchTerm = "data";
       //Convert the string into an array of words
        string[] source = text.Split(new char[] { '.', '?', '!', ' ', ';', ':', ',' }, StringSplitOptions.RemoveEmptyEntries);
        // Create the query.  Use ToLowerInvariant to match "data" and "Data" 
        var matchQuery = from word in source
                         where word.ToLowerInvariant() == searchTerm.ToLowerInvariant()
                         select word;
        // Count the matches, which executes the query.
        int wordCount = matchQuery.Count();


Нам посчастливлось начать работать с самой первой версии библиотеки. Код тогда ещё был не в GitHub, а в каком-то собственном репозитории от Microsoft. Кроме того, особенности лицензии не позволяли включать в проект неминифицированную версию. Огромной проблемой была документация — приходилось читать статьи, написанные для .NET, и пытаться понимать на уровне концепций, невзирая на различия в языках. Именно тогда я понял, что могу писать на любом языке программирования.

Как вообще вы пришли к идее использовать RxJS?



В каждом проекте есть свои особенности, которые влияют на выбор той или иной технологии. Решение может быть обсуловленно сложностью интерфейса, наличием или отсутствием внятного Roadmap’a, который показывает, что проект будет развиваться и усложняться как минимум несколько лет. А ещё в 2012 мы не смогли найти ничего другого, похожего на RxJS. Нам была важна хорошая техническая поддержка, и мы поддались бренду Microsoft.

Зачем же нам понадобился RxJS в тот момент?
Представьте себе приложение, в котором много независимых UI компонентов.
Теперь добавляем сюда штук 10 API запросов (от авторизации до проверки цены продукта). Так, есть.
Затем группируем компонеты во View так, что некоторые используются в разных View, а некоторые — нет. Хорошо получается.

Теперь нам надо научить компоненты менять свое состояние между запросами. Где-то показать слой со спиннером, где-то спрятать данные, когда вернется ошибочный запрос. Причём, компонент может зависить от нескольких API и, более того, иногда имеет значение не одиночный запрос, а серия запросов и их ответы. И вишенку на наш торт — на улице 2012 год, Angular нету, Backbone не подходит — значит, будем работать только с jQuery. Без фреймворка.

RxJS подошел идеально. Мы перестали ловить отдельные события и строить огромные пирамиды callback’ов. Что такое пирамида из callback объяснять не нужно, надеюсь?

Вместо этого между компонентами у нас появились потоки с данными, из которых мы могли создавать новые потоки, нужные в конкретной ситуации. Например, есть у нас поток с выбором какого-то продукта. Если пользователь добавляет что-то в корзину, то в этом потоке появляется событие с добавленным продуктом. Если пользователь удаляет продукт — в потоке появляется событие с пустым массивом. Допустим, мы хотим, чтобы таблица моргала красным каждый раз, когда удаляется что-то из корзины:

var cart = require(‘streams/cart’)
var removalsFromCart = cart
  .bufferWithCount(2,1)  
  .where(history => history[1].length < history[0].length)

removalsFromCart.subscribe(() => $(‘table’).setClassFor1Sec(‘warning))


Ссылка на сниппет.

.bufferWithCount() будет брать предыдущее и текущее события и передавать их массивом дальше. В .where() мы проверяем, что текущая корзина (она будет вторым в массиве после .bufferWithCount) содержит меньше элементов, чем предыдущая. Если условие правдивое, то данные передаются дальше в метод .subscribe(), попасть в который является целью каждого события в потоке. Если б не использование метода .where(), то каждое изменение корзины вызывало бы моргание.

Значит, причины были именно такие. Как ты считаешь, а по каким еще причинам имеет смысл начинать использовать реактивный подход в проектах?



В самом начале мы все-все события превращали в Rx.Observable. Со временем мы поняли, что это не всегда оправдано. Например, если мы на 100% уверены, что клик по этой кнопке вызывает перезагрузку страницы, то никаких дополнительных изменений на странице не потребуется. Теперь такие простые и не связанные с другими события мы обрабатываем без RxJS.

Но как только вам надо следить за многими событиями, тут без RxJS не обойтись.
Например, это могут быть вебсокеты, создающие огромные потоки данных.
Это могут быть анимации, которые начинаются при получении одного запроса, а при окончании должны запустить следующий запрос.

Но вот за что мы особенно полюбили RxJS, так это за то, что при написании всех этих .where(), .buffer(), .map() и пр. методов нам совершенно не важно, что является источником данных. Это может быть массив или же вебсокет, который может прислать по 100 объектов в секунду, а потом вдруг остановиться на минуту. Все эти события равны для нас и обрабатываются одинаково.

А это значит, что, разобравшись с асинхронными вещами, мы можем начать использовать RxJS для обработки абсолютно синхронных данных, например, пометить жирным все внешние ссылки:
Rx.Observable.from(document.querySelectorAll('a'))
  .where(el => el.getAttribute('href').indexOf('http') === 0)
  .subscribe(el => el.style.fontWeight = 'bold')


Ссылка на сниппет.
Резюмируя, скажу, что, как мне кажется, RxJS идеально подойдёт для проектов с большими потоками данных, на которые нужно реагировать — игры, чаты и простые сайты, в которых есть какие-то сложные обновления на странице. Не зря, думаю, RxJS включили в Angular 2.

А какие еще решения есть для JS?



Сходу вспоминается несколько альтернатив. В первую очередь это BaconJS. Библиотека создана примерно в то же самое время, когда и RxJS. Что интересно, в одном из проектов мы даже пытались выбрать между RxJS и Bacon — это было года 4 назад, когда обе библиотеки только-только вышли. Но тогда выбор склонился в сторону RxJS, так как Bacon проигрывал по количеству стандартных методов и более простому API в целом. Ну, и еще одним немаловажным фактором, как я уже сказал, было то, что развитием и поддержкой занимался лишь Juha Paananen, а за RxJS стояла Microsoft. Сегодня пользоваться BaconJS можно без каких-либо опасений, потому что хорошее сообщество уже сформировалось, API хорошо задокументировано, и можно найти много отличных примеров.

Следующая альтернатива — это KefirJS (в языке еще остались слова, к которым не добавили JS? :). Замечательная библиотека для реактивного программированния, поддерживаемая нашим соотечественником Романом Поминовым. Роман создавал KefirJS, стараясь взять простоту API от BaconJS (по сравнению с RxJS) и сразу исправляя ошибки в производительности. И знаете, получилось хорошо! Мы, например, пользуемся кефиром каждый день в одном из проектов.

Неужели всё так радужно? Можо просто взять и использовать эти фреймворки?



Есть нюансы.
Года 3 назад после доклада про RxJS на конференции у меня спросили: «Правильно ли я понял, что для того, чтобы использовать реактивное программирование, нужно изменить образ мышления?» Это был самый правильный вопрос за все мои доклады! Очень часто он читался в глазах слушателей, но задали его только раз. И ответ на него: «Да!»

Реактивный подход очень отличается от того, как мы привыкли писать программы. Теперь надо сначала написать код, который будет описывать пути прохождения событий, а уже потом запускать эти события в программу, где они автоматически будут вызывать необходимые действия.
Это первая проблема.

Вторая проблема состоит в том, что порой сложно понять, какой именно метод можно применить в конкретном случае. Например, вы превратили какие-то скалярные данные в запросы. Как теперь получить доступ к ответу сервера? Допустим, вы прочитали описание всех методов в RxJS и даже запомнили .switch(): «Transforms an observable sequence of observable sequences into an observable sequence producing values only from the most recent observable sequence»…
Ну вы поняли — без jsfiddle не разобраться.

С этим сложно бороться, надо будет пережить момент, пока знаний API недостаточно для безостановочного кодинга. Тут пригодится проект rxmarbles.com — его автор (Andre Staltz) создал большое количество динамичных временных диаграмм, по которым можно проследить, как именно влияет порядок данных на итоговый поток. Однако, метода .switch() там не нашлось.

К счастью есть reactivex.io/documentation/operators/switch.html, где можно найти подробное и человеческое описание основных методов и их временных диаграмм, и switch() в том числе:



Видно, что метод .switch() возвращает данные из вложенных потоков. Причем, что важно, данные из вложенного потока поступают на выход до тех пор, пока не появляется новый вложенный поток, который скоро начнет производить данные: обратите внимание на то, что желтый круг не прошел, хотя желтый треугольник еще не появился.
Именно этот метод мы обычно используем, когда работаем с ajax — как только отправлен новый запрос, данные, которые могут вернуться из предыдущего запроса, нам не интересны. Теперь мы никогда не увидим устаревший ответ сервера.

Получается, что при должном умении и желании вполне можно с этим работать и использовать в продакшн. С чего начать и какие ресурсы можно почитать?



Сегодня ресурсов очень много. Только ресурсов со ссылками на ресурсы десятки, на все вкусы: кто-то любит видео-курсы, кто-то — чтение документации с примерами, кому-то книги подавай. Я бы начал вот с этого списка:

  • egghead.io/series/introduction-to-reactive-programming — отличный вводный курс от автора RxMarbles;
  • reactivex.io/intro.html — много теории от авторов RxJS;
  • www.reactivemanifesto.org — манифест (куда без него?);
  • xgrommx.github.io/rx-book — много документации из репозитория RxJS, но есть и много своих хороших статей, например про Backpresure в RxJS (а это, между прочим, часть манифеста!);
  • www.introtorx.com — сборник статей, которые вошли в одноименную книгу (на сайте есть бесплатная mobi версия для Kindle). Не пугайтесь, что всё на .NET — отличное чтение, чтобы понять концепцию. Да и .NET очень похож на TypeScript;
  • Статьи по тегу FRP на Хабре;
  • А начать я советую с подключения в проект rx.lite.js и переводе ваших Ajax (Fetch) запросов на Rx.Observable.




Надеюсь, что в вас пробудилось желание выбросить императивный подход и начать наконец следовать реактивной парадигме! Хватит тянуть данные! Пусть данные сами пройдут по созданым цепочкам!
Кстати, доклад для holyjs.ru уже готов, остались небольшие доработки. В докладе я расскажу на примерах о практическом применении RxJS в ваших проектах. Так что увидимся в Петербурге на конференции 5-ого июня!
Поделиться с друзьями
-->

Комментарии (47)


  1. lair
    01.06.2016 15:22

    Реактивное программирование — это когда ты вместо обработки событий по одному объединяешь их в поток и затем работаешь уже только с ним.

    Кул. Вот и еще один взял и сузил все варианты реактивного программирования до потоков событий. Бедные, бедные акторы.


    1. napa3um
      01.06.2016 22:31
      +1

      Акторы и реактивное программирование — перпендикулярные концепции, они о разном. Реактивное программирование — это именно концептуализация потоков распространения изменений состояния, акторы — это концептуализация параллельных вычислений (хотя и возможно реализовать одно с помощью другого, семантически они не эквивалентны). Или вы имели ввиду что-то ещё?


      1. lair
        01.06.2016 22:50
        +1

        Акторы и реактивное программирование — перпендикулярные концепции, они о разном

        Расскажите это Рональду Куну, автору (одному из) книги Reactive Design Patterns, который считает акторов одним из способов реализации реактивного программирования: "Actors are asynchronous and non-blocking and do support message passing. They do scale up to use multiple cores on a machine. They also scale outward across nodes in both the Erlang and Akka implementations. They provide supervision mechanisms as well in support of fault tolerance. They meet all of the requirements for building Reactive applications."


        Заодно Кун — один из авторов Reactive Manifesto и один из авторов курса Принципы реактивного программирования, в котором акторы тоже упоминаются как равноправный инструмент.


        Окей, не нравится Кун? Вот вам Вернон, Reactive Messaging Patterns with the Actor Model.


        Реактивное программирование — это именно концептуализация потоков распространения изменений состояния

        А откуда вы взяли это определение, и почему вы считаете, что оно верное?


        1. napa3um
          01.06.2016 22:51
          +1

          Хотя и возможно реализовать одно с помощью другого, семантически они не эквивалентны. (Дом можно собрать из кирпичей, но это не значит, что суть дома и кирпича одна и та же.)


          1. lair
            01.06.2016 22:59
            +3

            Я нигде и не говорю, что они семантически эквивалентны. Я всего лишь говорю, что модель акторов — это такая же равноправная реализация реактивного программирования, как и потоки событий (Rx).


            Собственно, Reactive Manifesto — который, извините, немного первичнее, чем обсуждаемый пост — выделяет четыре основных характеристики реактивной системы. Акторы им соответствуют. Rx им тоже соответствует (хотя, по утверждению Куна, и в несколько меньшей мере).


            Так на основании чего вы утверждаете, что реактивное программирование — это только и обязательно потоки изменения состояния?


            1. napa3um
              01.06.2016 23:09
              +1

              «Я всего лишь говорю, что пельмени — это такая же равноправная реализация еды, как и борщ. Иванов считает, что борщ даже лучше еда, чем пельмени. Так на основании чего вы утверждаете, что еда — это только и обязательно пельмени?»

              Реактивное программирование — это еда, а не борщ или пельмени, если вдруг аналогия оказалась непонятной.


              1. lair
                01.06.2016 23:11

                Продолжая вашу аналогию, в статье утверждают, что единственная еда — жидкая, а вся твердая еда — от лукавого.


                1. napa3um
                  01.06.2016 23:28

                  В статье с заголовком «Борщ — отличная еда» вы ожидали рассказа о пельменях? Не очень понятна ваша претензия. О еде в статье написано всё верно, это именно явно описываемые потоки распространения событий изменения состояния, даже если вы предпочитаете делать акцент не на преобразователях данных, а на объектах, в которые упаковали эти преобразователи.


                  1. lair
                    01.06.2016 23:33
                    +1

                    В статье с заголовком «Борщ — отличная еда» вы ожидали рассказа о пельменях?

                    А вы не заметили, что я спорю не с заголовком, а с конкретным определением?


                    это именно явно описываемые потоки распространения событий изменения состояния, даже если вы предпочитаете делать акцент не на преобразователях данных, а на объектах, в которые упаковали эти преобразователи.

                    Я предпочитаю делать акцент на том, что это не потоки.


                    Таки я еще раз вас спрошу, на основании чего вы утверждаете, что реактивное программирование — это обязательно "потоки распространения событий изменения состояния"?


                    1. napa3um
                      01.06.2016 23:35

                      На основании всех источников, в том числе приведённых вами.

                      Для вас, похоже, поток — это что-то типа new Stream, а не концепция.


                      1. lair
                        02.06.2016 00:02
                        +2

                        На основании всех источников, в том числе приведённых вами.

                        Каких "всех"? Приведенные мной источники эту концепцию не поддерживают.


                        А в самых первых строчках статьи — общая концепция.

                        А теперь откроем английский текст: "reactive programming is a programming paradigm oriented around data flows and the propagation of change". Внимание, вопрос: как из этого определения вытекает "вместо обработки событий по одному объединяешь их в поток и затем работаешь уже только с ним"?


                        Data flow — это вполне может быть цепочка разнородных событий "голова к хвосту", те же future, нанизанные через map.


                        1. napa3um
                          02.06.2016 00:06

                          Хватит уже изворачиваться, «flow» переводится конкретно как «поток».


                          1. lair
                            02.06.2016 00:07
                            +2

                            В программировании много что переводится как "поток" — и flow, и stream, и даже thread, но при этом это совершенно разные вещи.


                            А доказать я ничего не хочу, просто уже не первый раз все понятие реактивного программирования сводят к Rx (и в этой статье тоже).


                            1. napa3um
                              02.06.2016 00:12

                              Похоже, вы сами придумали себе войну, решив за автора, что он имел ввиду и что не имел. Flow — это поток, вне зависимости от того, что бывают и иные виды потоков.


                              1. lair
                                02.06.2016 00:14

                                Похоже, вы сами придумали себе войну, решив за автора, что он имел ввиду и что не имел

                                Я делаю выводы о том, что имеет в виду автор, исходя из того, что он пишет в статье.


                                Flow — это поток, вне зависимости от того, что бывают и иные виды потоков.

                                Это только одно из значений. Совершенно не обязательно — правильное и подходящее в данном случае.


                                1. napa3um
                                  02.06.2016 00:17

                                  Вы сами с собой спорите? Теперь и flow вас не устраивает?


                                  1. lair
                                    02.06.2016 00:24

                                    Меня "не устраивает" перевод слова flow как "поток", учитывая существующие в индустрии коннотации — и особенно в контексте поста про Rx.


                                    1. the_ghost
                                      02.06.2016 00:26

                                      Какой перевод вам бы понравился?


                                      1. lair
                                        02.06.2016 00:28

                                        Зависит от фразы целиком. Если речь идет о приведенном выше определении из английской википедии, я бы говорил о "движении данных и распространении изменений".


                                        1. the_ghost
                                          02.06.2016 00:40

                                          Понятно, но не ёмко. Если так разворачивать каждое понятие, то получится простыня, которую понять еще сложнее будет. И так тема для многих сложная, поэтому кое-где приходилось идти на упрощения, которые вы и заметили.


                                          1. lair
                                            02.06.2016 00:43

                                            Эмм, а где "разворачивание"? Английская фраза звучит как "[centered around] data flows and propagation of change". Я просто взял другой вариант перевода слова flow.


                                    1. napa3um
                                      02.06.2016 00:32

                                      Акторы ближе к переводу flow, чем потоки? Какие в индустрии коннотации? Как, по-вашему, нужно было перевести?


                                      1. lair
                                        02.06.2016 00:35
                                        +1

                                        Акторы ближе к переводу flow, чем потоки?

                                        Акторы не имеют никакого отношения к переводу flow — как и reactive extensions.


                                        Какие в индустрии коннотации?

                                        "Поток однородных элементов", как в IO.Stream.


                                        Как, по-вашему, нужно было перевести?

                                        Я уже отвечал the_ghost, перевод "движение данных" кажется мне более уместным.


                                        1. napa3um
                                          02.06.2016 00:43

                                          И чем ваш перевод лучше? Вы уверены, что тот лингвистический дефект, что вы пытаетесь исправить, не дефект вашего личного лексикона?


                                          1. lair
                                            02.06.2016 00:44

                                            И чем ваш перевод лучше?

                                            Тем, что он не вносит (как минимум) третье значение для уже существующего термина.


                                            Вы уверены, что тот лингвистический дефект, что вы пытаетесь исправить, не дефект вашего личного лексикона?

                                            Я уверен, что не только я использую термин "поток" в качестве перевода терминов "stream" и "thread".


                                            1. napa3um
                                              02.06.2016 00:52

                                              Все остальные, пользующиеся терминами только как заклинаниями, не понимая их смысла. По-вашему, и слово «объект» уже использовано, и слово «прототип», а потому нужно говорить «некая сущность» и «прообраз сущности», чтобы не смутить программистов на JS смешиванием терминологии. Ведь русским языком программисты, как известно, не владеют, только языком программирования.


                                              1. lair
                                                02.06.2016 00:54

                                                Ведь русским языком программисты, как известно, не владеют, только языком программирования.

                                                Вам это может показаться странным, но многие программисты, даже русскоязычные, плохо владеют русским языком.


                                                По-вашему, и слово «объект» уже использовано, и слово «прототип», а потому нужно говорить «некая сущность» и «прообраз сущности», чтобы не смутить программистов на JS смешиванием терминологии.

                                                Это не по-моему, это вы мне приписываете нечто, чего я не говорил.


                                                1. napa3um
                                                  02.06.2016 01:10
                                                  -1

                                                  Это аналогия, утрированная, чтобы выразить своё мнение о том, что вы слишком смело свои личные трудности перевода (неспособность принять абстракцию «поток» за пределами IO.Streams или pthreads) спроецировали на остальных. Позабыв уже об акторах.


                                                  1. lair
                                                    02.06.2016 01:16

                                                    Мне, пожалуй, надоело пытаться что-то до вас донести. Всё, что я хотел озвучить по отношению к этому посту, я уже озвучил, и автор меня услышал.


                                                    1. napa3um
                                                      02.06.2016 01:17
                                                      -1

                                                      Спасибо за ваши попытки.


                            1. the_ghost
                              02.06.2016 00:14

                              Фокус на RxJS объясним — доклад будет именно об этой библиотеке.


                        1. the_ghost
                          02.06.2016 00:11

                          вопрос: как из этого определения вытекает «вместо обработки событий по одному объединяешь их в поток и затем работаешь уже только с ним»?

                          Моё определение вытекло вовсе не из приведенного вами. Считайте это «js фронт-енд» квинтэссенцией всех определений о реактивном программировании. Вы сами обратили внимание на количество вариантов. Мы даже xkcd вставили в статью, чтобы не воспринимали это определение как единственно верное.


                          1. lair
                            02.06.2016 00:12

                            Считайте это «js фронт-енд» квинтэссенцией всех определений о реактивном программировании.

                            Можно добавить это ограничение в текст статьи?


                            1. the_ghost
                              02.06.2016 00:16

                              Попробуем завтра подправить. Сегодня редакторы спят. Так сказать, подписались на поток сновидений.


                    1. napa3um
                      01.06.2016 23:47

                      https://ru.m.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5

                      Ваш случай — раздел «Объектно-ориентированное реактивное программирование». А в самых первых строчках статьи — общая концепция.


  1. ilyaplot
    01.06.2016 16:13

    и третьего потока net, который будет собирать данные из net и gross

    Net собирает данные из самого себя или это ошибка?


    1. the_ghost
      01.06.2016 16:42

      Опечатка по тексту — net собирает данные из gross и taxes. Код в статье и на jsfiddle верный.


      1. real_ales
        01.06.2016 17:54

        Спасибо, исправил!


  1. saw_tooth
    01.06.2016 19:12
    +5

    «Например, в жизни с «реактивностью» вы сталкиваетесь в Excel»

    Александр Соловьев, разлогиньтесь пожалуйста.
    ЗЫ. Советую послушать весь данный доклад


    1. the_ghost
      01.06.2016 19:51
      +2

      Отличный доклад, да. Особенно полезен тем, кто желает «раздуплить» реактивность


  1. vintage
    02.06.2016 12:33
    -1

    В KnockoutJS, MeteorJS, $jin_atom нет ни стримов, ни событий, но есть реактивное программирование. Как же так? :-)


    По примеру с экселем, как вы на стримах реализуете пользовательские формулы так, чтобы на изменение любой ячейки не происходил пересчёт всей таблицы?


    Знаете, от доклада на конференции ожидаешь более системного подхода, упорядоченного, всестороннего рассмотрения вопроса, а не просто описания API одной кривоватой библиотеки, подмены понятий и однобокого мнения.


    1. napa3um
      02.06.2016 13:40
      -1

      Как может идти дождь без ног, так и Meteor описывает потоки изменений состояния без объекта DataFlow. Реактивность — это даже не архитектура, это всего лишь абстрактный принцип, который выражаться в конкретной архитектуре может очень по-разному. Но суть этого принципа всегда заключается в удобстве работы с потоками данных.


      1. vintage
        02.06.2016 18:57

        Реактивное программирование — это когда ты вместо обработки событий по одному объединяешь их в поток и затем работаешь уже только с ним.

        Тут явным образом описан event-stream, а не data-flow.


        1. napa3um
          02.06.2016 19:27

          Я прочитал эту фразу с акцентом на повышении уровня абстракции. Т.е., автор, как мне показалось, говорит о наведении порядка в изменении состоянии приложения путём организации разрозненных обработчиков событий в декларативно обозначенные (хоть акторами выражено, хоть атомами, хоть трансдюсерами) _потоки_ распространения изменений состояния приложения. (Но я, наверное, наконец смог прочитать эту фразу и по-вашему.)


    1. the_ghost
      03.06.2016 00:11

      Knockout — в первую очередь это View. Meteor — цельный фреймфорк. В knockout повсюду торчат Observable. C Meteor / jin не работал, деталей не знаю. Сильно много «реактивно» на Knockout не попишешь — не хватает доступных методов для работы с observable — filter/combineLatest/flatMap. Да и по виду код Knockout очень слабо похож на bacon/rx/kefir — мало в нем реактивного.

      По excel. Не совсем понятно условие «любое изменение не пересчитывает всю таблицу». Возможно имеется в виду ситуация, когда значение в зависимой ячейке изменилось на такое же? Для этого есть методы distinct / distinctUntilChanged, которые откидывают повторные значения (более тонкую разницу можно увидеть сравнив диаграмы или почитав http://reactivex.io/documentation/operators/distinct.html

      А вот слова при «кривоватость» библиотеки настораживают… В чем кривость-то? На данный момент у RxJS самое обширное АПИ по работе с Observable.


      1. Riim
        07.06.2016 23:35
        +1

        Сильно много «реактивно» на Knockout не попишешь — не хватает доступных методов для работы с observable — filter/combineLatest/flatMap. Да и по виду код Knockout очень слабо похож на bacon/rx/kefir — мало в нем реактивного


        эти методы — буква F в FRP, отсутствие этих методов делает Knockout менее функциональным, но никак не менее реактивным. К тому же без них вполне неплохо живётся, просто вместо a.add(b) пишется a+b и необходимость в изучении 100500 методов на все случаи жизни сразу отпадает.


  1. vintage
    03.06.2016 09:52

    Knockout — в первую очередь это View. Meteor — цельный фреймфорк.

    И что? Модели реактивности там построены не вокруг потоков событий.


    В knockout повсюду торчат Observable.

    Которые являются реактивными переменными, а не стримами.


    C Meteor / jin не работал, деталей не знаю.

    А вы почитайте. Первый основан на идее "перезапусков", второй — как и нокают на идее "реактивных переменных".


    Сильно много «реактивно» на Knockout не попишешь — не хватает доступных методов для работы с observable — filter/combineLatest/flatMap.

    Они и не нужны. В том же нокауте:


    var filteredList = ko.computed( () => sourceList.filter( i => i % 2 ) ) // filter
    var ballance = ko.computed( () => debet() + credit() ) // combileLatest

    Что делает flatMap затрудняюсь сказать.


    Да и по виду код Knockout очень слабо похож на bacon/rx/kefir — мало в нем реактивного.

    Я бы сказал наоборот, в bacon/rx/kefir мало реактивного, так как они не о data-flow, а о event-streams.


    Возможно имеется в виду ситуация, когда значение в зависимой ячейке изменилось на такое же?

    Нет, имеются ввиду динамические зависимости, задаваемые не в коде, а пользовательским вводом. Ну а то, что "изменение" значения на такое же требует дополнительных костылей в виде distinct — тоже о многом говорит :-)


    А вот слова при «кривоватость» библиотеки настораживают… В чем кривость-то? На данный момент у RxJS самое обширное АПИ по работе с Observable.

    В подходе кривость — заменяются стандартные операторы управления потоком на своё апи, превращают код в лапшу.