FSMoothy
Сходил на Kolesa.conf. И тут подъехали видео докладов.
Самой мякоткой для меня, конечно, был доклад про конечные автоматы.
Когда узнал, что Кирилл собрался делать доклад на тему КА - я поднапрягся и доделал свою либу для TypeORM (typeorm-fsm). До того, как в проектах мы переехали на нее использовали какой-то огрызок с самописной обвязкой. Тут же я приложил чуть больше своего api-дизайнерского скилла и вроде даже получилось скрестить суть-фундамент с практической пользой.
Как мне кажется, основой такой библиотеки в приложении к самомой логике автоматов должны служить два подхода: Observer (реакция на события), DI (использование внешних систем на переходах).
Пробывал ли я еще что-то? Да, посмотрел много вариантов в npm. Везде свои трейдофы. На фронтовом проекте я ранее применял XState. Давайте рассмотрим что меня в нем не устроило:
- Портянка для описания в виде js объекта. Переходы описываются вербозно (зато есть визуализатор), поддерживает стандарт State Chart'ов.
- Observer на action'ах. Описывается очень вербозно. В разных частях портянки объекта-описания.
- Активный конечный автомат (actor). Круто! Но, в таком виде на бэке скорее очень мало куда подойдет.
- Персист данных встроенный в саму либу. На самом же деле логика персиста ложится на клиентскую часть. В экосистеме готового ничего нет.
- Своя система работы с эффектами. Выглядит прикольно, но на деле в таком виде нужно только для активного конечного автомата.
Есть более простые реализации конечных автоматов. Но в них всегда не хватает каких-то фич, которые фундаментальные, а без них некоторые кейсы решать очень сложно:
- Гварды. Условия на переходах. Без них никуда. Иначе логика также размажется по коду.
- Не все события можно отследить. В моем понимании у события есть следующий следующий жизненный цикл: покидаем предыдущее состояние (onLeave), входим в новое (onEnter), меняем состояние (transition), сработали глобальные подписчики, окончание перехода (onExit). Отсутсвие части этих подписчиков также заставляет размазать часть логики из перехода в клиентский код.
- Вложенные и паралельные состояния. Когда горит красный сигнал светофора - может загореться зеленный сигнал для пешехода. Согласование состояния - одна из фундаментальных фишек автомата. Мы можем сделать отдельное состояние для этого случая или сделать вложенный автомат для состояния "красный сигнал" у светофора. Наличие этой фичи решает проблему роста автомата (state explosion problem).
- Вложенные данные. Автоматы также могут содержать дополнительные атрибуты. Например, счетчик времени. И использовать их на переходах.
- Асинхронные подгрузки. Может потребоваться подгружать начальное состояние и вложенные данные из внешних источников.
...
- и на самом деле много чего еще
Моим решением стало написание собственной либы - fsmoothy. В ней все описанные вещи заложены в дизайн и уже реализованны. Дальнейшее расширение планируется за счет написания отдельных пакетов поверх нее и расширения экосистемы.
Выделяйте автоматы у себя в коде явно, думайте о них при проектировании. Берегите свою кодовую базу! 💎
Post #77
1.06K