Эволюция архитектурных паттернов в бэкенд-разработке: от MVC к микросервисам
Проблемы традиционного MVC


- Интеграция IoC и DI – современные MVC-фреймворки (например, ASP.NET MVC, Laravel, Spring MVC) предлагают встроенные контейнеры для внедрения зависимостей, что повышает модульность и облегчает тестирование;
- Чёткое разделение представлений и контроллеров – использование View Models, шаблонов и сервисов позволяет структурировать взаимодействие между слоями;
- Расширяемость за счёт дополнительных слоёв – при необходимости MVC можно дополнить слоями бизнес-логики, доменной модели и инфраструктуры, что делает архитектуру более гибкой.
- Распыление бизнес-логики – даже при наличии сервисного слоя и репозиториев, логика бывает распределена между контроллерами, моделями и другими компонентами, что усложняет её поддержку;
- Сложности масштабирования – в ходе роста проекта управление зависимостями и изменение функционала могут приводить к запутанности кода, что требует частого рефакторинга;
- Ограничения в тестировании – несмотря на использование DI, тесное взаимодействие между слоями иногда приводит к необходимости проводить преимущественно интеграционные тесты, а не модульные.
Этапы эволюции архитектуры
Переход к Domain-Driven Design (DDD)

- Снижение сложности за счет четкого описания предметной области. У каждого домена есть область ответственности, и его взаимодействие ограничено определёнными границами (Bounded Contexts);
- Логика изменения и добавления новых функций легко вписывается в уже существующие доменные модели, если они правильно структурированы;
- Внесение изменений в логику требует глубокого понимания доменных сущностей и их взаимосвязей;
- Если система построена с использованием DDD, то изменения вписываются в существующий контекст, минимизируя риск появления хаотичной логики;
- Добавление новых функций происходит через создание новых доменов или расширение текущих контекстов.
Переход на Modular Monolith

- Сложность уменьшается через разбивку системы на модули с чёткими интерфейсами, каждый из которых можно разрабатывать и тестировать независимо от других;
- Если модули хорошо изолированы, это снижает риск «разлома» других частей системы при внесении изменений;
- Модульная архитектура хорошо подходит для перехода к микросервисам, так как каждый модуль может стать им;
- Изменение существующих модулей требует проверки взаимодействия между ними, но при правильной архитектуре это становится менее рискованным;
- Поддержка кода упрощена за счёт изолированных областей.
Выбор подхода
Внедрение микросервисов и SOA



Практический опыт и примеры из проектов
Кейс 1: переход на современную MVC-структуру
- Баги после перераспределения логики – исправление ошибок, появившихся вследствие изменения архитектурных принципов;
- Давление со стороны бизнеса – ожидание более быстрого процесса, что осложняло итерации и отладку;
- Разделение логики по слоям и сервисам – необходимость минимизировать связанность и достичь атомарности.
Кейс 2: путь через компромиссы
- Обучение и адаптация – язык Go был новым для всех. Был нанят лидер разработки и организованы курсы переподготовки для PHP-разработчиков. Однако недостаток опыта привел к несогласованности данных между системами, крашам и потерям выручки;
- Бутылочные горлышки – высокая нагрузка выявляла критические участки, требующие немедленного исправления;
- Стресс команды – множество багов, нестабильность инфраструктуры и обилие проблем создавали ощущение приближающегося провала.
Рекомендации по выбору архитектурного паттерна
- Тестируемость – архитектура должна позволять легко покрывать функциональные блоки модульными и интеграционными тестами;
- Читаемость и поддерживаемость кода – структурированный код упрощает внесение изменений и снижает вероятность ошибок;
- Переиспользование логики – разделение функционала на атомарные компоненты помогает избежать дублирования и ускоряет разработку новых функций;
- Гибкость и масштабируемость – архитектура должна быть способна адаптироваться к изменяющимся требованиям проекта, позволяя поэтапно вводить новые возможности.
- Цель и область применения – DDD фокусируется на моделировании бизнес-логики, а SOA и Modular Monolith – на структурировании приложения с точки зрения развертывания и управления зависимостями;
- Развертывание – SOA подразумевает независимое развертывание сервисов, в то время как Modular Monolith развёрнут как единое целое, несмотря на внутреннюю модульную структуру. DDD же не диктует способ развертывания;
- Коммуникация – в SOA сервисы взаимодействуют по сети (например, через REST или SOAP), что влечёт за собой вопросы сетевой задержки, надёжности и безопасности. Modular Monolith не имеет таких проблем, так как модули вызывают друг друга напрямую внутри одного процесса;
- Управление сложностью – DDD помогает управлять сложностью бизнес-логики через чёткое разделение доменной модели на контексты. SOA и Modular Monolith, напротив, структурируют систему с точки зрения технического разделения и развертывания.