Código gerado por IA costuma chegar rápido ao estado em que "funciona". O problema é que funcionar não significa ser legível, substituível, testável ou seguro de evoluir. Um sistema pode passar nos fluxos principais e, ainda assim, esconder uma arquitetura frágil: regras duplicadas, módulos com responsabilidades empilhadas, integrações coladas no domínio e arquivos onde qualquer mudança vira risco.
Review de arquitetura existe para atacar essa camada. Ele não pergunta apenas se a feature está pronta. Ele pergunta se o código que acabou de nascer pode ser mantido por outra pessoa, receber novas funcionalidades e sobreviver a uma troca de ferramenta, provedor ou regra de negócio sem refatoração traumática.
Para fazer esse diagnóstico sem cair em opinião vaga, use um vocabulário pequeno e disciplinado. Os nove conceitos abaixo formam um framework prático para olhar uma codebase, encontrar os pontos de risco e transformar o diagnóstico em uma refatoração objetiva.
O Que Um Review de Arquitetura Deve Procurar
Um bom review separa três perguntas que muita gente mistura:
- O sistema faz o que promete? Essa é a pergunta de produto e teste funcional.
- O código deixa claro onde cada decisão mora? Essa é a pergunta de modularidade.
- O próximo comportamento será barato de implementar? Essa é a pergunta de arquitetura.
A terceira pergunta é a mais negligenciada em projetos acelerados por IA. O modelo tende a otimizar para entrega local: criar o arquivo, chamar a API, salvar no banco, renderizar a tela. Sem uma revisão explícita, ele raramente paga o custo de desenhar bons limites entre domínio, infraestrutura e adapters.
Módulo
Um módulo é uma peça de código com uma responsabilidade clara. A regra prática é simples: se a descrição precisa de vários "e", provavelmente o módulo está carregando mais coisa do que deveria.
EmailValidator validar e-mail é um módulo plausível. Um arquivo que valida e-mail, consulta CPF, calcula frete, formata moeda e decide permissão de usuário é apenas um depósito de regras. Ele pode funcionar, mas toda correção futura exigirá entender comportamentos que não pertencem ao mesmo assunto.
O objetivo não é criar muitos arquivos por estética. É criar fronteiras que representem decisões reais do sistema.
Interface
Interface é o contrato público de um módulo: o que o chamador precisa entregar, o que recebe de volta e quais detalhes não precisa conhecer. Não é sinônimo de tela. Uma função, um endpoint, uma classe, uma fila e um pacote interno também expõem interfaces.
Uma interface boa reduz conhecimento acidental. Quem chamacreateAccount(document) não deveria precisar conhecer a sequência interna de validação cadastral, análise de risco, criação de usuário e gravação de evento. Se o chamador precisa orquestrar tudo isso manualmente, a interface está vazando detalhes.
Profundidade
Um módulo profundo esconde bastante comportamento por trás de uma interface pequena. Um módulo raso expõe quase tanto trabalho quanto executa. Essa diferença é central para entender por que algumas abstrações ajudam e outras só adicionam indireção.
Profundidade não significa mágica. Significa que o módulo carrega conhecimento coeso do domínio e poupa o resto do sistema de repetir esse conhecimento. O risco oposto é o wrapper vazio: uma função que apenas repassa parâmetros para outra sem reduzir complexidade. Esse tipo de camada costuma falhar no teste de deleção.
Seam
Um seam é um ponto de encaixe que permite trocar uma peça sem mexer no restante do sistema. Ele é especialmente importante em integrações externas: pagamento, e-mail, storage, autenticação, analytics, motor de busca e provedores de IA.
Sem seam, a aplicação passa a conhecer detalhes da Stripe, do Pagar.me, do provedor de e-mail ou do banco em dezenas de pontos. Com seam, o domínio fala com um contrato estável e o detalhe concreto fica na borda.
type PaymentProvider = {
charge(input: ChargeInput): Promise<ChargeResult>;
};
const checkout = async (provider: PaymentProvider, order: Order) => {
const result = await provider.charge(toChargeInput(order));
return confirmOrderPayment(order.id, result);
};Esse contrato não precisa nascer perfeito. Ele precisa nascer no lugar certo: entre a regra do negócio e o fornecedor externo.
Adapter
Adapter é a implementação concreta que se encaixa no seam. UmStripePaymentProvider e um PagarmePaymentProvider podem obedecer ao mesmo contrato, mesmo que cada API externa tenha payloads, autenticação e erros diferentes.
O ganho aparece quando a troca de fornecedor deixa de ser uma cirurgia no sistema inteiro e vira uma decisão localizada. Ainda haverá trabalho: mapear erros, conciliar webhooks, revisar idempotência e testar casos de falha. Mas esse trabalho fica confinado na borda, não espalhado pelo domínio.
Leverage
Leverage é o ganho que o chamador recebe por usar o módulo. Um bom módulo não apenas encapsula código; ele entrega uma capacidade mais rica do que o chamador conseguiria montar com facilidade.
Uma busca de produtos com leverage não faz só WHERE name LIKE query. Ela pode normalizar acentos, tratar sinônimos, considerar estoque, relevância, categoria e histórico de compra. O chamador pede "tênis"; o módulo aplica conhecimento de busca.
Locality
Locality é o ganho do mantenedor: quando uma regra muda, quantos lugares precisam ser abertos? Alta locality significa que o trabalho está concentrado no módulo correto. Baixa locality significa que a regra está duplicada, escondida ou atravessando camadas.
Se um bug de frete exige alterar checkout, carrinho, página de produto, webhook e job de conciliação, o problema talvez não seja o bug. Talvez seja a ausência de um módulo que concentre a regra de cálculo e as invariantes do frete.
Hotspot
Hotspot é o arquivo onde a dor se acumula. Normalmente ele aparece como um serviço grande, com muitas responsabilidades, muitos commits recentes e alto medo de alteração. O nome pode variar:OrderService, MatchService, UserManager, PipelineRunner.
Hotspots são bons candidatos para review porque concentram risco real. Eles mostram onde a arquitetura está cobrando juros: qualquer feature encosta ali, qualquer bug passa por ali e qualquer refatoração parece perigosa demais para começar.
Teste de Deleção
O teste de deleção é um exercício mental: se esse módulo desaparecesse, o sistema perderia uma capacidade real ou apenas uma camada de repasse? Se uma função pode ser substituída por uma linha simples sem perda de clareza, talvez ela não mereça existir.
Esse teste evita uma reação comum ao código bagunçado: criar abstrações demais. Modularizar não é embrulhar tudo. É separar o que tem responsabilidade própria, esconder complexidade útil e apagar camadas que não carregam decisão nenhuma.
O Pipeline de Review em 6 Fases
Os conceitos acima viram prática quando entram em um pipeline. A ideia não é pedir para a IA "melhorar a arquitetura" de forma genérica. Isso gera sugestões soltas. O review precisa produzir diagnóstico, decisão e uma spec implementável.
- Zoom out: mapear domínios, módulos, fluxos principais, integrações, vocabulário da codebase e hotspots.
- Seleção de candidatos: escolher poucos pontos onde profundidade, locality ou seams parecem fracos.
- Diagnóstico: explicar a causa raiz com evidências de arquivos, chamadas, responsabilidades e regras espalhadas.
- Grill-me: pressionar alternativas, trade-offs, riscos de migração e critérios de aceite antes de escolher a solução.
- Decisões: registrar o que será criado, movido, preservado e testado.
- Spec: transformar a decisão em passos implementáveis, com arquivos afetados, contratos esperados e validações.
Exemplo: Quando Um Serviço de Jogo Faz Trabalho Demais
Imagine um sistema de xadrez onde MatchServicevalida o turno, aplica o lance do usuário, chama o motor externo, aplica o lance do motor, persiste movimentos, atualiza o FEN, finaliza a partida e calcula alteração de ranking. O serviço funciona, mas a responsabilidade de "comitar um turno" está dissolvida em várias decisões menores.
O diagnóstico arquitetural não deve ser "quebrar o arquivo em partes". Esse diagnóstico é raso. A pergunta correta é: qual responsabilidade profunda está faltando? Nesse caso, o candidato pode ser um módulo de commit atômico de turno, responsável por persistir o lance, atualizar o estado da partida, aplicar finalização e garantir idempotência em uma fronteira transacional.
Essa decisão melhora locality porque a regra de commit passa a morar em um lugar. Melhora leverage porque outros fluxos podem usar uma interface mais forte. E melhora testabilidade porque o commit pode ser exercitado sem atravessar toda a orquestração do motor de xadrez.
Trade-offs: Arquitetura Boa Não É Mais Camadas
Existe um erro comum depois que alguém aprende esses conceitos: transformar qualquer arquivo em uma coleção de interfaces, adapters, factories e services. Isso apenas muda o problema de lugar. O código deixa de ser um bloco grande e vira um labirinto de peças pequenas sem leverage.
A arquitetura melhora quando uma nova fronteira reduz complexidade total. Um seam vale a pena quando existe risco real de troca, isolamento de fornecedor, teste ou política de negócio. Um adapter vale a pena quando há detalhe externo para esconder. Um módulo profundo vale a pena quando concentra regra que seria duplicada ou orquestrada manualmente.
Em projetos pequenos, alguns seams serão hipotéticos. Tudo bem. O ponto é não vender flexibilidade infinita como virtude. O review deve justificar cada separação pelo custo que ela remove agora ou pelo risco que ela reduz no próximo ciclo de evolução.
Como Usar IA Nesse Processo Sem Delegar o Juízo
A IA é útil para mapear a codebase, listar fluxos, encontrar hotspots, comparar alternativas e redigir uma spec. Mas ela não deve decidir sozinha o que é arquitetura boa. O papel humano é validar se a fronteira proposta representa uma decisão real do negócio ou apenas uma reorganização estética.
Um prompt útil para começar um review é:
"Mapeie os módulos, interfaces, seams, adapters e hotspots desta codebase. Depois escolha três candidatos de refatoração e explique a causa raiz usando locality, leverage e profundidade."
A resposta ainda precisa ser auditada. Peça evidências por arquivo, force alternativas e só avance para implementação quando houver uma decisão clara, testável e proporcional ao tamanho do problema.
O Resultado Esperado
Um review de arquitetura não promete deixar o sistema mais bonito. Ele também não garante performance imediata. O ganho principal é reduzir o custo de mudança: menos medo de mexer, menos regra duplicada, menos fornecedor infiltrado no domínio, menos arquivo onde tudo acontece.
Esse ganho é futuro, mas não é abstrato. Ele aparece quando uma nova pessoa entra no projeto e entende onde alterar. Aparece quando uma feature encosta em um módulo pequeno e coeso em vez de atravessar um serviço de milhares de linhas. Aparece quando uma troca de provedor exige criar um adapter novo, não redesenhar o produto.
Em resumo: código gerado por IA precisa de review de arquitetura justamente porque ele chega rápido ao funcional. Os nove conceitos ajudam a enxergar se esse funcional também é sustentável: módulos claros, interfaces pequenas, seams bem posicionados, adapters nas bordas, leverage real, locality alta, hotspots identificados e abstrações que sobrevivem ao teste de deleção.