Конечные автоматы (FSM) Просто о сложном
Простое и наглядное введение в конечные автоматы (FSM) для разработчиков. Разберёмся, зачем они нужны, где применяются, и как реализовать FSM в коде — от теории до практики.
468 открытий3К показов

Часто встречаются задачи, где нужно управлять поведением объекта или системы, которое зависит от текущего режима работы и происходящих событий. Например, кнопка может быть нажата или отпущена, пользователь может быть авторизован или нет, заказ может находиться в стадии обработки, доставки или завершения. Для элегантного решения таких задач существует мощный паттерн — конечный автомат состояний (Finite State Machine, FSM).
Эта статья предназначена для программистов, которые хотят понять, что такое FSM и как их строить, используя практический пример на JavaScript.
Что такое FSM?
Если совсем просто, конечный автомат — это модель, описывающая поведение системы, которая может находиться в одном из нескольких предопределенных состояний. Система переходит из одного состояния в другое при наступлении определенных событий. Каждый такой переход называется транзакцией или переходом.
Давайте представим обычный светофор
Какие бывают состояния у светофора?
- Красный
- Желтый
- Зеленый
Какие бывают события у светофора?
- Прошло определенное время (таймер сработал).
Какие бывают переходы (транзакции) у светофора?
- Из «Красный» по событию «таймер_красного_истек» -> в «Желтый» (или «Красный+Желтый»).
- Из «Желтый» по событию «таймер_желтого_истек» -> в «Зеленый».
- Из «Зеленый» по событию «таймер_зеленого_истек» -> в «Желтый» (мигающий или постоянный).
Эта простая концепция помогает структурировать сложную логику, делая код более читаемым, предсказуемым и легким в поддержке. Вместо громоздких конструкций if-else появляется четкая карта состояний и переходов.
Основные компоненты FSM
Состояния (States): Конкретные режимы, в которых может находиться система (например, idle, loading, active, error).
События (Events): Триггеры, которые инициируют изменение состояния (например, buttonClick, dataLoaded, timeoutOccurred).
Переходы (Transitions): Правила, определяющие, из какого состояния в какое можно перейти при наступлении конкретного события.
Действия/Коллбэки (Actions/Callbacks): Фрагменты кода, которые выполняются при входе в состояние, выходе из него или во время перехода.
Разбираем код на части: Класс HFSM для создания автоматов
Для построения FSM мы будем использовать предоставленный JavaScript класс HFSM (Hierarchical Finite State Machine). «H» означает «иерархический», что позволяет вкладывать одни автоматы в состояния других, но об этом чуть позже.
Ключевые моменты конструктора constructor() HFSM:
- config.initial: Имя начального состояния, в котором автомат находится сразу после создания.
- config.transitions: Объект, где ключи — это имена состояний, а значения — массивы объектов, описывающих возможные переходы. Каждый объект перехода имеет вид { event: “имя_события”, to: "имя_целевого_состояния” }.
- config.callbacks: Объект с функциями, которые будут вызываться в определенные моменты жизненного цикла FSM (например, onAfterLogin после успешного события login, или onStateChange при любом изменении состояния).
- config.states: Используется для определения вложенных FSM, делая автомат иерархическим.
Важные методы:
- trigger(event, …args): Основной метод для взаимодействия с FSM. Он принимает имя события и опциональные аргументы. Если для текущего состояния и указанного события есть разрешенный переход, автомат меняет свое состояние и выполняет связанные коллбэки.
- can(event): Позволяет проверить, допустимо ли указанное событие в текущем состоянии FSM.
FSM в действии — Примеры
Рассмотрим, как этот класс используется для управления более сложной логикой на примерах.
1. Управление логикой звонков callFSM
Этот FSM описывает состояния и переходы, связанные с процессом звонка в приложении.
Предположим, пользователь инициирует исходящий звонок контакту «Alice». Код приложения вызовет:
- callFSM находится в состоянии idle.
- Он находит переход для события outgoingCall, который ведет в состояние checkCamera.
- Состояние изменяется на checkCamera.
- Выполняется коллбэк onAfterOutgoingCall(«idle», «checkCamera», «Alice»).
- Внутри коллбэка выполняем свою логику
2. Управление состоянием камеры cameraFSM
Это более простой FSM, отвечающий исключительно за логику работы камеры.
Таким образом мы можем создавать сколько угодно fsm конструкции.
Преимущества использования FSM
- Наглядность и читаемость: Структура состояний и переходов четко описывает логику.
- Уменьшение количества ошибок: Явное определение состояний и переходов снижает риск непредвиденного поведения.
- Простота расширения: Добавление новых состояний или событий обычно не требует значительной переработки существующего кода.
- Улучшенная тестируемость: Каждое состояние и переход можно тестировать изолированно.
- Управление сложностью: Особенно полезно для систем с множеством взаимосвязанных состояний.
Заключение
Конечные автоматы состояний — это не просто теоретическая концепция, а мощный и практичный инструмент в арсенале программиста. Они помогают вносить порядок в сложную логику управления состоянием, делая код более структурированным, предсказуемым и легким для сопровождения. Представленный класс HFSM и примеры показывают, как можно реализовать и использовать FSM в JavaScript для решения реальных задач.
468 открытий3К показов