- PVSM.RU - https://www.pvsm.ru -
"Reactive Extensions [1]" — это больше, чем фреймворк. Хотя бы потому, что существует практически идентичная реализация (с поправкой на особенности конкретного языка и соответствующих практик оптимизации) под каждый популярный ЯП. Есенин утверждает, что «большое видится на расстояньи». В этой записке я буду отходить на разные «расстоянья» и описывать то, что видится мне.
Вижу push-версию классической реализации Iterator [2]'a GoF. Я уже писал [3] об этом, поэтому без подробностей.
На этом расстоянии ясно виднеется различие между push- и pull-системами. После такого озарения каждый git push и git pull вызывает чуть ли не благоговейный трепет. Начинаешь шариться по коду и задаваться сакральными вопросами о дуалах.
«Нечто продолжается» (метод next), «нечто завершилось» (метод completed), «все пошло не так» (метод error) — три утверждения, которыми можно описать любой процесс, развивающийся во времени. Причем от физического времени абстрагироваться легко, заменив его «последовательностью состояний» (в которых оказывалась система). Rx позволяет свести самые разнообразные алгоритмы к единому интерфейсу (в смысле «договоренности» программиста с другими программистами и, что еще важнее, с машиной), при этом не накладывая ограничений ни на выразительность (число возможных состояний), ни на (по желанию: синхронное, асинхронное или мультипоточное) исполнение.
Отсюда следует важнейший вывод: один rx — один процесс. А если сложный процесс состоит из n подпроцессов, то… один rx «высшего порядка», который управляет работой n rx'ов «первого порядка». По аналогии с функциями высшего порядка [6].
По аналогии с функциями? Да, функциями. Последнее и самое мощное озарение в том, что rx — это просто декорация функции — программистской, а не математической: последние живут вне времени; обычная функция способна совершить return result; только один раз. А next(result); — это «многоразовая» версия return'а. Отсюда важнейший вывод: все, что можно делать с математическими (чистыми) и обычными ООПшными функциями (в том числе и каррирование [7], и композиция [8], и много чего другого, чему данный очерк не посвящен), можно делать и с rx. Функции бывают блокирующими и асинхронными: rx тоже. Функции могут возвращать функции: rx тоже. Функции могут быть рекурсивными: rx тоже. Вычисления функций можно кешировать: в rx тоже.
Любопытно, что на этом этапе понимания невольно возвращаешься в… функциональное программирование. Не ради декларативности, не ради иммутабельности — это все (необязательные) бонусы. В «функциональное» потому что вынужден думать в терминах функций и их композиций; а по непреложному закону «один rx — один процесс», именно функции (а не классы, абстрактные классы, интерфейсы или что там еще есть) становятся «отправной точкой» в проектировании.
У меня всё.
Автор: f2heartz
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/309672
Ссылки в тексте:
[1] Reactive Extensions: http://reactivex.io/
[2] Iterator: https://www.oodesign.com/iterator-pattern.html
[3] писал: https://habr.com/ru/post/437520/
[4] Observer: http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObserverDoc.html
[5] формализовать строго: https://en.wikipedia.org/wiki/Dual_(category_theory)#Formal_definition
[6] функциями высшего порядка: https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F_%D0%B2%D1%8B%D1%81%D1%88%D0%B5%D0%B3%D0%BE_%D0%BF%D0%BE%D1%80%D1%8F%D0%B4%D0%BA%D0%B0
[7] каррирование: https://en.wikipedia.org/wiki/Currying
[8] композиция: https://en.wikipedia.org/wiki/Function_composition
[9] Источник: https://habr.com/ru/post/441452/?utm_campaign=441452
Нажмите здесь для печати.