Концепция реактивного программирования сильно вводит в ступор программистов, привыкших к традиционному императивному программированию.
Лично у меня накопился солидный опыт реактивного программирования. Я много раз пытался написать какую-то учебную статью вида «Реактор для чайников», но все спотыкался, как же попроще объяснить вещи и при этом не пропустить какую-либо неточность. И вот примерный результат для Вашего внимания.
Допустим у нас есть традиционный алгоритм приготовления яичницы.
1. Если нет дома яиц, послать жену в магазин за яйцами. Иначе перейти на п.3
2. Дождаться жену с яйцами.
3. Разогреть сковороду с маслом.
4. Разбить пару яиц на сковороду
5. Если дома нет соли, послать жену за солью. Иначе перейти на п7.
6. Дождаться жену с солью
7. Посолить яйца.
8. Жарить до готовности
9. Подать яичницу на стол
Это императивный традиционный алгоритм. Его недостаток в том, что он синхронный и блокирующий. Так, в п.2, п6, п8 идет ожидание, блокирующее выполнение программы до момента пока не произойдет какое-то событие. Конечно, можно использовать какую-то многопоточность, делать в соседнем потоке другие полезные дела. Но это лишь способ, который все равно не меняет суть или концепцию императивной программы.
Суть реактивной программы, это не писать действия программы последовательно одна за другой, а писать императивные кусочки действий, которые надо выполнить по какому-то событию или сигналу. В этом случае нам не нужно даже заботиться о том, чтобы открывать/закрывать потоки и тому подобной ерунде. Программный движок, обнаружив, что у вас реактивный код, сам выделит оптимальное число потоков, чтобы выполнять ваши кусочки в оптимальном, на его взгляд, порядке, максимально снижая простой программы.
Итак, чтобы сделать программу реактивной, нам надо выделить действия и выделить сигналы, по которым эти действия должны запуститься. Так как в реактивном программировании не важен порядок действий, то давайте начнем с конца.
==========
==========
Да, вот так выглядит компьютерная программ в концепции реактивного программирования. Да, смотрится неудобно, а отладка вообще кошмар. Но зато движок может сам решить какие действия ему исполнять, когда ему это делать (естественно по наличию сигнала), а также может взять на выполнение сколько угодно этих действий одновременно, максимально оптимизируя использование ядер.
Это была простая программа, но, по сути, это уже реактивная программа. Настоящая реактивная программ может состоять из описания тысяч таких действий и сигналов. И каждое из этих действий может быть исполнено в любом неизвестном заранее порядке, и одновременно с какими-либо другими действиями.
Но мы видим и составные части программного кода. Это сигнал, по которому надо стартовать действие. Это само действие, которое надо исполнить, и, наконец, это выходные сигналы, которые генерирует данное действия. Эти элементы обязательны, но с оговорками.
Например. Действие должно стартовать по [Сигнал А] И [Сигнал Б]. В этом случае данное действие не будет стартовать пока не просигнализируют оба эти сигнала. В любом порядке, но оба этих сигнала должны поступить.
То же самое и про действия, которые могут стартовать по [Сигнал А] ИЛИ [Сигнал Б]. Думаю, объяснять разницу не надо.
Второе – один сигнал, не означает, что по нему может стартовать только одно действие. Несколько действий могут использовать для старта один и тот же сигнал.
Ну и то, что действие может генерировать не один, а разные сигналы на выходе, в зависимости от каких-то условий, мы видели на примере действий [Проверить наличие яиц.] и [Проверить наличие соли]
Попробуем оптимизировать нашу реактивную программу. Мы можем «одновременно» проверить наличие и яиц и соли, и послать жену в магазин и за солью, и за яйцами один раз. При этом мы можем начать разогревать сковороду, не дожидаясь жены из магазина.
Тогда программа будет такая. Для удобства напишу ее в хронологическом порядке, но этот порядок не важен в реактивном программировании:
===========
===========
Заметили, насколько оптимизировалась программа? Теперь жена ходит в магазин один раз. Сковорода начинает разогреваться независимо от наличия яиц или соли, когда жена возвращается из магазина, сковорода может быть уже вполне разогрета, если движок выполнял эти действия в двух параллельных потоках.
Если у нас есть яйца, но нет соли, то это не мешает начать жарить яйца, пока жена ходит в магазин за солью. Вернется и можно сразу солить горячую яичницу.
Вот кратко и суть концепции реактивного программирования в моем изложении для чайников.