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
| Componente | Responsabilidade | Exemplo |
|---|---|---|
| Translator | Converte dados entre modelos | LegacyCustomer → Customer |
| Adapter | Adapta a interface do sistema externo | REST → SOAP, JSON → XML |
| Facade | Simplifica a API do sistema externo | 5 chamadas legadas → 1 método limpo |
| Mapper | Mapeia campos e valores entre modelos | status: "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
| Categoria | Opções |
|---|---|
| Padrões de design | Adapter, Facade, Translator, Mapper |
| Bibliotecas de mapeamento | MapStruct (Java), AutoMapper (.NET), class-transformer (TS) |
| Integração | Apache Camel, Spring Integration, MuleSoft |
| API Translation | GraphQL 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.