6 de Agosto de 2025
Contrato interno entre módulos sem inventar RPC dentro do mesmo app
Separar módulos não deveria obrigar o time a fingir rede, versão e protocolo distribuído dentro de um monólito que ainda é um único deploy.
Andrews Ribeiro
Founder & Engineer
3 min Intermediario Sistemas
O problema
Quando o time começa a modularizar um backend, aparecem dois extremos ruins.
Primeiro extremo:
- qualquer módulo importa qualquer coisa
- query atravessa contexto
- regra interna vaza sem cerimônia
Segundo extremo:
- cada chamada local vira pseudo-API
- cada módulo ganha client, DTO, facade e versão
- o monólito passa a fingir que é uma malha de microservices
Os dois extremos cansam a base.
O primeiro por frouxidão.
O segundo por teatro.
Modelo mental
Contrato interno não é igual a protocolo distribuído.
Contrato interno serve para responder:
- por onde esse módulo deve ser usado?
- o que ele promete?
- o que ele espera?
- o que pode mudar por dentro sem quebrar outros?
Dentro do mesmo app, isso normalmente pode ser resolvido com:
- interface pequena
- porta de entrada clara
- tipos internos coerentes
- semântica explícita de erro e resultado
Sem fingir latência, versionamento e serialização onde ainda não existe rede.
O que costuma ser suficiente
Num monólito modular, muitas vezes basta que outro módulo fale com você por:
- um use case público
- uma facade interna pequena
- um serviço de aplicação bem nomeado
- eventos internos quando fizer sentido desacoplar
O importante é existir um ponto de entrada reconhecível.
Não é obrigar cada chamada local a parecer HTTP.
Exemplo simples
Imagine orders precisando perguntar algo a billing.
Uma solução ruim de frouxidão:
ordersimporta repository debilling- consulta tabela de cobrança direto
Uma solução ruim de teatro:
billingexpõe pseudo-client interno- payload serializado
- response envelope
- mapeamento como se fosse chamada remota
Uma solução mais saudável:
billingexpõe uma porta interna clara, comocheckChargeabilityougetAccountStandingordersdepende dessa semântica, não dos detalhes internos
O contrato existe.
Mas o time não precisou encenar rede.
Quando evento interno ajuda
Às vezes o melhor contrato nem é chamada direta.
Se o módulo só precisa reagir a um fato, evento interno pode ser mais adequado.
Exemplos:
- pedido confirmado
- usuário bloqueado
- assinatura cancelada
Mas o mesmo critério vale:
evento interno útil não é substituto genérico para qualquer chamada.
Se um módulo precisa de resposta imediata para decidir agora, talvez evento não seja a forma certa.
O erro comum
O erro comum é importar a discussão de microservices sem olhar o runtime real.
Se ainda é:
- mesmo deploy
- mesmo processo
- mesma base
talvez o melhor contrato interno seja mais leve.
Do contrário, você duplica custo mental sem ganhar isolamento proporcional.
Como um senior pensa
Quem decide melhor costuma perguntar:
- esse módulo precisa de fronteira explícita ou de protocolo teatral?
- quem pode chamar isso e por onde?
- qual dependência estou tentando proteger?
- estou preparando extração futura com bom senso ou só carregando custo agora?
Essa leitura costuma produzir limites melhores e menos teatrais.
Ângulo de entrevista
Esse tema aparece em perguntas sobre modular monolith, service boundaries e evolução de arquitetura.
O entrevistador quer ver se você:
- sabe criar limite interno real
- evita tanto acoplamento livre quanto abstração cênica
- entende que contrato interno não é cópia de API pública
Resposta forte costuma soar assim:
“Eu criaria um ponto de entrada explícito por módulo, com semântica interna clara, mas evitaria simular RPC dentro do mesmo app. O objetivo é proteger fronteira e reduzir acoplamento, não fingir distribuição antes da hora.”
Takeaway direto
Contrato interno bom faz o módulo ficar mais previsível.
Não faz o monólito atuar como se estivesse num congresso de microservices.
Resumo rápido
O que vale manter na cabeça
- Módulo interno precisa de contrato claro, mas não precisa simular RPC só para parecer distribuído.
- Contrato interno bom define intenção, dependência e semântica; não necessariamente HTTP, versionamento e serialização.
- Se tudo pode chamar tudo, a modularização é decorativa.
- Se cada chamada local exige teatro de integração, o time comprou complexidade antes da hora.
Checklist de pratica
Use isto ao responder
- Consigo dizer por onde um módulo deveria ser usado pelos outros?
- Meu contrato interno expressa intenção de negócio ou só replica detalhes de implementação?
- Estou forçando protocolo de rede onde bastava uma fronteira de código mais explícita?
- Se um módulo mudar por dentro, os outros continuam estáveis?
Você concluiu este artigo
Próximo passo
Monólito modular na prática Próximo passo →Compartilhar esta página
Copie o link manualmente no campo abaixo.