Какова реальная разница между редуксом и конечным автоматом (например, xstate)?

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

Мы решили, что, очевидно, нам нужно реализовать некоторый контейнер состояний для этого приложения в рамках дальнейшего рефакторинга. Ранее у меня был некоторый опыт работы с RedEx и с магазином ngrx (который фактически следует тем же принципам).

Redux - вариант для нас, но один из разработчиков предложил использовать конечный автомат, в частности библиотеку xstate.

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

Я часами пытался найти ответ, или любую другую информацию, связанную со сравнением xstate и redux, или с некоторыми "за и против". К сожалению, у меня в голове беспорядок. Я не нашел какой - либо четкой информации, за исключением некоторых статей, как "получить от перевождь к государственной машине", или ссылки на библиотеки, ориентированных на использование Redux и xstate вместе, и, наконец, сломал меня.

Если кто-то может описать разницу или сказать мне, когда разработчики должны выбрать xstate - милости просим.

Спасибо.

Ответ 1

Я создал XState, но я не собираюсь говорить вам, следует ли использовать один поверх другого; это зависит от вашей команды. Вместо этого я постараюсь выделить некоторые ключевые различия.

  • Redux - это, по сути, контейнер состояния, в котором события (называемые действиями в Redux) отправляются редуктору, который обновляет состояние.
  • XState также является контейнером состояний, но он отделяет конечное состояние (например, "loading", "success") от "бесконечного состояния" или контекста (например, items: [...]).
  • Redux не определяет, как вы определяете ваши редукторы. Это простые функции, которые возвращают следующее состояние, учитывая текущее состояние и событие (действие).
  • XState - это "редуктор с правилами" - вы определяете законные переходы между конечными состояниями из-за событий, а также какие действия должны выполняться при переходе (или при входе/выходе из состояния)
  • Redux не имеет встроенного способа обработки побочных эффектов. Есть много вариантов сообщества, таких как redux-thunk, redux-saga и т.д.
  • XState делает действия (побочные эффекты) декларативными и явными - они являются частью объекта State который возвращается при каждом переходе (текущее состояние + событие).
  • Redux в настоящее время не имеет возможности визуализировать переходы между состояниями, поскольку он не различает конечное и бесконечное состояния.
  • XState имеет визуализатор: https://statecharts.github.io/xstate-viz, который выполним благодаря декларативному характеру.
  • Неявная логика/поведение, представленное в редукторах Redux, не может быть декларативно сериализовано (например, в JSON)
  • Определения машин XState, которые представляют логику/поведение, можно сериализовать в JSON и читать из JSON. Это делает поведение очень переносимым и настраиваемым внешними инструментами.
  • Redux не является конечным автоматом.
  • XState строго придерживается спецификации W3C SCXML: https://www.w3.org/TR/scxml/
  • Redux полагается на разработчика, чтобы вручную предотвратить невозможные состояния.
  • XState использует диаграммы состояний для естественного определения границ для обработки событий, что предотвращает невозможные состояния и может подвергаться статическому анализу.
  • Redux поощряет использование единого "глобального" атомарного магазина.
  • XState поощряет использование подхода, подобного модели актера, где может быть много экземпляров иерархической диаграммы состояний/"службы", которые взаимодействуют друг с другом.

Я добавлю больше ключевых отличий в документы на этой неделе.

Ответ 2

Конечный автомат не сообщает (не заставляет) иметь однонаправленный поток данных. Это не имеет ничего общего с потоком данных. Это больше об ограничении изменений состояния и о переходах состояний. Таким образом, как правило, только некоторые части приложения будут создаваться с помощью конечных автоматов, и только в том случае, если вам нужно ограничить/запретить некоторые изменения состояния и вас интересуют переходы.

Имейте в виду, что для конечных автоматов, если по какой-то причине (зависимость от внешнего API и т.д.) Существует вероятность того, что приложение может быть заблокировано в состоянии, когда оно не может перейти в другое состояние из-за ограничений, вы должны решить это.

Но если вас интересует только само последнее состояние приложения, а не переходы между состояниями, и ограничения состояния не имеют значения, то лучше не использовать конечный автомат и напрямую обновлять состояние (вы все еще можете переносить состояние в обновлении класса Singleton через Классы действий).


С другой стороны, Redux является структурой однонаправленной архитектуры. Однонаправленные архитектуры обеспечивают единую направленность потока данных. В Redux он начинается с User->View->(Action)->Store->Reducer->(Middleware)->Store->(State)->View. Подобно State Machines, вы можете запускать побочные эффекты с помощью Middlewares в Redux. Вы можете ограничить/запретить переходы состояний, если хотите. В отличие от State Machine, Redux обеспечивает однонаправленный поток данных, чистый ! функции редуктора, неизменяемые объекты состояния, единое наблюдаемое состояние приложения.