Hexagonal Architecture
Гексагональная архитектура или архитектура портов и адаптеров - это архитектурный подход, при котором основная логика приложения отделяется от источников данных, внешних сервисов и пользовательских интерфейсов. По-моему мнению, является одной из разновидностей “Чистой архитектуры” Роберта Мартина. (https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)
Все такие архитектуры (и гексагональная в том числе) преследуют одну и туже цель - разделение приложения на слои с целью отделить детали реализации от основной логики приложения. Разработанные при помощи такого подхода приложения обладают следующими преимуществами:
- Не зависят от фреймворков. По крайней в идеале не должны зависеть от фреймворков. Мы можем изменить фреймворк, на котором строится приложение с минимальными изменениями в пакете с бизнес логикой.
- Тестируемы. Все бизнес-правила должны быть независимы и могут быть оттестированны без использования БД, UI, сторонних сервисов и каких-либо других сторонних зависимостей.
- Не зависимы от деталей реализации взаимодействия с внешним миром. Так как реализация взаимодействия с внешним миром отделена от основной логики приложения, мы можем легко менять их (детали). Например изменить БД с MySQL на Oracle или на MongoDB. Изменить UI или веб-взаимодействие, например, с REST HTTP на GRPC.
Рассмотрим детали
Схематически гексагональную архитектуру обычно представляют в виде шестиугольников вложенных друг в друга. Теперь более подробно о каждом элементе, представленном на фигуре, показанной на рисунке:
Domain:
Этот уровень содержит сущности (здесь и далее вместо русcкого “сущность”, будем использовать Entity, потому что русскоязычный термин не в полной мере передает смысл) и присущую им бизнес-логику. Entities инкапсулируют наиболее общую, не зависящую от приложения бизнес логику. Это могут быть как объекты с методами (привет DDD) так и набор структур данных вместе с функциями.
Application:
Этот уровень содержит основные бизнес-сценарии, которые выполняет наше приложение. Здесь происходит имплементация бизнес-логики приложения, управление потоком данных от/к Entities. Этот слой предоставляет адаптеры запросов от внешнего слоя. Взаимодействие с внешним миром слой Application осуществляет посредством абстракций - портов (Ports).
Port - это интерфейсы, через которые наше приложение взаимодействует с внешним миром. В некоторых вариантах эти интерфейсы помещают в отдельный подуровень уровня Application. Реализация Port в коде - это абстрактный класс или интерфейс для взаимодействия с внешним миром.
Framework:
Его также называют инфраструктурным слоем. Он реализует сервисы и интерфейсы, объявленные во внутренних слоях. Для каждого порта из слоя Application здесь реализуется конкретный адаптер (Adapter), имплементирующий низкоуровневое взаимодействие с внешним миром - HTTP, SQL и т.п. Например, здесь может быть реализован репозиторий, который осуществляет доступ к БД Oracle. На этом уровне к приложению подключают фреймворки и библиотеки, необходимые для функционирования приложения.
Важное замечание: Внутренние слои не должны ничего знать о внешних, то есть Domain ничего не знает о Application а тем более о Framework. Слои Domain и Application в зависимостях должны иметь минимум сторонних библиотек.
Недостатки:
Естественно как и у каждого решения, у гексагональной архитектуры есть свои недостатки:
Что дальше?
Попробуем на примере демо приложения реализовать наше видение гексагональной архитектуры.
Подписывайся на мой канал в telegram