FSM вместо if/else в backend — мой опыт

На производственной практике писал backend-систему управления проектами — и упёрся в проблему состояний 🤔

У проекта есть этапы: дизайн → разработка → QA → релиз → поддержка → архив И просто так прыгать между ними нельзя

Например: — нельзя начать разработку без утверждённой спецификации — некоторые переходы требуют причину — все изменения нужно фиксировать

Сначала хотел решать это через if/else… но быстро понял, что логика размажется по коду и станет неуправляемой

👉 В итоге реализовал конечный автомат (FSM) через библиотеку Stateless Вот пример перехода в домене: public ProjectTransitionResult StartDevelopment() { if (!HasApprovedSpecification()) return ProjectTransitionResult.Fail("No approved specification"); return Execute(ProjectTrigger.StartDevelopment); }

А внутри — единая точка управления переходами: if (!machine.CanFire(trigger)) return ProjectTransitionResult.Fail( $"Cannot execute {trigger} from {Stage}");

Теперь: — допустимые переходы описаны явно — бизнес-правила живут в домене, а не в контроллерах — каждый переход фиксируется в истории — ошибка перехода — это не баг, а контролируемый результат

📌 FSM встроил прямо в доменную модель (Clean Architecture) Параллельно применил: — Clean Architecture (Роберт Мартин) — CQRS + MediatR (Vertical Slice) — ASP.NET Core + PostgreSQL — JWT + роли

📚 Что повлияло на решения: — «Чистая архитектура» — Роберт Мартин — «Гид по Computer Science» — Уильям Спрингер — доклады с DotNext (идея использовать FSM вместо условий)

📂 Проект: https://github.com/markld-ui/RedRamkaPractice

Что понял: FSM сильно упрощает работу с бизнес-логикой — ты явно видишь все переходы и ограничения Но платишь за это более сложным входом и проектированием на старте.

Интересно, как вы обычно решаете такие задачи с состояниями в проектах?🤔