515просмотров
17 октября 2025 г.
Score: 567
Порты и адаптеры в чистой архитектуре В прошлых постах я рассказывал, как реализовать уровни core и application в гексогональной архитектуре на примере микросервиса авторизации. Когда основная логика уже написана, остается дать возможность приложению взаимодействовать с внешним миром: 💡 Обрабатывать входящие запросы или сообщения. 💡 Вызывать другие системы и отправлять нотификации. 💡 Работать со различными базами данных. Для этого нужно написать код уровня инфраструктуры, основу которого составляют ingress и egress адаптеры. Входящий поток (ingress) Адаптерами здесь являются, например, REST-controllers и Kafka-listeners. Они решают 3 главных задачи: 💡 Проверка данных запроса и генерация ошибок валидации. 💡 Маппинг транспортных моделей в доменные и обратно. 💡 Вызов основной бизнес-логики приложения. Адаптеры на выходе из приложения решают те же задачи, но устроены чуть сложнее. Исходящий поток (egress) Для интеграции они используют клиентов к внешним системам. И в рамках одного метода адаптер может вызывать их несколько раз. Типичные кейсы: 💡 Получение данных одной модели несколькими REST-запросами. 💡 Сохранение данных одной модели вставкой в несколько таблиц. Таким образом, основное назначение адаптеров в чистой архитектуре - абстрагировать логику работы приложения от деталей внешних интеграций. Это, действительно, удобно. Только вот с ходу заходит не всем. Мне по началу тоже было не просто. Поэтому я решил собрать ответы на вопросы, которые у меня возникали в ходе погружения в тему: Вопрос: Как взаимодействуют между собой порты и адаптеры? Ответ: Входящие адаптеры вызывают ingress-порты application-слоя. Исходящие адаптеры имплементируют egress-порты application-слоя. Вопрос: Можно ли исходящие адапптеры делать по одному на каждую вызываемую систему? Ответ: Нет, каждый адаптер дает возможность работать только с одной доменной моделью. Корреляции с вызываемыми системами быть не должно. Вопрос: Как быть, если мне нужно вызывать один и тот же egress-адаптер из обоих слоев (core и application)? Ответ: Исходящий адапетер может имплементировать исходящие порты обоих слоев. Вопрос: Можно ли сохранять что-либо в БД не использую core-слой? Ответ: Нет, при изменении состояния базы нужно всегда проверять соблюдение бизнес инвариантов, а это ответственность ядра приложения. Ну и в завершение хочу отметить очень важный момент. Как только вы правильно разделите ответственность между компонентами системы, вы сразу же получите чистый код по всем Best practice "из коробки". Все сложится как пазл. Если у вас остались вопросы - пишите их в комментариях. Ставьте лайк, если планируете применить все это на своих проектах. TeamLead говорит | Александр Романов