System Analysis and Design
ООP
Programming
Designing and refactoring
Perfect code
February 19

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

Андрей Копылов, наш технический директор, рассказывает, какой подход к проектированию архитектуры приложений использует команда веб-разработчиков AREALIDEA, и, чем 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.

+6
3.6k 62
Comments 26