Три дзена reactive extensions

    "Reactive Extensions" — это больше, чем фреймворк. Хотя бы потому, что существует практически идентичная реализация (с поправкой на особенности конкретного языка и соответствующих практик оптимизации) под каждый популярный ЯП. Есенин утверждает, что «большое видится на расстояньи». В этой записке я буду отходить на разные «расстоянья» и описывать то, что видится мне.

    Дзен первый


    Вижу push-версию классической реализации Iterator'a GoF. Я уже писал об этом, поэтому без подробностей.

    Краткий пересказ для тех, кому лень читать
    Смысл в том, что Observer — это (почти) «зеркальное отражение» классической реализации Iterator'а. Почему «почти» — объяснено в посте по ранее данной ссылке. Важное замечание: «зеркальное отражение» — это без пяти минут математическое определение и его можно формализовать строго.

    На этом расстоянии ясно виднеется различие между push- и pull-системами. После такого озарения каждый git push и git pull вызывает чуть ли не благоговейный трепет. Начинаешь шариться по коду и задаваться сакральными вопросами о дуалах.

    Дзен второй


    «Нечто продолжается» (метод next), «нечто завершилось» (метод completed), «все пошло не так» (метод error) — три утверждения, которыми можно описать любой процесс, развивающийся во времени. Причем от физического времени абстрагироваться легко, заменив его «последовательностью состояний» (в которых оказывалась система). Rx позволяет свести самые разнообразные алгоритмы к единому интерфейсу (в смысле «договоренности» программиста с другими программистами и, что еще важнее, с машиной), при этом не накладывая ограничений ни на выразительность (число возможных состояний), ни на (по желанию: синхронное, асинхронное или мультипоточное) исполнение.

    Отсюда следует важнейший вывод: один rx — один процесс. А если сложный процесс состоит из n подпроцессов, то… один rx «высшего порядка», который управляет работой n rx'ов «первого порядка». По аналогии с функциями высшего порядка.

    Дзен третий


    По аналогии с функциями? Да, функциями. Последнее и самое мощное озарение в том, что rx — это просто декорация функции — программистской, а не математической: последние живут вне времени; обычная функция способна совершить return result; только один раз. А next(result); — это «многоразовая» версия return'а. Отсюда важнейший вывод: все, что можно делать с математическими (чистыми) и обычными ООПшными функциями (в том числе и каррирование, и композиция, и много чего другого, чему данный очерк не посвящен), можно делать и с rx. Функции бывают блокирующими и асинхронными: rx тоже. Функции могут возвращать функции: rx тоже. Функции могут быть рекурсивными: rx тоже. Вычисления функций можно кешировать: в rx тоже.
    Любопытно, что на этом этапе понимания невольно возвращаешься в… функциональное программирование. Не ради декларативности, не ради иммутабельности — это все (необязательные) бонусы. В «функциональное» потому что вынужден думать в терминах функций и их композиций; а по непреложному закону «один rx — один процесс», именно функции (а не классы, абстрактные классы, интерфейсы или что там еще есть) становятся «отправной точкой» в проектировании.

    У меня всё.
    Поделиться публикацией

    Похожие публикации

    Комментарии 1

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

    Самое читаемое