Гексагональная архитектура (Hexagonal Architecture) — это способ организации кода в проекте,
чтобы логика приложения была независимой от внешних систем, таких как базы данных,
API или пользовательские интерфейсы.
Этот подход делает код проще для тестирования, расширения и поддержки.
Основная идея
В гексагональной архитектуре весь проект делится на три основных части:
Основная логика (Core):
Здесь сосредоточены все "мозги" приложения — бизнес-логика, правила и процессы.
Эта часть ничего не знает о том, как хранятся данные или каким образом пользователь
взаимодействует с приложением.
Порты (Ports):
Это интерфейсы, которые описывают, что нужно основной логике.
Например, "сохранить данные книги" или "получить данные о пользователе".
Но порты не говорят, как именно это делается.
Адаптеры (Adapters):
Это "переходники", которые реализуют порты.
Они связывают основную логику с конкретными технологиями,
например:
- Работа с базой данных через JPA.
- Отправка HTTP-запросов к внешнему API.
- Обработка запросов от веб-клиента.
Ссылки:
wiki
author blog about Hexagonal architecture
Clean architecture book.
мне понравилось это видео: Гексагональная архитектура и микросервисы
Для большего кол-ва инфы можно чат гпт по расспрашивать на эту тему
и поискать другие статьи самостоятельно.
P.S. Недавно встретил эту архитектуру, странно как она так проходила мимо меня,
решил поделится, потому что на JR про нее не нашел статей, выкатил кусочек,
чисто ради того что бы было упоминание на эту тему,
и о ней не узнали в какой нибудь последний момент :)
Комментарии (17)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
ВК
31 декабря 2024, 13:10
Миллениалы изобрели отделение логики от представления и назвали новым термином? )
Всю сознательную жизнь (кроме, может, первых набитых шишек) начиная писать игрушку, делал два модуля - один для модели игрового мира (заветное world = new World(256, 256); ), второй - способы его изображения ( camera = new Camera(world); ). И это без всякой теории само напрашивается, потому и для отладки, и для портабельности удобно (можно наделать разные представления одного и того же мира в консоли, на канве формы, на 3d-сцене).
Применительно к бекенду, бизнес-логика будет в ядре, а способы её вызова могут быть разными - что-то через rest дёрнут, что-то по веб-сокету передадут, что-то по кастомному протоколу, что-то вообще из cli-интерфейса...
А вот, вспомнил умный термин - MVC (model, view, controller), это ж про то же самое?
0
empty
31 декабря 2024, 15:59
Alistair Cockburn 71 years old. Hexogenal Achitecture.
забавная фамилия однако)
Imho:
нет, mvc больше относится к presentation layer.
presentation это из 3-layer architecture, где есть слой presentation затем service и persistence.
mvc это такой более узкий паттерн, у которого есть view и model которые
выполняют свою логику, а в контроллере эти две сущности инжектятся и
контроллер регулирует, скажем так, их взаимодействие. Это грубо говоря.
допустим у нас есть такие компоненты:
controller,
bussines logic,
dto,
mapper,
config(root / web)
exception,
util,
repository,
это такие базовые +-
на деле еще много компонентов...
в общем куча пакетов с кучей классов,
надо бы это все разделить на "логические слои"
то есть layers, где в presentation из этого списка можно
добавить, логику работы с клиентом, те же контроллеры,
вью, и т.п. mvc как раз в этом слое логики..
Важно тут бизнес логику не реализовывать...
Далее service layer, сюда бизнес логику, исключения,
дто, мапперы, конфиги, утильные какие то пакеты,
и т.д. Важно что бы не было каких то sql запросов,
низкоуровневой логики, репозиториев, и т.п.
и собственно persistence layer, это как раз слой логики
для работы с БД, с какими то низкоуровневыми компонентами,
и т.д.
То есть начиная от persistence и заканчивая presentation
уровень абстракции(абстрагирования от деталей реализации)
должен расти.
Что касается Hexogenal architecture которая вводит такие понятия
как порт и адаптер, и ядро.
Опять же, без углубления в детали, потому как сам обучаюсь,
и все еще разбираюсь в деталях...
0
empty
31 декабря 2024, 15:59
Так вот эта архитектура дает возможность понизить вот эту связь между слоями,
сильнее, и выделив ее в адаптеры.
Получается у нас есть такая вещь - Основная логика(бизнес логика, ядро),
которая имеет порты input и output, так сказать вилки и розетки, через которые
происходит коннект с другими слоями логики, другими компонентами
не имеющими отношение к смыслу сервиса, то есть той логики ради которой
создавалось в принципе приложение.
Адаптеры нужны что бы была возможность работать с разными
компонентами не изменяя основной логики(ядра).
Например у тебя есть World1 и есть Camera объекты,
ты инжектишь в объект Camera объект World1 и пишешь в реализации
Camera логику которую предоставляет World1.
Но что если появится объект World2, который предлагает другую реализацию,
другую специфику и т.п. Получается что если инжектить в объект Camera объект World2,
а учитывая что в Camera реализована логика конкретно для Wolrld1,
то придется переписывать логику под World2 или писать новую Camera2.
Но мы можем написать одну реализацию Camera и не трогать ее,
сделать для нее порт(розетку),
и вот эти World1 и World2 для них написать для каждого свою реализацию,
и сделать адаптеры(переходники) которые подходят под порт Camera, и
рабоать через эти адаптеры.
Собственно вот +- логика Гексогональной архитектуры..(в общих рамках)...
Так что mvc, hexogenal architecture и подобные,
они про разное и работают на разных уровнях,
но направлены на то что бы пофиксить
хаотичность в коде, в пакетах, в целом в архитектуре,
и понизить связность между классами, компонентами,
пакетами, отдельными сервисами и т.п.
0
Денис Enterprise Java Developer
31 декабря 2024, 17:49
Там все чуток сложнее, общая идея отделить мух от котлет, проблема в том как это делается.
Возьмем среднестатистическую структуру приложения, у тебя есть какой-то контроллер, у тебя есть для него какой-то сервис в сервисе крутится логика и допустим данные хранятся в базе, с которой работает сервис через репозиторий.
Если приложение построено правильно, то у тебя уже все от всех отделены. Сервис принимает в себя доменные объекты, их же возвращает. У сервиса есть зависимость на что-то что умеет работать с базой, будь это репозиторий или другой сервис - не столь важно. Все просто, понятно, легко запомнить.
Но людям же не живётся так просто :) Они говорят, давайте мы каждый метод в сервисе обзовём портом, выделим в отдельный интерфейс и прикрутим через множественное наследование интерфейсов в сервис. Не изменится ровным счётом нифига, но текста станет сильно больше. Соответственно ты не можешь нормально инжектнуть этот сервис в контроллер, ты теперь должен разговаривать на языке кейсов и портов, потому у тебя появляются "Менеджеры" которые наследуют эти самые интерфейсы, т.е. еще один слой абстракции.
Тот факт что приложение и без этого всего работает деликатно опускается, ведь это в самом деле невозможно вызвать один и тот же сервис из разных частей приложения :) Например из рестового эндпоинта и вебсокета, вообще невозможное занятие! Точно так же считается невозможным, походу и замена репозитория базы на ... условный S3 storage service :)
Что в сухом остатке?
- Функционала эта гексагоналка не приносит, если приложение написано грамотно оно уже работает достаточно изолированно, если же нет - горбатого могила исправит.
- Сущностей в коде становится существенно больше, ими приходится жонглировать и достаточно легко провтыкать что ни будь.
- Очевидно количество тестов требуемых на это все дело, а заодно конвертеры и прочее вырастает кратно.
Возможно я не умею эту гексагоналку готовить, но пока не понял зачем оно существует.
0
Денис Enterprise Java Developer
31 декабря 2024, 17:55
Ну и само собой, правка которая обычно потребовала бы изменений в 1-2 классах теперь может расплыться на N мест в зависимости от атомарности твоих кейсов, а заодно и все тесты будь добр поправить тоже.
Одним из доводов в пользу гексагоналки, едва ли не единственным, является то что если приложению надо работать с огромным количеством внешних зависимостей, типа разных апи, разных хранилищ, и тому подобных - она удобная.
На мой взгляд, если у приложения и правда так много внешних зависимостей, проще построить вокруг них микросервисы и общаться по унифицированному, внутреннему апи уже. Да и в гибкости такое решение сильно выигрывает. Появилась новая зависимость - строишь новый микросервис и встраиваешь его в общий поток, при том это даже не требует редеплоя и никак не влияет на остальные части системы (ну в основном конечно же).
0
empty
31 декабря 2024, 18:15
Нууу, мне показалось, интересным подходом,
типа фишка в гибкости...
Порты нужны, чтобы изолировать ядро приложения от деталей реализации.
Такая штука позволяет легко заменить реализацию
(переход с реляционной БД на другой вариант).
Адаптеры обеспечивают преобразование данных между лэерами.
Да, их количество растет, но это некая цена за модульность.
Становится ли код сложнее, в некотором смысле, однако
усложнение скорее играет роль обеспечения гибкости.
Понятно что не всегда можно лепить одно к другому,
и гексагональная архитектура тоже не всегда, уверен, подходит.
Однако чем крупнее проект тем она более оправдана чем на оборот...
Хотя конечно, думаю есть альтернативы, с которыми я еще не знаком,
и потому выдвигать на роль панацеи, естественно не буду...
У всего есть свои плюсы и минусы.
0
Денис Enterprise Java Developer
31 декабря 2024, 18:33
Я потому и предлагал тебе написать приложение с этим подходом ) и потом уже делать выводы.
0
empty
31 декабря 2024, 18:50
Так я и пишу, не ради подхода, цель другая,
но эту архитектурку решил попробовать внедрить,
может и прикреплю когда нибудь проект...
0
JustinianJudge в Mega City OneMaster
26 марта 2025, 18:59
для меня честно говоря это была непростая архитектура, то есть я долго не мог въехать зачем оно вообще.
Но мы программисты, есть контекст, есть задачи, есть инструменты.
Одно и то же можно сделать многими разными способами.
С точки зрения программистов, фокус идет на инструментах и архитектурных принципах: SOLID, n-layer, MVC etc, мы строим гибкую систему, и нам все-равно по сути какая доменная область, наше решение будет гибким, адаптивным.
При таком подходе, наше приложение изолировано от заказчика и бизнес требований, есть некий интерфейс - это функциональность, мы ее заделиверили, как мы это сделали, это наш вопрос. Заказчик получил то что хотел в любом случае.
А вот гексагональная архитектура, как я вижу, это другая парадигма, это взгляд со стороны бизнеса, то есть хороший пример domain driven development.
Когда команда достаточно тесно инкорпорирована в продукт, в доменную область, которая достаточно плотно засела в бизнес требованиях, то есть не просто крутится вокруг функциональности, а именно вокруг определенных бизнес-моделей, и функционал как их придаток, грубо говоря, тогда можно и по другому посмотреть на подход к разработке,
При гексагональной архитектуре, бизнес требования, доменная область и само приложение будет в синергии, это просто другой взгляд на работу.
При этом, с того что я видел, изолированность самих моделей была лучше именно в гексагональной архитектуре, там прям задачка со звездочкой, если захочется намешать.
И оно в целом логичней выглядит в связи именно с определенной дата моделью и бизнес-процессами.
Это просто другой подход, и сложно представить если именно девелопер будет инициатором, если разве прям не прочувствовал это на предыдущих проектах и считает что здесь это будет уместно.
По дефолту мы делаем n-layer и строим универсальную систему.
А вот архитекторы и/или со стороны продукта да, они могут такое инициировать, поскольку это может быть вполне уместно конкретному бизнес-контексту и процессам разработки
+1
Денис Enterprise Java Developer
26 марта 2025, 19:20
Я в целом то за любой кипиш, кроме голодовки, лишь бы оно действительно решало задачу. Если же какой-либо подход создаёт больше проблем чем решает, у меня есть вопросы :) Я в общем то пишу из своего опыта и скорее всего не самого удачного - так бывает. Вот побывать на почти идеальном (если не действитеьно идеальном) микросервисном проекте мне повезло, я прочувствовал всю силу и крутизну, а вот с гексагоналкой пока хороших примеров видеть не довелось, что не значит что их нет.
+1
JustinianJudge в Mega City OneMaster
27 марта 2025, 09:25
да, здесь простой принцип, не чувствуешь потребности не делаешь.
А чтобы прочувствовать потребность нужно либо достаточно глубоко влезть в DDD, паттерны, архитектуру либо хотя бы несколько хороших проектов увидеть.
Поэтому мы всегда отталкиваемся от своего опыта и понимания и решаем задачи прогнозируемыми инструментами которые хорошо понимаем.
Чтобы исполнять завет "инженер должен знать свои инструменты", если видим какой-то крюк с поди какой пользой, ну классно, в сторону отставили и будем делать так, как считаем нужным :)
0
Денис Enterprise Java Developer
26 декабря 2024, 10:05
Ты бы чтоли пример написал, и сравнил чем и где это лучше более традиционных подходов. А то сферический конь в вакууме получается какой-то.
Моя практика говорит что гексагоналка достаточно противоречивая штука, не очень удобная в поддержке и с непонятными бенефитами, но может быть я просто не видел удачной реализации :)
0
empty
26 декабря 2024, 10:45
Этот пост или статья, как назвать я не шарю, но я написал в конце что это чисто в виде упоминания,
что мол есть такая штука и ее бывает используют,
и кому интересно пусть погуглит :)
Насчет примера, ну я мог бы привести пример как я понял,
но я можно сказать сам еще не до конца вкурил как она выглядит.
Ну ок, такой пример, супер простой, не уверен что правильный,
если что подкорректируй
Допустим у нас есть БД в данном случае это внешний сервис,
где в джава мы как то с ним работаем AccountJpaRepository extends JpaRepository,
нам нужно подсоединить этот сервис как то к основной логике(ядру, бизнес логике),
можно сделать на прямую(инжектировать в сервис(бизнес логика)),
но тогда при изменении внешнего сервиса, придется менять основную логику(core, ядро)
в общем сервис(AccountService), такие моменты могут возникать с разных так сказать сторон,
и потому хотелось бы реализовать такую архитектуру при которой не было бы влияния
при изменении внешнего сервиса на внутреннюю основную логику, как это сделать,
создать input и output порты(интерфейсы) которые лишь описывают апи
назовем один такой портAccountRepository,
но не привязаны к конкретным внешним сервисам,
и сделать адаптеры(реализация для каждого внешнего сервиса)
- AccountRepositoryAdapter делаем
implement AccountRepository оверрайдим методы этого интерфейса которые нужны бизнес логике,
и инжектим в адаптер представителя конкретного внешнего сервиса
AccountJpaRepository и реализуем апи основной логики в адаптере,
а в саму основную логику потом инжектим собственно AccountRepository
Короче должна получиться такая штука, где если вдруг поменяется внешний сервис,
например на монгоДБ(nosql db) то нужно будет просто написать новый адаптер под
этот внешний сервис, а порт(интерфейс, апи основной логики) просто имплементить
к этому адаптеру и основную логику не придется переписывать.
0
empty
26 декабря 2024, 10:45
В общем сумбурно, но как понял...Это не большой пример...
Сам еще разбираюсь...
Корректировки / комментарии приветствуются...
0
Денис Enterprise Java Developer
26 декабря 2024, 11:18
Это раздел статей, здесь публикуют хоть сколько ни будь применимую информацию. Напиши проект с использованием гексагоналки, приложи его к статье, распиши плюсы и минусы подхода - тогда это станет статьёй.
+1
empty
26 декабря 2024, 11:28
Блин, Денис, мне все равно статья это или нет, я могу на форуме запостить..
мне все равно сколько лайков, и как получить ачивку..
Я просто решил поделится интересной темой, тк на JR про нее не было даже упоминания,
думаю вот раньше не слышал про нее, а теперь узнал, типа прикольная штука,
поделюсь с другими.
Мог в чате написать но там быстро улетела бы..
Тут мол останется..
Если модеров не устроит такая "упоминалка" в разделе "статьи" пусть дропают...
Если мозолит глаза, можешь написать в "support"
с просьбой удалить/скрыть... Мне хуже не станет...
0
Денис Enterprise Java Developer
26 декабря 2024, 11:31
Разве я говорил что-то про ачивки? Ты делишься информацией - делай это осмысленно. Вроде как умеешь уже в программирование, а пишешь как инфоцыган прости господи :) Вот и выходит как в том меме "них*я не понял, но очень интересно".
Технически на JR и с вот этой статьёй не прибыло информации о гексагоналке, потому что ровным счетом ничего в статье об архитектуре не написано. Если просто хотелось поделиться чем то новым - эти две ссылки можно было скинуть в чат, как это делает РА, но если пишешь - пиши нормально.
+1