Parei de tratar Hexagonal e Clean Architecture como rivais: a analogia da tomada resolveu
Passei anos vendo dev sênior discutir se ia usar "hexagonal" ou "clean" como se fossem religiões opostas. A real: as duas respondem a mesma pergunta e compartilham o mesmo princípio. Demorei pra sacar isso, e o que destravou foi uma analogia boba.
A tomada e o plug
Pensa na tomada da parede. Ela não conhece o formato do plug do teu carregador. Ela só expõe um contrato: "encaixa aqui, recebe energia". Quando você viaja, não quebra a parede, usa um plug adaptador.
Na hexagonal é isso:
- a porta é a tomada (um contrato do domínio)
- o adaptador é o plug do país (a implementação concreta que pluga o mundo externo)
Por isso o nome original do Alistair Cockburn (2005) era Ports and Adapters. "Hexagonal" pegou só por causa do desenho. Mesmo padrão, dois nomes.
A regra de ouro é uma só
Dependências sempre apontam pra dentro. O domínio no centro não importa nada de fora, ele só declara as portas de que precisa. Quem depende do domínio são os adaptadores da borda.
Na prática, em Java, a porta secundária que o domínio declara:
// domain/port/out/UsuarioRepository.java (PORTA secundária)
public interface UsuarioRepository {
Usuario salvar(Usuario usuario);
boolean existePorEmail(String email);
}
O serviço de domínio depende só dessa interface, sem Spring, sem ORM:
public class CadastrarUsuarioService implements CadastrarUsuario {
private final UsuarioRepository repository; // depende da PORTA, não da impl
public Usuario executar(String email) {
if (repository.existePorEmail(email))
throw new IllegalStateException("E-mail ja cadastrado");
return repository.salvar(new Usuario(UUID.randomUUID().toString(), email));
}
}
A "sujeira" de framework fica confinada no adaptador da borda (o @Repository com Spring Data, o @RestController). Ganho concreto: pra testar o service você não sobe banco nem Spring, passa um repositório falso no construtor. Migrou de Postgres pra DynamoDB? Escreve um adaptador novo, o domínio não muda uma linha.
Hexagonal vs Clean: primas, não rivais
| Hexagonal | Clean | |
|---|---|---|
| Criador/ano | Cockburn, 2005 | R. C. Martin, 2012 |
| Metáfora | hexágono com portas | círculos concêntricos |
| Foco | comunicação núcleo ↔ exterior | organização em camadas |
| Granularidade | 2 tipos de porta | 4+ camadas |
Regra comum às duas: dependência aponta pra dentro, domínio isolado de infra. A hexagonal é mais enxuta e responde "como o núcleo fala com o exterior". A Clean empilha camadas e detalha o fluxo. Muito time usa hexagonal de base e pega emprestado o conceito de use case da Clean quando a regra cresce.
Quando NÃO usar
Num CRUD simples ou num MVP que você joga fora em um mês, hexagonal é over-engineering puro, só adiciona indireção que ninguém agradece. Compensa quando: a regra de negócio é o coração do produto e cresce, tem vários pontos de entrada (REST, fila, scheduler) e vários destinos (banco, cache, serviço externo), e testabilidade importa.
Escrevi a versão completa (diagrama driving/driven, comparativo com 3-tier e os adaptadores completos) aqui, se quiser aprofundar: https://www.techknow.com.br/post/arquitetura-hexagonal-ports-adapters