Шаблоны для использования React с автоматами станов на основе Statechart

1656568592 shablony dlya ispolzovaniya react s avtomatami stanov na osnove statechart

от Шона Маккея

SjSgltemLEUI9D4oLDecB1Noz9pZVoWBKyiu
Фото Эндрю Ридли на Unsplash

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

Но если диаграммы состояний являются прекрасным решением для управления интерфейсом пользователя и состоянием в Javascript (JS), почему за ними нет большего импульса?

Одной из главных причин, почему диаграммы состояния не выросли в популярности в интерфейсном мире, состоит в том, что лучшие методы еще не созданы. Не совсем понятно, как использовать конечные автоматы с популярными библиотеками пользовательского интерфейса на основе компонентов, такими как React, Vue или Angular.

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

Машина диаграмм состояния

Диаграммы состояний работают как для визуального дизайна, так и базовый код для конечного автомата на основе графов.

Имейте в виду, что мы только начали использовать диаграммы состояния с JS, и, возможно, следует поэкспериментировать с разнообразными библиотеками или даже разработать собственные. При этом XState лидирует в наборе машинных библиотек состояний в JS.

7jucyNQr2bs02ta20zRnBRj-uUQ0DvKFoLLk
https://gist.github.com/ShMcK/769a179f89f1d7db1f83363cc2e42399

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

eUlLxIJzgceeXmtnFNwZVl9ZdPtOJm5GUFAx

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

q3OYT9hd3E2M93-qLHciSoHceVwcC5ELrs7e

Теперь, когда у нас есть представление о том, что делает XState, давайте посмотрим, чего он не делает.

Слоган XState: «автоматы конечных состояний без состояния и диаграммы состояний».

Итак, что значит быть государственной машиной без гражданства?

Машины без состояния

Автоматы без гражданства предлагают безупречный план для управления состоянием – своего рода «свернуть собственное» решение, не определяющее, где и как сохранять состояние в вашей программе.

Подобно презентационному компоненту, машина без состояния состоит из чистых функций, неизменная и не поддерживающая никакого состояния. Он не отслеживает прошлое, настоящее или будущее, но его можно использовать для вычисления каждого.

Управлять своим состоянием можно так же просто, как сохранить его в локальном переменном состоянии.

kAqxO0cq9qT-nMGfnhlsFaSxINVkpP233WSb

Автоматы без состояния не дают вам многое из коробки. Чтобы инициировать переход, мы должны передавать узел текущего состояния, чтобы найти следующий. XState может сообщать вам, какие действия следует выполнять при каждом изменении состояния, но вам придется самостоятельно управлять этими действиями.

Если вас интересует более полное решение, подумайте о создании своего конечного автомата государственный.

Состоянные машины

Машина с определением состояния отслеживает положение вашего узла на графике состояния и управляет запуском действий. Нет необходимости передавать текущее состояние при переходах – оно отслеживает ваш текущий узел состояния.

D1FxAQN9JgcjK9TwGl1TxXHUewyTFZBAIvn9

Как результат, приведенный выше экземпляр машины с определением состояния:

  • определяет положение зеленого состояния в «Звонок»
  • ограничивает возможные фиолетовые активные события перехода к CANCEL или SNOOZE
  • выстреливает startRing действия при поступлении
  • выстреливает stopRing действия по выходу из гос

Конечно, существует более одного способа создать машину с определением состояния. Мы возвращаемся к вопросу, где управлять состоянием:

  • в пределах существующего состояния компонента?
  • в подключенном автомате?

Давайте рассмотрим некоторые шаблоны дизайна с примерами, начиная с компоненты, сохраняющие состояние.

Компоненты, сохраняющие состояние

Компонент с сохранением состояния, как вы можете представить себе, управляет состоянием внутри компонента или внутри компонента высшего порядка обертки. В React это будет как state. Сохранение состояния в библиотеке пользовательского интерфейса гарантирует, что изменения не будут пропущены, и приведет к повторному визуализации.

Это подход библиотеки под названием React-Automata, которая использует компонент высшего порядка, инициированный withStatechart.

6hX-DEHCmfZZbMsyp8bE4MyZgqmKr-BmqfR3

React-Automata предлагает несколько шаблонов для использования диаграмм состояния с компонентами:

  • состояние от реквизита
  • условное воспроизведение из контекста
  • состояние от действий

Мы рассмотрим любую модель и рассмотрим плюсы и минусы.

Государство от реквизита

Передача состояния непосредственно в компоненты кажется наиболее очевидным решением.

CfqmdxiglBKlVIBCSOBMrKoSnnjvqYuwsBtD

В React-Automata состояние можно передать, обратившись к нему на machineState prop – ссылка на фактический конечный автомат.

Gr113rIoWhqeyyCvUT3GSjebtKN4y14VtQCg

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

Учитывайте, что диаграмма состояний и компоненты могут обеспечить четкое разделение, поскольку они решают разные проблемы:

  • диаграммы состояния: когда случаются вещи, например, переход в состояние, запущенные действия
  • компоненты: как и что происходит, например, просмотр, взаимодействие пользователя

Кроме того, можно отключить компонент от конечного автомата путем условного рендеринга со значением по умолчанию без воспроизведения.

FzXtUh2ITWYn0AePrsqZZ3Tme-8hcrwfnwhh

Конечно, должен быть более естественный способ настроить условное воспроизведение без необходимости преобразовывать все ваши визуализации в if/else и switch заявления.

Условное воспроизведение из контекста

Состояние, к которому обращается контекст, не нужно передавать напрямую.

I4yIlaK9q13fHzI7H20RN7XcyM0KbCgtgO6d

React-Automata предоставляет шаблон для условного воспроизведения дочерних компонентов с помощью контекста React и a <State> компонент. Заметьте, чтоt the Свойство value может совпадать со строчкой, массивом строк или даже шаблоном на основе шара.

9g7rEjSlDp5DZtsunVJMkr4lnLQzBzglx3k4

Если значение состояния соответствует Ringingдети внутри State компонент будет воспроизведен. Иначе ничего.

Состояние по контексту может помочь уточнить количество возможных комбинаций вида конечного состояния. Как и в случае выше, понятно, что есть только две возможные конфигурации.

Если конфигурации просмотра начинают выходить из-под контроля, React-Automata предлагает шаблон рендеринга, который передается логическим значением на основе значения.

JR-iT393EkkGzs5vqgMcMdI1LnAbiE9Bze3-

Аналогично можно условно отображать на основе действий контекста.

EVHZhlEFxplZquVI9C9pihSIEW1jQHhsYTkl

Условное воспроизведение на основе состояния или действий поддерживает связь между диаграммой состояний и компонентами, но менее явно через контекст. Как вы можете предоставить компонентам их изолированное состояние, кроме диаграмм состояний?

Состояние от действий

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

xe2pZXijfRO5YUV19NX1LBZfMdUONssLBqnY

React-automata проверяет методы компонента и вызывает функции, если имена соответствуют запускаемым действиям.

Как пример, действие onEntry startRing запускается, когда входит государственная машина Ringingвызывая AlarmClock состояние изменить на ringing. При выходе из Ringing государство, stopRing уволен, и ringing установлено на false.

mrkROREfV5flyHGYngYrWHyFSWVHSNS-vrdq

Заметьте, что хотя эти методы вызываются с параметрами, они уже имеют доступ к тому, что им нужно machineState через реквизит.

Использование внутреннего состояния компонента, управляемого с помощью действий, приводит к сильному отделению компонентов от диаграмм состояний. Однако это также может создать определенный беспорядок или путаницу в компонентах. Неясно, как и когда будут вызваны методы без изучения названий действий в диаграмме состояний. По этой причине я часто называю свои действия и методы enterX или exitX чтобы было четко понятно, почему и откуда их увольняют.

Внешние автоматы состояния

Другой вариант, который стоит рассмотреть – это сохранение состояния за пределами вашей рамки интерфейса пользователя. Как и в других библиотеках управления состоянием, таких как Redux, компоненты могут быть подключены к внешнему конечному автомату и обновлены с помощью событий «при изменении состояния» и «при действии».

Cpdc3lKa2eFWX82Vu7SoPHXmcb4mWTpKAY9b

Например, XStateful – это обертка вокруг XState, которая обрабатывает состояние, переходы, излучение событий, действия инициирования и т.д.

8KMPv6PSbvRMQXebFnVL6PQKY6nlJn40TUHC

XStateful хорошо работает с коннектором React под названием XStateful-React.

FBxnxH0x9tzYnBpMJvtyLgndKtMlhZxCgPrw

XStateful-React имеет много общего с React-Automata. Но есть по крайней мере одно существенное отличие – экземпляр конечной машины не управляется никаким компонентом.

vjYPif3blpUKKDprAMfUigXfz5r1vpyPqzfG

Итак, как внешнее состояние от редукторов работает в XStateful?

Состояние и данные

Программы часто требуют больше, чем просто узел состояния в графе состояния — они также нуждаются в данных. Часто эти данные нужно синхронизировать между компонентами, что может быть разочаровано, если их нужно передавать от общего родительского.

Есть популярные решения для синхронизации данных, таких как Redux или моя оболочка управления состоянием для Redux. К сожалению, они плохо работают со многими обертками состояния, такими как React-Automata, из-за открытой проблемы с передачей ссылок в React Redux (см. эту открытую проблему с connect() и React.forwardRef).

Полное решение для состояния должно управлять как состоянием, так и данными.

XStateful предлагает именно такое решение состояния и данных, используя шаблон редуктора состояния, подобный Redux.

8xMXiOZdWjR-P3ctNVeMB4LE4v7ZvPTUuybt

Абоненты конечного автомата прослушивают и обновляют изменения на основе действий, выпущенных конечным автоматом. Обратите внимание, что XState ссылается на данные как расширенное состояниеили extstate.

hdrk3HqBbfBkNfd2gWC1VEKHSj1Py-isMhIA

Этот конкретный шаблон Reducer может показаться незнакомым, однако он активно используется в таких проектах как ReasonReact.

К данным также можно получить доступ в условной визуализации объекта cond.

4jrU5i-bzBirWwqhn3ojmLpGkk3peLjRY8BW

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

Эти данные можно передать в ваш компонент с помощью рендерингового шаблона.

r63dar8rwDffa7lnxUoUjYpeUlY0gGfl8YTT

Существует меньше потребности в инструментах управления состоянием, например Redux, если данные можно хранить в полноценном состоянии, например XStateful.

Тестирование

Составные автоматы также предлагают лучший путь для тестирования интерфейса.

Детерминированная природа конечных автоматов создает возможность упрощенного тестирования интерфейса.

В React-Automata вы можете автоматически генерировать тесты снимков с помощью testStatechartметод, принимающий конфигурацию XState и компонент.

32aHtwD8mghMTy8m1zwteefbxEX8wSSDhWgl

testStatechart проходит через график состояния и создает тест снимков Jest для каждой возможной конфигурации компонента. Он включает и выключает ваши разные <State />, <Компоненты Action, ведущие к записи всех возможных условных комбинаций визуализации.

Devtools

Devtools играют активную роль в том, что делает библиотеку удобной для разработчиков – отладка может быть самой сложной или простой частью вашей работы.

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

q9HFedJVnw4i1qaVE26n3x9lB03JgZ0jfBfE

XState предлагает совершенно новый набор переменных для отслеживания. Рассмотрим следующий пример Эрика Могенсена о типах информации, которую может отслеживать отладчик XState.

culeh91to9lyS13adQMF0gyawStWoPWeAmpR

Это не означает, что инструменты разработки конечной машины должны смотреться как наши существующие инструменты разработки. Инструменты разработки конечной машины дают возможность для более визуальной отладки.

Вывод

Хотя мы все еще находимся в начале развития диаграмм состояний в JS, есть достаточно вариантов, чтобы начать разработку приложений поверх XState. Мы можем учиться на этих моделях разработки для улучшения доступных библиотек и создания инструментов для поддержания огромного потенциала визуального программирования.

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

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *