Что такое Action в паттерне MVI (Model-View-Intent)?

«Что такое Action в паттерне MVI (Model-View-Intent)?» — вопрос из категории Паттерны, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В архитектуре MVI (Model-View-Intent) Action (или Intent) — это иммутабельный объект-сообщение, который описывает намерение пользователя или системы изменить состояние приложения. Это единственный способ для View инициировать изменения.

Роль в однонаправленном потоке данных:

  1. View наблюдает за пользовательскими событиями (клики, ввод) и преобразует их в объекты Action.
  2. Intent (или обработчик) принимает поток Actions, применяет к ним необходимую бизнес-логику (например, асинхронные запросы) и выдает новые намерения для изменения Model.
  3. Model (состояние) обновляется на основе этих намерений, и новое состояние передается обратно во View для рендеринга.

Пример реализации на C# (упрощенно):

// 1. Определяем Actions как типы (часто используют record или sealed class)
public abstract record CounterAction;
public record IncrementAction(int Step = 1) : CounterAction;
public record DecrementAction(int Step = 1) : CounterAction;
public record LoadDataAction : CounterAction;

// 2. Модель (состояние)
public record CounterState(int CurrentCount, bool IsLoading);

// 3. Обработчик (Intent/Reducer), который создает новое состояние на основе Action
public static CounterState Reduce(CounterState currentState, CounterAction action)
{
    return action switch
    {
        IncrementAction inc => currentState with { CurrentCount = currentState.CurrentCount + inc.Step },
        DecrementAction dec => currentState with { CurrentCount = currentState.CurrentCount - dec.Step },
        LoadDataAction => currentState with { IsLoading = true },
        _ => currentState // Игнорируем неизвестные действия или возвращаем текущее состояние
    };
}

Ключевые принципы для Action в MVI:

  • Иммутабельность: Каждый Action — это неизменяемый "пакет" данных.
  • Детерминированность: Для одного и того же Action и текущего состояния результат должен быть предсказуем.
  • Серийность: Actions обрабатываются последовательно, что упрощает отладку и воспроизведение состояния.
  • Отсутствие побочных эффектов: Сами Actions не содержат логики. Побочные эффекты (запросы к API) обрабатываются отдельно (например, в Middleware или сайд-эффект менеджере).