19.3Kпросмотров
2 апреля 2025 г.
📷 ФотоScore: 21.2K
Anti corruption layer Часто в наших приложениях мы обращаемся к каким-то внешним системам. Иногда мы просто обращаемся к ним, иногда ждем обратных вызовов. Это может быть платежная система, сервис уведомлений, инвентаризации или что-то ещё. Ключевое в таких интеграциях то, что такие системы имеют свой жизненный цикл, свой контекст и часто их устройство слабо похоже на то, что нам надо от них, однако интеграция с ними может быть жизненно необходима для нашего приложения. Для того, чтобы сделать наше приложение более устойчивым к изменениям внешнего API и одновременно сохранить нашу логику чистой, мы выделяем отдельный компонент - Anti Corruption Layer. Его задача - скрыть за собой детали взаимодействия с этой системой, предоставив нашей бизнес логике понятное ей API. Структура с использованием ACL может состоять из таких частей: • Какая-то часть нашей бизнес-логики использует интеграцию. Она знает о том, что принципиально это за сервис, однако не знает о деталях общения с ним. • У бизнес-логики есть требования к взаимодействию. Они выражаются в виде интерфейсов и каких-то моделей данных. Хоть мы и абстрагируемся от деталей, мы всё-таки выражаем наше представление о конкретном сервисе, но лишь об интересных нам аспектах и о данных в терминах понятных нашему бизнесу. • Сторонний сервис для нас представляет некоторое API, удобное или не очень. Иногда это вызовы библиотек, иногда - удаленные обращения по HTTP или другим протоколам. Мы не контролируем код, который это реализует. Это чужой код. • Если сторонний сервис не предоставляет для нас достаточно понятного API, мы самостоятельно реализуем клиентский фасад. Он обязательно выражается в терминах чужой системы, что позволит нам при её изменениях проще его обновлять. Он может реализовывать только часть вызовов, или игнорировать часть данных, но он достаточно примитивный (хоть и может содержать сложные парсеры DTO) и призван просто улучшить читаемость чужого API. Это можно сделать вводя более строгие типы, конкретизируя сигнатуры методов, разделяя вызовы или группируя по смыслу. Важно не пытаться тут сразу транслировать удаленные вызовы в наши доменные сущности. Если у нас уже есть достаточно хорошая реализация чужого API, то дополнительный фасад не требуется. • Чтобы совместить фасад с нашим интерфейсом, мы делаем адаптер. Он будет трансформировать вызовы выраженные в наших терминах (понятные нашей БЛ) в вызовы в терминах чужого сервиса (понятные фасаду или чужому коду). При этом на одно обращение к нему, он может делать несколько вызовов чужого API, если это требуется. • Так как кроме самих вызовов необходимо так же менять форму данных, это часто удобно вынести в отдельные трансляторы. В качестве них могут быть использованы дополнительные объекты или просто методы адаптера. Пример из практики в комментарии Дополнительные материалы: • https://martinfowler.com/articles/patterns-legacy-displacement/legacy-mimic.html • https://adaptix.readthedocs.io/en/latest/conversion/tutorial.html
19.3K
просмотров
2985
символов
Нет
эмодзи
Да
медиа

Другие посты @advice17

Все посты канала →