Adapter: contratos incompatíveis conversando
O domínio define a interface dos sonhos; o adapter traduz para o fornecedor da vez. Da classe tradutora à camada anticorrupção, com os três dividendos e a régua de quando não adaptar.
A cena se repete em todo projeto: seu domínio precisa enviar notificações, e o SDK do fornecedor tem uma API com nomes estranhos, callbacks aninhados e um formato de erro exótico. A tentação é espalhar o SDK pelo código; a conta chega quando o fornecedor muda (de preço, de API, de existência). O Adapter é a resposta com nome de tomada: um tradutor entre o contrato que o seu domínio quer e o contrato que o mundo oferece.
O padrão em código real
O movimento tem dois passos: primeiro, o seu domínio define a interface dos sonhos (o que ele precisa, no vocabulário dele); depois, o adapter traduz para o fornecedor da vez:
// 1. O contrato que o DOMÍNIO define (não o fornecedor)
interface EnviadorDeNotificacoes {
enviar(destino: Destinatario, mensagem: Mensagem): Promise<Envio>;
}
// 2. O adapter traduz para o SDK exótico do fornecedor
class AdapterZentexApi implements EnviadorDeNotificacoes {
constructor(private sdk: ZentexSDK) {}
async enviar(destino: Destinatario, mensagem: Mensagem): Promise<Envio> {
// tradução de formato, nomes e erros:
const resp = await this.sdk.dispatchMsg({
rcpt: destino.telefone.replace(/\D/g, ""),
body: mensagem.texto,
chan: "wa",
});
if (resp.st !== "OK") {
throw new FalhaDeEnvio(this.traduzirErro(resp.errCd));
}
return { id: resp.msgId, status: "enviado" };
}
}
// 3. O domínio nem sabe quem envia
class ConfirmarPedido {
constructor(private notificador: EnviadorDeNotificacoes) {}
// ...usa notificador.enviar(), no vocabulário do negócio
}
Amanhã o fornecedor dobra o preço? Escreve-se outro adapter, e o domínio não muda uma linha. É a inversão de dependência da Clean Architecture no seu caso de uso mais cotidiano: o núcleo define o contrato; a borda se adapta.
A versão estratégica: camada anticorrupção
Em integrações grandes (o ERP legado, o sistema do parceiro), o adapter cresce de classe para camada: a anti-corruption layer do DDD. A ideia é a mesma, com um objetivo explícito: impedir que o modelo confuso do outro sistema contamine o seu. Os conceitos deles ("registro tipo 7 com flag B") são traduzidos na fronteira para os seus ("pedido cancelado"), e a estranheza fica em quarentena num módulo só, em vez de vazar pelo domínio.

Os três dividendos (além da troca de fornecedor)
- Testes destravados: o domínio se testa com um dublê da SUA interface, limpa e pequena, em vez de mockar o SDK de 40 métodos. E o adapter ganha testes de integração contra o sandbox do fornecedor, cada camada com seu trabalho.
- Erros com vocabulário único: cada fornecedor falha do seu jeito; o adapter traduz tudo para as SUAS exceções. O tratamento de erro do domínio fica um, e o retry/circuit breaker embrulha a interface estável.
- Multi-fornecedor de graça: dois gateways de pagamento com roteamento por custo? Dois adapters da mesma interface, e a decisão vira configuração.
Quando NÃO adaptar
A régua honesta da série: adapter para fronteiras que podem mudar ou que poluem (fornecedores, legados, SDKs). Não para embrulhar a biblioteca padrão da linguagem, nem para criar "interface + implementação única" de tudo por cerimônia: abstrair o que nunca vai variar é custo sem retorno. O teste rápido: "se isto mudar, quantos arquivos eu toco?" Se a resposta é "metade do sistema", faltou adapter; se a camada existe para uma dependência que jamais mudará, sobrou.
Próximo e último padrão da série: Factory Method, criando objetos sem se acorrentar a eles. Desenhar essas fronteiras com juízo é o cotidiano do nosso serviço de Arquitetura de Software.
Quantos arquivos você tocaria para trocar seu gateway de pagamento hoje? Conte para a IA da Rabelo Digital, aqui no canto da tela, e ela desenha a interface e o adapter que blindam o domínio. Sem formulário, sem espera.


Deixe um Comentário