Anti-Corruption Layer (ACL)

Como proteger seu domínio da contaminação de sistemas externos, legados ou de terceiros por meio de uma camada de tradução que isola modelos incompatíveis.

Que problema resolve

Quando seu sistema precisa se integrar com um sistema externo (legado, de terceiros ou de outra equipe), os modelos de dados e conceitos de negócio costumam ser muito diferentes. Sem proteção, o modelo do sistema externo contamina seu domínio:

Sem ACL:
  Seu Serviço de Pedidos
  ┌──────────────────────────────────┐
  │ createOrder(legacyCustomerCode,  │
  │   legacyProductSKU,              │  ← Conceitos do sistema legado
  │   legacyPriceFormat,             │     infiltrados no seu domínio
  │   legacyTaxCalculation)          │
  └──────────────────────────────────┘


  Sistema Legado ERP (modelo incompatível)

Os problemas concretos são:

  • Contaminação do modelo: Seu domínio adota nomes, estruturas e regras do sistema externo
  • Acoplamento forte: Mudanças no sistema externo exigem mudanças no seu domínio
  • Complexidade crescente: Seu código mistura lógica de negócio com lógica de tradução
  • Testes difíceis: Você não consegue testar seu domínio sem simular o sistema externo

Como funciona

O Anti-Corruption Layer é uma camada de tradução que se posiciona entre o seu sistema e o sistema externo. Ela traduz conceitos, formatos e protocolos em ambas as direções, mantendo seu domínio limpo.

Com ACL:
  Seu Serviço de Pedidos
  ┌──────────────────────────────┐
  │ createOrder(customerId,      │
  │   productId,                 │  ← Seu modelo de domínio limpo
  │   price,                     │
  │   tax)                       │
  └──────────┬───────────────────┘

  ┌──────────▼───────────────────┐
  │    Anti-Corruption Layer     │
  │                              │
  │  customerId → legacyCustCode │
  │  productId → legacySKU       │  ← Tradução bidirecional
  │  price → legacyPriceFormat   │
  │  tax → legacyTaxCalc         │
  └──────────┬───────────────────┘


  Sistema Legado ERP

Componentes do ACL

ComponenteResponsabilidadeExemplo
TranslatorConverte dados entre modelosLegacyCustomer → Customer
AdapterAdapta a interface do sistema externoREST → SOAP, JSON → XML
FacadeSimplifica a API do sistema externo5 chamadas legadas → 1 método limpo
MapperMapeia campos e valores entre modelosstatus: "A"status: "active"

Exemplo de tradução

Seu modelo (domínio limpo):
  Order {
    id: "ORD-001"
    customer: { id: "C-123", name: "María García" }
    items: [{ product: "Laptop", quantity: 1, price: 1500 }]
    status: "confirmed"
  }

Modelo do sistema legado:
  LEGACY_ORDER {
    ORDER_NUM: "00000001"
    CUST_CODE: "CUST00123"
    CUST_NM: "GARCIA, MARIA"
    LINE_ITEMS: "LAPTOP|1|150000"  (preço em centavos, pipe-separated)
    STAT_CD: "CF"
  }

O ACL traduz entre ambos os modelos:
  OrderACLTranslator.toExternal(order) → LEGACY_ORDER
  OrderACLTranslator.fromExternal(legacyOrder) → Order

Localização do ACL

O ACL pode ser implementado em diferentes níveis:

Como serviço independente:

Seu Serviço ──► ACL Service ──► Sistema Externo

Como módulo dentro do seu serviço:

Seu Serviço
  ├── Domain Layer (limpo)
  ├── Application Layer
  └── ACL Module ──► Sistema Externo

Como parte do API Gateway:

API Gateway (com ACL) ──► Sistema Legado

Vantagens

  • Domínio limpo: Seu modelo de negócio não é contaminado com conceitos externos
  • Desacoplamento: Mudanças no sistema externo são absorvidas pelo ACL, não pelo seu domínio
  • Testes isolados: Você pode testar seu domínio sem o sistema externo (mock do ACL)
  • Migração gradual: Você pode substituir o sistema externo sem alterar seu domínio
  • Clareza: A lógica de tradução fica centralizada e é explícita
  • Múltiplas integrações: Você pode ter ACLs diferentes para diferentes sistemas externos

Trade-offs / Desvantagens

  • Código adicional: O ACL é código que precisa ser escrito, testado e mantido
  • Latência: Uma camada a mais de processamento em cada chamada
  • Sincronização de mudanças: Quando o sistema externo altera sua API, o ACL deve ser atualizado
  • Complexidade de mapeamento: Alguns mapeamentos são complexos (dados que não têm equivalente direto)
  • Risco de ACL inchado: Se o ACL crescer demais, pode se tornar um problema em si mesmo
  • Manutenção dupla: Mudanças no seu modelo ou no externo exigem atualizar o ACL

Quando usar

  • Integração com sistemas legados que têm modelos de dados incompatíveis
  • Consumo de APIs de terceiros com modelos diferentes do seu domínio
  • Migração gradual de um monólito para microsserviços
  • Quando múltiplos bounded contexts precisam se comunicar sem contaminar seus modelos
  • Integração com sistemas que usam protocolos ou formatos diferentes (SOAP, XML, arquivos planos)
  • Quando o sistema externo muda com frequência e você quer isolar o impacto

Quando evitar

  • Integração com sistemas que compartilham o mesmo modelo de domínio
  • APIs externas simples onde a tradução é trivial (um mapeamento de 2-3 campos)
  • Protótipos onde a velocidade de desenvolvimento é mais importante que a pureza do modelo
  • Quando o sistema externo é temporário e será substituído em breve

Tecnologias e implementações comuns

CategoriaOpções
Padrões de designAdapter, Facade, Translator, Mapper
Bibliotecas de mapeamentoMapStruct (Java), AutoMapper (.NET), class-transformer (TS)
IntegraçãoApache Camel, Spring Integration, MuleSoft
API TranslationGraphQL como ACL, API Gateway com transformações

Relação com outros padrões

  • DDD (Bounded Context): O ACL protege os limites entre bounded contexts
  • API Gateway: Pode implementar funções de ACL para sistemas externos
  • BFF: O BFF atua como um ACL entre o frontend e os microsserviços
  • Shared Kernel: Alternativa ao ACL quando dois contextos compartilham um modelo comum deliberadamente
  • Microsserviços: Cada microsserviço pode ter seu próprio ACL para integrações externas

Próximos passos

O Anti-Corruption Layer é essencial para manter a integridade do seu domínio. Para entender como lidar com falhas na comunicação com sistemas externos, explore o padrão Retry. Para compartilhar modelos de forma controlada entre contextos, revise o Shared Kernel.