Архитектура веб-приложения для SaaS
Ключевые тезисы:
- MVC (Model-View-Controller) — базовая архитектура для разделения ответственности.
- HMVC (Иерархический MVC) — модульная организация кода для больших приложений.
- Контексты (Front, App, Admin, API) — логическое разделение функционала по типам пользователей.
- Сервисы — вынос повторяющейся бизнес-логики, используемой в нескольких местах.
- Провайдеры — абстракция для работы с внешними сервисами, обеспечивающая легкую замену.
Как работает MVC (Model-View-Controller)
MVC — это паттерн, разделяющий приложение на три роли с разной ответственностью.
Пример цикла запроса (страница истории платежей):
- Роутинг (Route): Запрос по адресу
/billing/historyпередаётся контроллеруBillingHistoryController, методуindex. - Контроллер (Controller): Выступает "дирижёром". Решает, какие данные нужны (платежи, информация о подписке) и обращается к соответствующим моделям.
- Модель (Model): Слой работы с данными. Например,
PaymentModelзнает, как получить платежи из базы данных. - Вид (View): Получает данные от контроллера и превращает их в HTML-страницу (таблицы, кнопки).
Преимущества разделения: Изменение шаблона (View) не затрагивает логику работы с данными (Model), и наоборот. Легче ставить задачи и изолировать изменения.
HMVC: Модульная архитектура для SaaS
Когда приложение растёт (регистрация, личный кабинет, админ-панель), всё в одной папке становится нечитаемым.
Решение — HMVC:
- Приложение делится на независимые модули (например,
Auth,Users,Billing). - Каждый модуль содержит свой собственный MVC внутри (свои контроллеры, модели, роуты, шаблоны).
Главное преимущество для AI-кодинга: ИИ, получая задачу в рамках конкретного модуля, изучает его структуру и пишет код, который вписывается в проект, не ломая остальное.
Четыре контекста приложения
Один модуль может работать в разных контекстах (логических зонах):
- Front
: Публичный сайт (лендинг, блог). Доступен без авторизации. - App
: Личный кабинет зарегистрированного пользователя (дашборд, настройки). - Admin
: Панель администратора (управление пользователями, аналитика). - API
: REST API, возвращает JSON. Используется для мобильных приложений и интеграций.
Пример: Модуль User живёт в контексте Admin (админ видит всех пользователей) и в App (пользователь редактирует свой профиль). Используются разные контроллеры и шаблоны, но одна модель User.
Сервисы: Централизация бизнес-логики
Проблема: Одна и та же логика (например, регистрация пользователя) нужна в нескольких контекстах (Front, Admin, API). Если дублировать код, при изменении придётся правлять его везде, что ведёт к багам.
Решение — Сервисы:
- Сервис — это класс с бизнес-логикой, которая не принадлежит конкретной модели (например,
UserRegistrationService). - Он инкапсулирует сложные операции: валидация, вызов моделей, отправка писем, создание настроек.
- Все контроллеры вызывают один сервис. Изменения вносятся в одном месте.
Правило: Создавайте сервис, когда логика нужна в нескольких местах или когда действие затрагивает несколько моделей.
Провайдеры: Абстракция для внешних сервисов
Проблема: Код напрямую обращается к внешнему сервису (например, Mailgun). При его замене нужно переписывать множество мест.
Решение — Провайдеры:
- Провайдер — это прослойка-абстракция. Весь код приложения говорит "отправь письмо", не зная, через какой сервис.
- Конкретная реализация (Mailgun, SendGrid) описывается в одном месте.
- Для замены сервиса меняется только конфигурация провайдера.
Практический пример: Модуль API-ключей
Создан реальный модуль для управления API-ключами в проекте, применяющий все рассмотренные концепции:
- Модуль
ApiKeysс контекстами App (пользователь создаёт ключи) и Admin (админ видит все ключи). - Модель
ApiKeyдля работы с данными. - Сервис/Фильтр для аутентификации и проверки лимитов запросов.
- Безопасное хранение: В базе сохраняется только хэш ключа, оригинал показывается пользователю единожды.
Как работает аутентификация:
- Запрос к защищённому эндпоинту проходит через фильтр.
- Фильтр извлекает ключ из заголовка, ищет его хэш в базе.
- Проверяет активность ключа и лимиты запросов/расходов.
- При успехе — пропускает запрос и увеличивает счётчик. При ошибке — возвращает 401 (нет авторизации) или 429 (превышен лимит).
Выводы:
Для создания масштабируемого и поддерживаемого SaaS-приложения необходима чёткая архитектура:
- MVC как основа.
- HMVC для модульной организации.
- Разделение на контексты (Front, App, Admin, API).
- Вынос общей логики в сервисы.
- Использование провайдеров для абстракции внешних интеграций.
Эта структура делает код предсказуемым, облегчает разработку с помощью AI и снижает количество ошибок.