png png
к ленте

KISS Architecture. От микросервиса до монолита

Апрель'19

Андрей Копылов, наш технический директор, рассказывает, какой подход к проектированию архитектуры приложений использует команда веб-разработчиков Ареал, и, чем KISS Architecture, его собственная разработка, так хороша.

Существует масса подходов к проектированию архитектуры приложения. MVC, DDD, Clean Architecture и множество других.

MVC хорошо подходит для маленьких приложений. При попытке масштабирования MVC превращается в самую распространенную архитектуру в мире IT — Большой ком грязи.

DDD отличная архитектура, но ее никто не понимает. Разве что сам создатель и пара архитекторов. Цель же архитектуры в том, чтобы она была понятна каждому разработчику.

Clean Architecture отличная архитектура, но ее полная реализация имеет смысл для огромных приложений. Для малых и средних мне она показалась слишком сложной.

Современные тенденции — переход к сервисам и микросервисам — на этом фоне Clean Architecture становится чересчур тяжеловесной.

Казалось бы тогда давайте возьмем MVC для микросервиса и на этом и остановимся. Но нет, такой велосипед нам не подходит.

Составляющие

Велосипед для проектов в нашем агентстве собран из запчастей от разных архитектурных подходов.

Вот компоненты, которые нужны для создания понятной и удобной структуры:

  • Routers
  • Controllers
  • Views
  • Services
  • Models

Слои

Router

Router отвечает за маршрутизацию запросов. Размер роутера и их количество косвенно говорит о размере вашего приложения. Для большого монолитного приложения может быть более одного слоя роутеров.

Router присутствует в любой архитектуре, но часто в неявном виде. А поскольку явное лучше неявного, то стоит его вытащить наружу — сделать составной частью архитектуры.

Controller

Контроллер является прослойкой между роутером и сервисами. Бизнес логики в контроллере быть не должно.

Каждый контроллер управляет только одной сущностью. Если нужно больше сущностей, то нужно добавить еще один контроллер.

Количество и размер контроллеров косвенно говорит о размере вашего приложения. Вертикальный слой под контроллером можно выделить в отдельный микросервис.

Views

View находится в одном слое с контроллером, отвечает за конечное отображение данных. Контроллер после получения данных из сервиса передает данные во View и возвращает View для отображения.

В предельном случае View представляет собой JSON, XML и подобные форматы.

Services

Только Сервис может содержать бизнес логику. Сервис обычно обращается только к одной модели. Сервис может вызвать другой сервис.

Слой сервисов разделяем на Commands и Queries (команды и запросы). Это стандартный подход для CQRS.

Один сервис выполняет только одну функцию. Приватных функций может быть сколько угодно, а публичная только одна. Название сервиса начинается с глагола. Примеры: GetUsers, GetPostById, UpdateUser, PublishPost. Именно название сервиса намекает на правильное разделение функционала.

В Queries помещаем сервисы, которые не изменяют базу данных. Query содержит одну публичную функцию get. В Commands помещаем сервисы, которые изменяют БД. Command содержит одну публичную функцию execute.

Models

Модель содержит только простейшую логику, связанную с чтением и сохранением данных. Причем эти манипуляции могут быть и не связаны с БД.

Если модель работает с БД, то одна модель обслуживает только одну или несколько таблиц.

Рецепты

Микросервис

Микросервис в моем понимании должен управлять только одной сущностью. Поэтому архитектура для простейшего микросервиса будет выглядеть таким образом:

  • один Роутер;
  • один Контроллер;
  • несколько Views;
  • несколько Сервисов;
  • одна Модель.

Сервис

Сервис — это мини приложение. Оно содержит:

  • один Роутер;
  • несколько Контроллеров;
  • несколько Views;
  • несколько Сервисов;
  • несколько Моделей.

Монолит

Монолит — это большое приложение. Монолиты никто не любит по причине их монструозности. Монолит оправдан, если следовать подходу Monolith first. В таком состоянии ваше приложение может пребывать довольно долго.

Монолит содержит в себе:

  • один СуперРоутер;
  • несколько обычных Роутеров;
  • много Контроллеров;
  • много Views, много Сервисов;
  • много Моделей.

Это начинает выглядеть немного страшно. Здесь явно видно дополнительное вертикальное разделение слоев. Это позволяет оставаться приложению пока еще управляемым и поддерживаемым. Распиливание монолита на части становится чисто механической задачей.

Для сохранения стройности архитектуры нужно:

  1. Добавить один верхнеуровневый роутер, который будет разруливать глобальные пути — СуперРоутер.
  2. Распределить файлы в структуре помодульно. То есть в соответствии с будущим распилом на отдельные сервисы.

Тестирование

В рамках рассматриваемой архитектуры тщательному тестированию подлежат только сервисы — только в них заложена бизнес логика. А мокать нужно только Модели.

Если у вас возникает желание протестировать, что-то кроме сервисов, то вероятно место для логики выбрано неправильно.

Заключение

На мой взгляд, KISS Architecture подходит для 80% проектов и обеспечивает плавную эволюцию проекта.

Этот архитектурный подход будет понятен всем разработчикам и для его применения на практике не нужно читать толстенные книги про DDD.