← Назад к вопросам

Что такое паттерн Anti Corruption Layer?

2.7 Senior🔥 91 комментариев
#Микросервисы и архитектура

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Паттерн "Антикоррупционный слой" (Anti Corruption Layer, ACL)

Антикоррупционный слой — это широко применяемый архитектурный паттерн из области Domain-Driven Design (DDD) и интеграционной архитектуры. Его основная цель — защитить доменную модель вашего приложения от негативного влияния внешних систем, сервисов или устаревших модулей (legacy systems), имеющих иные модели данных, концепции и контракты.

Простыми словами, ACL — это буфер, переводчик и фильтр, который размещается между вашей чистой, новой системой и внешним "хаотичным" миром. Он не позволяет "коррупции" (в виде чужих, несовместимых или нежелательных моделей, структур или побочных эффектов) проникнуть в ядро вашего приложения и исказить его дизайн.

Проблема, которую решает ACL

Представьте ситуацию: вы разрабатываете современный микросервис на Go с четкой предметной областью (например, "Управление заказами"). Ему необходимо получать данные о клиентах из старой монолитной CRM-системы, которая:

  • Использует устаревший SOAP-протокол.
  • Возвращает XML с огромным количеством ненужных полей.
  • Имеет свои внутренние понятия "Контрагент" и "Адрес доставки", которые лишь частично соответствуют вашим "Клиентам".
  • Может менять свой контракт без предупреждения.

Без ACL: Ваш сервис будет напрямую зависеть от этой "грязной" модели. Ваш код заполнится парсингом XML, сложными маппингами полей, обработкой неожиданных значений. Любое изменение в CRM сломает вашу логику. Ваша чистая доменная модель Customer окажется загрязнена служебными атрибутами извне.

С ACL: Вы создаете промежуточный слой, который берет на себя всю "грязную" работу.

Архитектура и реализация в Go

ACL обычно реализуется в виде набора Go-компонентов, размещенных на границе вашего приложения (часто в слое Infrastructure или в отдельном клиентском пакете).

// ВАША ЧИСТАЯ ДОМЕННАЯ МОДЕЛЬ (ядро приложения)
package domain

type Customer struct {
    ID        string
    FullName  string
    Email     string
    IsActive  bool
}

type CustomerRepository interface {
    FindByID(id string) (*Customer, error)
}
// ВНЕШНЯЯ СИСТЕМА: Модель и клиент (представлены для контекста)
package legacycrm

// Внешняя "грязная" модель (SOAP/XML)
type ExternalContractor struct {
    ContractorID      string `xml:"ContrId"`
    Name              string `xml:"FullName"`
    ContactEmail      string `xml:"Email1"`
    Status            string `xml:"AccStatus"` // "ACTIVE", "INACTIVE"
    // ... 20+ других полей, которые вам не нужны
}

type SOAPClient struct {
    // ... клиент для вызова SOAP-сервиса
}

func (c *SOAPClient) GetContractor(id string) (*ExternalContractor, error) {
    // Сложный вызов SOAP, парсинг XML...
}
// АНТИКОРРУПЦИОННЫЙ СЛОЙ (ACL) - ИМПЛЕМЕНТАЦИЯ
package anti_corruption

import (
    "your-app/domain"
    "your-app/legacycrm"
)

// Adapter (Адаптер) - ключевой компонент ACL
type CRMAdapter struct {
    client *legacycrm.SOAPClient
}

func NewCRMAdapter(client *legacycrm.SOAPClient) *CRMAdapter {
    return &CRMAdapter{client: client}
}

// Фасад и трансляция в одном методе: скрывает сложность внешней системы.
func (a *CRMAdapter) FindCustomerByID(id string) (*domain.Customer, error) {
    // 1. Изоляция: взаимодействие с внешним миром
    externalData, err := a.client.GetContractor(id)
    if err != nil {
        // 2. Обработка внешних ошибок и их трансляция во внутренние
        if err.Error() == "not found" {
            return nil, domain.ErrCustomerNotFound
        }
        return nil, err
    }

    // 3. Трансляция (Translation): Преобразование "грязной" модели в чистую.
    // Это СЕРДЦЕ ACL.
    customer := a.translateToDomain(externalData)
    return customer, nil
}

// Приватный метод трансляции. Изменения внешней модели затрагивают только его.
func (a *CRMAdapter) translateToDomain(ext *legacycrm.ExternalContractor) *domain.Customer {
    // Фильтрация данных, сложное преобразование, обогащение.
    return &domain.Customer{
        ID:       ext.ContractorID,
        FullName: ext.Name,
        Email:    ext.ContactEmail,
        IsActive: ext.Status == "ACTIVE", // Преобразование формата статуса
    }
}
// ИСПОЛЬЗОВАНИЕ В СЛОЕ ПРИЛОЖЕНИЯ (Application Service)
package service

import (
    "your-app/domain"
    "your-app/anti_corruption"
)

type CustomerService struct {
    repo domain.CustomerRepository // Работаем ТОЛЬКО с доменным интерфейсом
}

// Внедряем ACL через доменный интерфейс (Dependency Inversion)
func NewCustomerService(adapter *anti_corruption.CRMAdapter) *CustomerService {
    // CRMAdapter неявно реализует domain.CustomerRepository благодаря методу FindCustomerByID
    // (в реальности лучше использовать явную обертку, реализующую интерфейс).
    return &CustomerService{repo: adapter}
}

func (s *CustomerService) GetCustomerProfile(id string) (*domain.Customer, error) {
    // Сервис не знает, откуда берутся данные. Он работает с чистой моделью.
    return s.repo.FindByID(id)
}

Ключевые компоненты ACL в коде

  • Фасад (Facade): Упрощает сложный интерфейс внешней системы (CRMAdapter скрывает SOAP-вызовы).
  • Адаптер (Adapter): Преобразует интерфейс внешней системы в интерфейс, ожидаемый вашим доменом (реализует CustomerRepository).
  • Транслятор (Translator): Выполняет непосредственное преобразование DTO/моделей внешнего мира в ваши доменные объекты и обратно (метод translateToDomain).
  • Служба анти-коррупции: Может включать дополнительную логику валидации, кэширования, повторных попыток вызова (retry) для неустойчивых внешних систем.

Преимущества использования ACL в Go-проектах

  • Сохранение целостности домена: Ядро приложения остается чистым, тестируемым и независимым.
  • Упрощение тестирования: Домен можно тестировать unit-тестами с моками репозитория. Сам ACL тестируется интеграционными тестами.
  • Контролируемая граница контекстов: Явно определяет, как и какие данные пересекают границу между Bounded Context (ограниченным контекстом) вашего сервиса и внешним миром.
  • Защита от изменений: Если внешний сервис изменит API, правки будут локализованы только в одном месте — внутри ACL.
  • Повышение надежности: ACL — идеальное место для добавления устойчивости (resilience) к сбоям внешних систем через паттерны Retry, Circuit Breaker (предохранитель) или Fallback.

Когда применять паттерн

  • Интеграция с Legacy-системами.
  • Работа со сторонними API, которые вы не контролируете.
  • Взаимодействие между микросервисами с разными моделями данных.
  • Поэтапный рефакторинг большой системы, когда новый модуль должен сосуществовать со старым.

Таким образом, Anti Corruption Layer в Go — это не просто "еще один адаптер", а стратегический архитектурный элемент, который инвестирует в долгосрочную поддерживаемость и эволюционность вашей системы, ограждая ее наиболее ценную часть — бизнес-логику — от хаоса внешнего мира.

Что такое паттерн Anti Corruption Layer? | PrepBro