03 - Conformist
video: https://youtu.be/... no frontmatter da nota.Conformist
O Conformist é a estratégia de integração em que o contexto downstream adota integralmente o modelo do upstream, sem camada de tradução e sem tentativa de preservar uma linguagem própria. O consumidor aceita as entidades, os estados, os nomes e até as distorções do modelo fornecido, porque o custo de proteger o próprio modelo é maior do que o benefício de tê-lo. Em produção, o padrão aparece com frequência em integrações com provedores externos, gateways de pagamento, serviços de entrega, plataformas de e-mail, e em relações internas de plataforma em que o fornecedor concentra todo o poder de decisão. A decisão de ser conformist é uma decisão de custo: você troca autonomia de modelagem por simplicidade de integração, e essa troca pode ser excelente ou um erro caro, dependendo da estabilidade e da qualidade do modelo upstream. O erro clássico é adotar a aderência por preguiça e descobrir, dois anos depois, que o modelo de terceiro foi costurado no coração do domínio próprio.
Conceito e natureza da aderência
Aderir significa assumir o modelo do upstream como parte do modelo próprio, dentro do contexto downstream. Se o gateway de pagamento chama o conceito de transação de Charge, com estados pending, settled e refunded, o contexto de cobrança passa a trabalhar com Charge e com esses estados, e não cria uma EntidadeDePagamento com tradução. O contraste é direto com a Anti-Corruption Layer, que existe justamente para impedir que conceitos externos contaminem o modelo local; o Conformist decide que a contaminação é aceitável, ou até desejada, porque o modelo externo é bom o suficiente.
A adesão tem gradações, e nomeá-las evita decisões confusas:
- Aderência de tipo: o downstream usa os mesmos tipos e schemas, como DTOs gerados a partir do OpenAPI ou dos proto do upstream, e mantém nomes idênticos no código.
- Aderência de estado: o downstream adota a máquina de estados do upstream, tratando settled e refunded como estados válidos do próprio modelo de negócio.
- Aderência de processo: o downstream adota o fluxo imposto pelo upstream, como a sequência obrigatória de criação de cliente antes de cobrança, e desenha sua operação em cima dela.
- Aderência de identidade: o downstream usa os identificadores do upstream como chave primária em suas tabelas, abrindo mão de identidade própria.
Quanto mais fundo a aderência, maior o ganho imediato de simplicidade e maior o preço futuro de sair. Aderência de tipo é reversível com esforço moderado; aderência de identidade é a mais difícil de desfazer, porque o identificador externo se espalha por todas as tabelas e integrações.
Na escala de estratégias do DDD, o Conformist ocupa a posição entre o Shared Kernel e a Anti-Corruption Layer. Com o kernel, os dois lados mantêm o modelo junto; com o conformist, o downstream apenas segue o modelo que não controla; com a ACL, o downstream constrói e protege o próprio modelo. A diferença entre seguir e compartilhar é de governança, e a diferença entre seguir e traduzir é de custo e autonomia. Identificar em que ponto dessa escala cada integração da sua arquitetura está é um exercício de dez minutos que revela riscos que ninguém tinha catalogado.
O problema que resolve
Entre contextos com relações desiguais de poder, o downstream tem três opções genéricas: traduzir, conformar ou isolar. Traduzir significa pagar uma camada de adaptação permanente, com testes, manutenção e risco de divergência; para um modelo upstream estável e bem desenhado, essa camada não protege de nada, apenas adiciona código. Isolar significa negar a integração, o que raramente é uma opção quando o upstream fornece capacidade essencial, como processamento de cartão. O Conformist resolve o dilema ao reconhecer que, em certas relações, o modelo upstream é o melhor modelo disponível, e a maior eficiência é usá-lo diretamente.
O padrão também resolve um problema de governança. Quando a empresa tem uma plataforma interna que atende múltiplos consumidores, exigir que cada consumidor crie sua própria tradução do modelo da plataforma multiplica o esforço total e fragmenta o entendimento. A aderência padronizada alinha todos os consumidores ao vocabulário da plataforma, reduz o custo de trocar pessoas entre times e torna a documentação da plataforma suficiente para todos.
Mecânica: adoção direta do modelo upstream
Na prática, a implementação conformist se reconhece por três marcas no código. Os DTOs do upstream atravessam a fronteira do serviço sem conversão, ou viram modelo de domínio com renomeação superficial. A persistência local grava estruturas espelhadas do upstream. A lógica de negócio do downstream consulta estados e atributos definidos pelo upstream.
# Conformist: o modelo do gateway vira o modelo do contexto, sem tradução
from gateway_pagamento.cliente import Cargo, StatusDeCargo
class ProcessadorDeCargos:
def conciliar_cargo(self, cargo: Cargo):
# o estado do upstream é tratado como estado do negócio local
if cargo.status == StatusDeCargo.SETTLED:
self.contabilidade.registrar_liquidado(
id_externo=cargo.id, # identidade do upstream como chave
valor=cargo.valor_liquido, # nomes e semântica do upstream
)
elif cargo.status == StatusDeCargo.REFUNDED:
self.contabilidade.estornar(id_externo=cargo.id)
else:
# estados desconhecidos do upstream chegam ao consumidor
self.fila_investigacao.colocar(cargo.id, motivo=cargo.status)
def resumo_por_status(cargos):
# agregação local usa o vocabulário do provedor diretamente
por_status = {}
for cargo in cargos:
por_status[cargo.status] = por_status.get(cargo.status, 0) + cargo.valor
return por_status
Repare no tratamento de estado desconhecido, que é o ponto em que a aderência cobra o preço. O upstream pode introduzir um estado novo, como chargeback_notify, e o consumidor que não esperava esse estado precisa de um caminho de fallback, tipicamente fila de investigação, para não processar errado. Em desenho conformist, essa resiliência é obrigatória justamente porque não há tradução que normalize o que chega.
Ganho de simplicidade e perda de autonomia
O trade-off do padrão é único entre as estratégias de integração, porque tudo que uma estratégia ganha a outra perde de forma simétrica. Vale explicitar os dois lados antes de decidir.
| Aspecto | Ganho com aderência | Perda com aderência |
|---|---|---|
| Código de integração | Sem tradutor, sem adaptador, sem mapeamento | Nenhum isolamento do formato externo |
| Velocidade inicial | Integração em dias, documenta-se direto do upstream | Renomear depois exige migração ampla |
| Evolução do upstream | Mudanças compatíveis são adotadas sem custo local | Mudanças incompatíveis chegam com força total |
| Qualidade do modelo | Aproveita modelo maduro de plataforma consolidada | Herda conceitos ruins, nomes ruins e decisões alheias |
| Independência de negócio | Nenhuma discussão de vocabulário entre times | Trocar de provedor exige reescrita do núcleo do contexto |
| Rastreabilidade | Logs e erros usam o mesmo vocabulário do provedor | Suporte de terceiro e time interno falam a única língua possível |
A leitura da tabela em produção costuma ser assimétrica no tempo. No primeiro trimestre, a coluna de ganhos domina, e o time entrega rápido. No terceiro ano, a coluna de perdas domina, tipicamente na troca de provedor ou na exigência regulatória que o modelo externo não contempla. A decisão correta avalia o horizonte: para integrações com previsão de vida curta ou de troca frequente de fornecedor, a aderência é péssima; para capacidades estáveis que a empresa não quer diferenciar, é eficiente.
Quando aceitar
O padrão é escolha racional em um conjunto identificável de situações:
- O upstream é um provedor externo com API madura e ampla adoção de mercado, e o domínio integrado não é diferenciador para o seu negócio.
- O upstream é uma plataforma interna consolidada, com regime de versão sério, e a empresa prefere um vocabulário único em vez de dezenas de traduções locais.
- O modelo upstream é de qualidade reconhecida, com conceitos bem definidos, e criar uma tradução só replicaria o mesmo modelo com nomes diferentes.
- O contexto downstream é de suporte, com pouca lógica própria, e a chance de o modelo local divergir do fornecido é baixa.
- A relação é de Customer-Supplier já bem estabelecida, e o downstream participou da formação do modelo upstream, de modo que aderir é endossar um modelo que já é seu em parte.
O denominador comum é a combinação de modelo upstream bom com baixa ambição de diferenciação local. Quando qualquer uma das duas condições falta, a tradução começa a se justificar.
Exemplo com API de provedor externo
O caso mais comum é a integração de checkout com provedor de pagamento. O modelo do provedor define Charge, com estados pending, authorized, settled, failed e refunded, ciclos de estorno e regras de captura parcial. Em desenho conformist, o serviço de ordens de pagamento adota esses tipos diretamente, gera os clientes a partir do schema do provedor e grava o estado da charge em tabela espelhada. O ganho aparece na velocidade: a equipe integra em duas semanas, sem desenhar modelo próprio, e a documentação do provedor serve como documentação interna.
O custo aparece nos dois cenários previsíveis. No primeiro, a empresa precisa migrar de provedor por questão comercial; como o identificador e os estados do provedor antigo atravessam o domínio, a migração vira reescrita do serviço, com conversão de dados históricos. No segundo, o negócio evolui para exigir parcelamento customizado ou split de recebíveis que o provedor não modela, e a ausência de modelo próprio impede expressar a regra, forçando soluções laterais no código. Nos dois casos, a conta do conformist é paga com juros, e a resposta correta costuma ser introduzir ACL gradualmente, começando pelo identificador e pelos estados.
Há também o custo silencioso de aprendizado. Em desenho conformist, os novos integrantes do time aprendem o domínio de pagamento pela documentação do provedor, e os conceitos internos, como política de estorno e regra de conciliação, ficam implícitos no código sem vocabulário próprio. Times que operam nesse regime por anos relatam a mesma dificuldade em entrevistas de modelagem: a linguagem ubíqua local simplesmente não existe, porque toda nomenclatura é emprestada. Esse efeito é reversível, mas só com investimento deliberado em reconstrução de vocabulário.
Comparação com outras estratégias
| Estratégia | Tradução do modelo | Acoplamento com upstream | Custo inicial | Custo em 3 anos |
|---|---|---|---|---|
| Shared Kernel | Nenhuma, código é comum | Máximo, release conjunto | Baixo | Alto, com governança |
| Customer-Supplier | Nenhuma a leve, modelo negociado | Alto, com contrato e pactos | Moderado | Moderado, sob estabilidade |
| Conformist | Nenhuma, adota o modelo alheio | Alto, unilateral | Mínimo | Depende da estabilidade do upstream |
| Anti-Corruption Layer | Total, na fronteira | Baixo, o modelo local é soberano | Alto | Baixo, mudanças externas ficam na fronteira |
Sinais de que a aderência começou a custar caro
A decisão de migrar de conformist para tradução raramente é tomada cedo demais, quase sempre é tomada tarde. Alguns sinais antecipam o ponto de inflexão:
- Regras de negócio locais começam a ser codificadas como casos especiais sobre estados do provedor, porque o modelo externo não tem conceito para elas.
- O número de condições no código que comparam texto de estado externo cresce a cada release do upstream, sem nenhuma abstração local.
- Discussões de produto trocam o nome do conceito de negócio pelo nome do campo da API, sinal de que o vocabulário externo engoliu o interno.
- A troca de provedor entra no radar comercial, e a estimativa técnica de migração assusta a gestão.
- Testes dependem de ambiente de sandbox do provedor, e a instabilidade externa vira a principal causa de pipeline vermelho.
Quando dois ou mais sinais coexistem, o plano realista é a tradução gradual: introduzir a camada por um único conceito, tipicamente o identificador ou o estado, e avançar conceito a conceito em releases normais, sem grande projeto de reescrita. A tradução gradual preserva a vantagem que motivou a aderência original, que era velocidade, enquanto devolve ao contexto o controle sobre o vocabulário e a identidade.
Erros comuns e boas práticas
| Sintoma em produção | Causa raiz | Mitigação |
|---|---|---|
| Migração de provedor vira projeto de um ano | Identidade e estados externos espalhados pelo domínio | Aderir por tipo, nunca por identidade |
| Novo estado do upstream quebra processamento | Sem caminho de fallback para estado desconhecido | Fila de investigação e handler de estado não previsto |
| Equipe não entende os próprios dados | Vocabulário do terceiro sem glossário interno | Glossário que mapeia conceito externo à operação |
| Regra de negócio sem lugar para morar | Modelo externo não expressa a regra local | Introduzir tradução parcial antes de hackear a regra |
| Testes acoplados a sandbox instável do provedor | Aderência sem contratos gravados | Gravar interações e testar contra gravações |
A prática mais valiosa em desenho conformist é a aderência seletiva, que adota tipos e estados, mas preserva identidade própria. Manter uma chave interna com a chave externa como atributo mantém a reversibilidade da decisão, e o custo extra é mínimo. A segunda prática é a resiliência de vocabulário: todo switch de estado do upstream precisa de ramificação default explícita, porque provedores adicionam estados sem pedir licença, e o consumidor sem fallback processa errado em silêncio. A terceira é registrar a decisão: um parágrafo no repositório declarando que o contexto é conformist, com a data e as condições avaliadas, transforma uma escolha em política revisável, em vez de deixar que ela se eternize por inércia.
A revisão da política merece cadência, tipicamente anual ou quando o contrato comercial do provedor é renegociado. O registro da decisão transforma a pergunta de revisão de estilização arquitetural em verificação factual: as condições que justificaram a aderência ainda valem, e a resposta alimenta ou a continuidade ou o plano de tradução gradual descrito na seção anterior.