Comparação - Hexagonal vs Clean vs Camadas
O problema comum que todas tentam resolver
Seção intitulada “O problema comum que todas tentam resolver”As três buscam responder à mesma pergunta: como impedir que detalhes de tecnologia (banco, framework web, mensageria) contaminem as regras de negócio? A diferença está em como organizam o código e para onde apontam as dependências.
O ponto de virada é a Inversão de Dependência. Sem ela, “camadas” acaba com o domínio dependendo do banco. Com ela, o domínio define interfaces e a infraestrutura as implementa — que é exatamente o que Hexagonal e Clean formalizam.
Camadas tradicional (N-tier)
Seção intitulada “Camadas tradicional (N-tier)”graph TD
UI["Apresentação<br/>(Controllers)"] --> BLL["Regras de Negócio<br/>(Services)"]
BLL --> DAL["Acesso a Dados<br/>(Repositories/DAO)"]
DAL --> DB[("Banco de Dados")]
A dependência flui de cima para baixo até o banco. O problema clássico: a camada de negócio depende da camada de dados, e frequentemente dos tipos do ORM/JPA. O domínio passa a “conhecer” a tecnologia. Tende ao modelo anêmico e a regras espalhadas nos services.
Hexagonal (Ports and Adapters)
Seção intitulada “Hexagonal (Ports and Adapters)”graph LR
REST["Adapter REST"] --> DP["Driving Port"]
DP --> CORE(("Núcleo<br/>Domínio + Aplicação"))
CORE --> DVP["Driven Port"]
DVP -.implementada por.-> JPA["Adapter JPA"]
Organiza o mundo em dentro (núcleo com o domínio) e fora (adapters de tecnologia), conectados por portas. Ver Driving e Driven. Não impõe número de camadas internas; a fronteira é o hexágono.
Clean Architecture
Seção intitulada “Clean Architecture”graph TD
subgraph Externo
FW["Frameworks & Drivers<br/>(Spring, JPA, Web)"]
IA["Interface Adapters<br/>(Controllers, Gateways, Presenters)"]
end
subgraph Interno
UC["Use Cases"]
ENT["Entities"]
end
FW --> IA --> UC --> ENT
Detalha o dentro em círculos concêntricos com a Regra da Dependência: o código-fonte só aponta para dentro. É mais prescritiva sobre as camadas internas (Entities, Use Cases, Interface Adapters, Frameworks). Ver Camadas da Clean Architecture.
Tabela comparativa
Seção intitulada “Tabela comparativa”| Aspecto | Camadas tradicional | Hexagonal | Clean |
|---|---|---|---|
| Autor | difuso (anos 90) | Alistair Cockburn (2005) | Robert C. Martin (2012) |
| Metáfora | pilha de camadas | hexágono com portas | círculos concêntricos |
| Direção da dependência | de cima para baixo (até o DB) | de fora para o núcleo | de fora para dentro |
| Isolamento do domínio | fraco (vaza tecnologia) | forte (portas) | forte (regra da dependência) |
| Prescrição de camadas internas | services + DAOs | livre (só define a fronteira) | rígida (Entities/Use Cases/…) |
| Inversão de dependência | opcional (e por isso rara) | central | central |
| Vocabulário | camada, service, DAO | porta, adapter, driving/driven | entity, use case, boundary, gateway |
Como enxergar a equivalência
Seção intitulada “Como enxergar a equivalência”O mapeamento entre os vocabulários deixa claro que Hexagonal e Clean descrevem quase a mesma estrutura:
| Hexagonal | Clean Architecture |
|---|---|
| Núcleo (domínio) | Entities |
| Serviço de aplicação / driving port | Use Case + Input Boundary |
| Driven port (ex: repositório) | Output Boundary / Gateway (interface) |
| Adapter primário (controller) | Interface Adapter (Controller) |
| Adapter secundário (gateway JPA, client HTTP) | Interface Adapter (gateway); o driver/ORM em si é Frameworks & Drivers |
Ver o desenvolvimento completo em Como Tudo se Conecta.
O mesmo caso de uso, lado a lado
Seção intitulada “O mesmo caso de uso, lado a lado”A equivalência fica visível colocando a mesma transferência bancária nas duas estruturas — os artefatos são um a um os mesmos, só mudam de crachá:
| Artefato (transferir dinheiro) | No projeto Hexagonal | No projeto Clean |
|---|---|---|
Regra de negócio (Conta, Dinheiro) |
domain/ |
domain/ (Entities) |
| Contrato do caso de uso | port/in/TransferirUseCase |
port/in/TransferirInputPort |
| Implementação do caso de uso | service/TransferenciaService |
usecase/TransferirInteractor |
| Contrato de persistência | port/out/ContaRepository |
port/out/ContaGateway |
| Tradução HTTP | rest/TransferenciaRestController |
web/TransferenciaController |
| Persistência concreta | persistence/ContaJpaAdapter |
persistence/ContaGatewayJpaAdapter |
O diff real entre Exemplo Hexagonal com Spring e Exemplo Clean com Spring se resume a um ponto: a Clean canônica acrescenta o output port + presenter para desacoplar também a apresentação, enquanto o Hexagonal pragmático devolve o resultado pelo próprio caso de uso.
Qual escolher
Seção intitulada “Qual escolher”Nenhuma delas é gratuita: portas, boundaries e mapeamentos entre modelos custam código. Em um CRUD anêmico isso é cerimônia sem retorno. O gatilho para adotá-las é domínio com regras que valem a pena proteger — normalmente onde DDD também faz sentido.
Anti-padrões e erros comuns
Seção intitulada “Anti-padrões e erros comuns”- “Hexagonal com camadas por dentro”: criar
serviceque chamarepositoryconcreto e chamar isso de hexagonal. Sem porta invertida, é só N-tier renomeada. - Clean cerimonial em CRUD: input/output boundaries, presenters e request models para um cadastro trivial. Custo alto, benefício nulo.
- Mapear tudo em todo lugar: exageros de DTOs entre camadas viram boilerplate. Mapeie nas fronteiras que realmente isolam.
- Confundir camada física (pacote) com camada lógica: a regra da dependência é sobre dependência de código, não sobre pastas.
Relações
Seção intitulada “Relações”- Arquitetura Hexagonal
- Clean Architecture
- Como Tudo se Conecta
- DIP - Dependency Inversion Principle
- Domain-Driven Design
Perguntas de revisão
Seção intitulada “Perguntas de revisão”- Por que a arquitetura em camadas tradicional costuma falhar em isolar o domínio, mesmo tendo uma camada de negócio separada?
Resposta
Porque a dependência aponta para baixo, até o banco. A camada de negócio depende da de dados (e dos tipos do ORM), então a tecnologia vaza para dentro do domínio. Falta a inversão de dependência que Hexagonal e Clean tornam central.
- Qual conceito de Clean corresponde a uma driven port da Hexagonal?
Resposta
A output boundary / gateway (uma interface definida por dentro e implementada na camada externa), por exemplo o repositório.
- Quando adotar Clean em vez de Hexagonal?
Resposta
Quando você quer disciplina explícita e prescritiva sobre as camadas internas e os boundaries (Entities, Use Cases, Interface Adapters), tipicamente em sistemas/times maiores. Hexagonal dá a mesma proteção com menos prescrição interna.
- Qual princípio SOLID é o mecanismo comum que faz as três “seções cruzadas” funcionarem?
Resposta
O DIP: módulos de alto nível e detalhes dependem de abstrações; o detalhe (infra) implementa a interface definida pelo núcleo.