← Назад к вопросам

Что такое State machine?

1.0 Junior🔥 271 комментариев
#Асинхронность и многопоточность#Основы C# и .NET

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое State Machine (Конечный автомат)?

State Machine (машина состояний, конечный автомат) — это математическая абстракция и архитектурный паттерн, используемый для моделирования поведения системы, которое может находиться в одном из конечного числа состояний (states) в каждый момент времени. Переходы между состояниями происходят в ответ на события (events) или входные данные, причём каждый переход может сопровождаться определёнными действиями (actions). Это фундаментальная концепция в computer science, широко применяемая в backend-разработке на C# для управления сложной бизнес-логикой, workflow, обработки данных и коммуникаций.

Ключевые компоненты State Machine

  • Состояния (States): Дискретные режимы работы системы (например, Idle, Processing, Completed, Error). В каждый момент времени система находится ровно в одном состоянии.
  • События (Events): Внешние или внутренние триггеры, инициирующие попытку перехода (например, StartProcess, DataReceived, Timeout).
  • Переходы (Transitions): Правила, определяющие, в какое состояние система перейдёт из текущего при наступлении события. Часто описываются как (CurrentState, Event) -> NextState.
  • Действия (Actions): Операции, выполняемые при входе в состояние, выходе из него или во время перехода (например, логирование, вызов API, изменение данных).
  • Начальное состояние (Initial State): Состояние, в котором система начинает работу.

Пример на C#: простая State Machine для заказа

Рассмотрим реализацию паттерна "состояние" для управления статусом заказа в e-commerce приложении.

// Определение состояний заказа
public enum OrderState
{
    Pending,
    Approved,
    Shipped,
    Delivered,
    Cancelled
}

// Класс State Machine для заказа
public class OrderStateMachine
{
    private OrderState _currentState;

    public OrderState CurrentState => _currentState;

    public OrderStateMachine()
    {
        _currentState = OrderState.Pending; // Начальное состояние
    }

    // Метод для выполнения перехода по событию
    public bool TryTransition(OrderEvent orderEvent)
    {
        try
        {
            var nextState = GetNextState(_currentState, orderEvent);
            if (nextState != _currentState)
            {
                ExecuteTransitionActions(_currentState, nextState, orderEvent);
                _currentState = nextState;
                Console.WriteLine($"Order state changed to {_currentState} due to {orderEvent}");
                return true;
            }
            return false;
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"Transition failed: {ex.Message}");
            return false;
        }
    }

    // Определение правил переходов
    private OrderState GetNextState(OrderState current, OrderEvent orderEvent)
    {
        return (current, orderEvent) switch
        {
            (OrderState.Pending, OrderEvent.Approve) => OrderState.Approved,
            (OrderState.Pending, OrderEvent.Cancel) => OrderState.Cancelled,
            (OrderState.Approved, OrderEvent.Ship) => OrderState.Shipped,
            (OrderState.Approved, OrderEvent.Cancel) => OrderState.Cancelled,
            (OrderState.Shipped, OrderEvent.Deliver) => OrderState.Delivered,
            _ => throw new InvalidOperationException(
                $"Invalid transition from {current} on event {orderEvent}")
        };
    }

    // Выполнение действий при переходе
    private void ExecuteTransitionActions(OrderState from, OrderState to, OrderEvent orderEvent)
    {
        // Пример действий: логирование, уведомления, обновление БД
        if (to == OrderState.Shipped)
        {
            Console.WriteLine("Sending shipping notification to customer...");
        }
        else if (to == OrderState.Cancelled)
        {
            Console.WriteLine("Initiating refund process...");
        }
    }
}

// События, инициирующие переходы
public enum OrderEvent
{
    Approve,
    Cancel,
    Ship,
    Deliver
}

Преимущества использования State Machine в C# Backend

  • Управление сложной логикой: Упрощает обработку многошаговых процессов (например, платежи, onboarding пользователей).
  • Предотвращение недопустимых состояний: Жёстко контролирует возможные переходы, исключая "невозможные" сценарии (например, отмена доставленного заказа).
  • Повышение тестируемости: Состояния и переходы можно тестировать изолированно с помощью unit-тестов.
  • Улучшение поддерживаемости: Логика состояний инкапсулирована в одном месте, а не размазана по кодовой базе.
  • Визуализация workflow: Диаграммы состояний (state diagrams) служат отличной документацией.

Библиотеки для State Machine в C#

Для production-решений вместо "ручной" реализации часто используются специализированные библиотеки:

  • Stateless: Популярная легковесная библиотека для создания конечных автоматов. Позволяет описывать состояния, события и переходы декларативно.
  • Automatonymous: Часть MassTransit, ориентирована на workflow в распределённых системах.
  • StateSharp: Современная библиотека с поддержкой async/await и dependency injection.

Пример с библиотекой Stateless

using Stateless;

public class Order
{
    private readonly StateMachine<OrderState, OrderEvent> _machine;

    public Order()
    {
        _machine = new StateMachine<OrderState, OrderEvent>(OrderState.Pending);

        _machine.Configure(OrderState.Pending)
            .Permit(OrderEvent.Approve, OrderState.Approved)
            .Permit(OrderEvent.Cancel, OrderState.Cancelled);

        _machine.Configure(OrderState.Approved)
            .Permit(OrderEvent.Ship, OrderState.Shipped)
            .Permit(OrderEvent.Cancel, OrderState.Cancelled)
            .OnEntry(() => Console.WriteLine("Order approved, preparing for shipment"));

        _machine.Configure(OrderState.Shipped)
            .Permit(OrderEvent.Deliver, OrderState.Delivered);
    }

    public void ProcessEvent(OrderEvent orderEvent) => _machine.Fire(orderEvent);
    public OrderState CurrentState => _machine.State;
}

Применение в Backend-разработке

  • Workflow engine: Обработка бизнес-процессов (согласование документов, цепочки задач).
  • Коммуникационные протоколы: Реализация сетевых протоколов (например, WebSocket, TCP сессии).
  • Игровая логика: Управление состояниями персонажей или игровых объектов.
  • UI-навигация: Контроль flow в wizard-интерфейсах (хотя чаще на frontend).

Заключение: State Machine — это мощный паттерн для структурирования сложного поведения систем. В C# backend он помогает создавать предсказуемый, поддерживаемый и отказоустойчивый код, особенно когда бизнес-логика включает много состояний и переходов. Выбор между самостоятельной реализацией и использованием библиотек зависит от сложности требований и масштаба проекта.

Что такое State machine? | PrepBro