Arquitetura Hexagonal: Como estruturar o projeto
Você já sentiu que seu código está “preso” ao framework? Que trocar o Spring pelo Micronaut ou o MySQL pelo DynamoDB seria um pesadelo? A Arquitetura Hexagonal (ou Ports & Adapters) resolve isso separando o que é “negócio” do que é “ferramenta”.
O Core é Sagrado
Na Arquitetura Hexagonal, o centro (Core) contém as regras de negócio puras. Ele não sabe o que é um Banco de Dados, o que é um Controller REST ou o que é o Kafka. Ele apenas expõe e consome interfaces (Ports).
graph LR
subgraph ADAPTERS_IN [Adapters de Entrada]
REST[REST Controller]
CLI[CLI]
KAFKA_IN[Kafka Consumer]
end
subgraph CORE [CORE - Hexágono Interno]
direction TB
subgraph PORTS_IN [Ports de Entrada]
S_INT[Service Interface]
end
subgraph DOMAIN [Domínio]
LOGIC[Business Logic]
MODEL[Entities]
end
subgraph PORTS_OUT [Ports de Saída]
R_INT[Repository Interface]
end
end
subgraph ADAPTERS_OUT [Adapters de Saída]
JPA[JPA / MySQL]
API_EXT[API Externa]
KAFKA_OUT[Kafka Producer]
end
REST --> S_INT
CLI --> S_INT
KAFKA_IN --> S_INT
S_INT --> LOGIC
LOGIC --> R_INT
R_INT --> JPA
R_INT --> API_EXT
R_INT --> KAFKA_OUT
A Estrutura de Pastas Sugerida
Para um projeto Java/Kotlin, uma estrutura robusta seria:
1
2
3
4
5
6
7
8
9
10
11
12
13
src/main/java/com/company/benefit
├── domain/ <-- O Coração (Hexágono Interno)
│ ├── model/ <-- Entidades puras (Account, Balance)
│ ├── service/ <-- Lógica de negócio (UseCase)
│ └── repository/ <-- Interfaces (Output Ports)
├── application/ <-- Orquestração
│ └── dto/ <-- Objetos de entrada/saída da API
└── infrastructure/ <-- O Mundo Externo (Adapters)
├── adapters/
│ ├── db/ <-- Implementações JPA/NoSQL
│ ├── web/ <-- Controllers REST
│ └── messaging/ <-- Consumidores Kafka/Rabbit
└── config/ <-- Configurações de Beans do Framework
Os Componentes Chave
- Domain: Contém a inteligência. Não deve ter dependências de infraestrutura (nada de
@Entitydo Hibernate aqui, se você for um purista). - Ports (Interfaces): Definem o contrato. “Eu preciso de alguém que salve uma conta”.
- Adapters (Implementações): São os “plugs”. O
JpaAccountRepositoryé um adaptador que se encaixa no portAccountRepository.
Exemplo de Inversão de Dependência
O segredo está em quem conhece quem:
- O Adapter conhece o Port.
- O Service conhece o Port.
- Ninguém do Core conhece o Adapter.
1
2
3
4
5
6
// infrastructure.adapters.db
@Component
public class JpaAccountAdapter implements AccountRepository { // Implementa o PORT
private final JpaRepo jpa;
public void save(Account a) { ... }
}
Vantagens Reais
- Testabilidade: Você testa o
domain.serviceusando apenas Mocks das interfaces, sem subir banco ou contexto de framework. - Longevidade: O framework pode evoluir ou mudar, mas as regras de negócio (ex: como calcular benefícios) continuam intactas no Core.
- Foco: O desenvolvedor foca no problema de negócio antes de se preocupar com a tabela do banco.
Insight Final: O Hexágono como Proteção de Investimento
A Arquitetura Hexagonal não é sobre criar mais pastas ou interfaces, é sobre proteger o seu investimento intelectual. Frameworks, bancos de dados e protocolos de comunicação são tecnologias transitórias que mudam a cada 5 ou 10 anos. Já as regras de negócio do seu domínio são o que realmente gera valor. Ao isolar o “Core” do mundo externo, você garante que sua aplicação possa evoluir tecnologicamente sem precisar ser reescrita do zero a cada mudança de tendência do mercado.