A arquitetura hexagonal é um padrão de design que isola a lógica de negócio das tecnologias externas por meio de ports (interfaces) e adapters (implementações). Dessa forma, o núcleo da aplicação não sabe se os dados vêm de um Postgres ou de um arquivo. Neste guia você vai entender, na prática com código Java, a diferença para a Clean Architecture e quando o padrão vale a pena.

O padrão foi criado e nomeado como “Ports and Adapters” por Alistair Cockburn em 2005. Na prática, a ideia era resolver um problema que todo dev sênior já viu: a regra de negócio grudada no framework, no ORM e no formato de entrada. Como resultado, ninguém consegue testar nem trocar nada sem quebrar tudo. Se você está começando agora, calma: vamos partir de uma analogia simples antes de qualquer linha de código.

O que é arquitetura hexagonal e como funciona

A arquitetura hexagonal coloca a lógica de negócio no centro e conecta o mundo externo através de interfaces bem definidas. Em outras palavras, o domínio da aplicação vive isolado, e tudo que é “detalhe técnico” (web, banco, mensageria) fica na borda, plugado por adaptadores. Alistair Cockburn desenhou esse modelo como um hexágono justamente para fugir do diagrama tradicional de camadas empilhadas, que sugeria uma hierarquia rígida de cima pra baixo.

A analogia da tomada e do plug

Por exemplo, vamos a uma analogia que resolve a confusão de vez. Pense numa tomada padrão na parede da sua casa. Afinal, a parede não conhece o formato do plug do seu carregador. Por isso, ela só expõe um contrato: “encaixe aqui e receba energia”. Da mesma forma, quando você viaja, não quebra a parede para usar o carregador de outro país. Em vez disso, você usa um plug adaptador. Na arquitetura hexagonal, a porta é a tomada na parede, ou seja, um contrato do domínio. Já o adaptador é o plug do país: a implementação concreta que conecta o mundo externo àquela porta.

Por isso o padrão também é chamado de “portas e adaptadores”. Aliás, vale deixar explícito para quem está pesquisando: ports and adapters é exatamente o mesmo que arquitetura hexagonal. “Ports and Adapters” foi o nome original de Cockburn; “hexagonal” pegou por causa do desenho. Ou seja, não são dois padrões diferentes, e sim dois nomes para a mesma coisa.

Na prática, a regra de ouro é uma só: as dependências sempre apontam para dentro. De fato, o domínio no centro não importa nada de fora, ele apenas declara as portas de que precisa. Por outro lado, os adaptadores externos é que dependem do domínio. Dessa forma, você troca o banco, o framework web ou o provedor de e-mail. E faz isso sem tocar em uma única regra de negócio. A AWS, inclusive, documenta a arquitetura hexagonal como padrão recomendado para desacoplar a lógica de negócio da infraestrutura. Segundo a AWS, isso facilita testes e a substituição de serviços de nuvem.

Ports e adapters: as peças do padrão com exemplo em código

Diagrama da arquitetura hexagonal: núcleo no centro, adaptadores primários à esquerda, adaptadores secundários e banco de dados à direita, com dependências apontando para dentro
Diagrama ports and adapters: adaptadores primários (driving) à esquerda, secundários (driven) à direita, dependências apontando para o núcleo.

De fato, as peças da arquitetura hexagonal são o domínio, as portas primárias e secundárias, e os adaptadores driving e driven. Antes do código, vale separar dois lados que confundem muita gente. Primeiro, de um lado ficam os adaptadores que acionam a aplicação; de outro, os que a aplicação aciona. Veja a distinção com calma.

  • Porta primária (driving): o contrato que o mundo externo usa para chamar o domínio. É a API de entrada da sua regra de negócio. Exemplo: uma interface CadastrarUsuario.
  • Adaptador primário (driving): quem aciona o domínio por essa porta. Um controller REST, um consumer de fila, um comando de CLI. Ele traduz o request externo em chamada de domínio.
  • Porta secundária (driven): o contrato que o domínio usa para pedir algo ao mundo externo. Exemplo: uma interface UsuarioRepository declarada no domínio.
  • Adaptador secundário (driven): a implementação concreta dessa porta. Um repositório JPA, um cliente HTTP, um envio de e-mail.

Exemplo de arquitetura hexagonal em Java e Spring Boot

Vamos agora ao código. Segundo a Stack Overflow Developer Survey 2024, 30% dos desenvolvedores profissionais usam Java, então montamos um caso de cadastro de usuário em Spring Boot. Primeiro, o domínio puro, sem nenhuma anotação de framework. Além disso, repare que a entidade não conhece o banco.

Java
// domain/Usuario.java - entidade pura, zero dependência externa
public class Usuario {
    private final String id;
    private final String email;

    public Usuario(String id, String email) {
        if (email == null || !email.contains("@")) {
            throw new IllegalArgumentException("E-mail invalido");
        }
        this.id = id;
        this.email = email;
    }

    public String getId() { return id; }
    public String getEmail() { return email; }
}

Em seguida, as portas. Ou seja, a porta primária é o que o mundo externo pode pedir ao domínio. Por outro lado, a porta secundária é o que o domínio precisa do mundo externo. Ambas são apenas interfaces.

Java
// application/port/in/CadastrarUsuario.java - PORTA PRIMARIA (driving)
public interface CadastrarUsuario {
    Usuario executar(String email);
}

// application/port/out/UsuarioRepository.java - PORTA SECUNDARIA (driven)
public interface UsuarioRepository {
    Usuario salvar(Usuario usuario);
    boolean existePorEmail(String email);
}

Depois vem o caso de uso. Assim, ele implementa a porta primária e depende apenas da porta secundária, nunca de uma classe concreta. Assim, o serviço não sabe se o repositório é JPA, MongoDB ou um mapa em memória.

Java
// application/CadastrarUsuarioService.java - logica de negocio no centro
public class CadastrarUsuarioService implements CadastrarUsuario {

    private final UsuarioRepository repository; // depende da PORTA, nao do banco

    public CadastrarUsuarioService(UsuarioRepository repository) {
        this.repository = repository;
    }

    @Override
    public Usuario executar(String email) {
        if (repository.existePorEmail(email)) {
            throw new IllegalStateException("E-mail ja cadastrado");
        }
        Usuario novo = new Usuario(UUID.randomUUID().toString(), email);
        return repository.salvar(novo);
    }
}

Por fim, os adaptadores na borda. Por exemplo, o adaptador primário é o controller REST, que traduz o HTTP em chamada de domínio. O adaptador secundário implementa a porta de saída usando o Spring Data. Toda a “sujeira” de framework fica confinada aqui fora.

Java
// adapter/in/web/UsuarioController.java - ADAPTADOR PRIMARIO (driving)
@RestController
@RequestMapping("/usuarios")
public class UsuarioController {

    private final CadastrarUsuario cadastrarUsuario; // usa a PORTA

    public UsuarioController(CadastrarUsuario cadastrarUsuario) {
        this.cadastrarUsuario = cadastrarUsuario;
    }

    @PostMapping
    public ResponseEntity<String> criar(@RequestBody Map<String, String> body) {
        Usuario u = cadastrarUsuario.executar(body.get("email"));
        return ResponseEntity.status(201).body(u.getId());
    }
}

// adapter/out/persistence/JpaUsuarioRepository.java - ADAPTADOR SECUNDARIO (driven)
@Repository
public class JpaUsuarioRepository implements UsuarioRepository {

    private final SpringDataUsuario springData; // o ORM fica escondido aqui

    public JpaUsuarioRepository(SpringDataUsuario springData) {
        this.springData = springData;
    }

    @Override
    public Usuario salvar(Usuario usuario) {
        UsuarioEntity e = springData.save(new UsuarioEntity(usuario));
        return e.toDomain();
    }

    @Override
    public boolean existePorEmail(String email) {
        return springData.existsByEmail(email);
    }
}

Repare no ganho concreto: para testar o CadastrarUsuarioService, você não sobe banco nem Spring. Em seguida, basta passar um UsuarioRepository falso no construtor. E se amanhã o time migrar de Postgres para DynamoDB, você escreve um novo adaptador secundário e nada no domínio muda. Portanto, é esse desacoplamento que a arquitetura hexagonal entrega.

Publicidade

Arquitetura hexagonal vs Clean Architecture: qual a diferença

A diferença principal é o foco. De fato, a arquitetura hexagonal se concentra na comunicação entre o núcleo e o mundo externo via portas. Já a Clean Architecture organiza o código em camadas concêntricas com regras de dependência mais detalhadas. Na prática, as duas compartilham o mesmo princípio central, ou seja, dependências apontando para dentro e domínio isolado de infraestrutura. Ou seja, elas são primas, não rivais.

Se você já leu nosso guia de Clean Architecture, vai reconhecer o parentesco na hora. Primeiro, a hexagonal é mais enxuta e responde uma pergunta específica: como o núcleo fala com o exterior. Já a Clean Architecture, proposta por Robert Martin, empilha camadas como entidades, casos de uso, adaptadores de interface e frameworks. Além disso, ela detalha o fluxo de controle entre elas. Veja a comparação direta na tabela abaixo.

CritérioArquitetura HexagonalClean Architecture
Criador / anoAlistair Cockburn, 2005Robert C. Martin, 2012
Metáfora visualHexágono com portas nas bordasCírculos concêntricos
Foco principalComunicação núcleo ↔ exteriorOrganização em camadas e fluxo de dependência
GranularidadeMais simples (2 tipos de porta)Mais detalhada (4+ camadas)
Regra comumDependências apontam para dentro; domínio isolado da infraestrutura
Melhor paraIsolar I/O e maximizar testabilidadeProjetos grandes com muitas regras de negócio

Nossa visão prática: não escolha entre elas por ideologia. Na prática, muitos times usam a hexagonal como base e tomam emprestado o conceito de casos de uso da Clean quando a regra de negócio cresce. Além disso, ambas casam bem com Domain Driven Design e com os princípios SOLID, que são a fundação por trás desse desacoplamento todo.

Arquitetura hexagonal vs arquitetura em camadas (3-tier)

A arquitetura em camadas empilha o código em três blocos horizontais: apresentação, negócio e dados. Por outro lado, a hexagonal coloca o negócio no centro e conecta tudo por portas. Se você está saindo do modelo tradicional, essa comparação ajuda a enxergar o que a hexagonal melhora. De fato, no 3-tier clássico, a camada de negócio quase sempre importa a camada de dados. Ou seja, a regra de negócio depende do banco. Consequentemente, testar a lógica sem subir o banco vira um pesadelo.

Na prática, na hexagonal essa seta se inverte. Ou seja, o domínio não depende do banco; o banco (via adaptador) é que depende de uma porta declarada no domínio. Além disso, o modelo em camadas trata a interface web como algo “acima” e o banco como algo “abaixo”. É como se fossem coisas de natureza diferente. Por isso, a hexagonal enxerga ambos como o que realmente são: detalhes externos plugáveis. Assim, web e banco entram pela mesma lógica de portas e adaptadores, um de cada lado.

Para um projeto simples, o 3-tier funciona muito bem e é mais rápido de escrever. Todavia, aos poucos surgem múltiplos pontos de entrada (REST, fila, agendador) e múltiplos destinos (banco, cache, serviço externo). Nesse cenário, o acoplamento do modelo em camadas começa a doer. É aí que a inversão de dependências da hexagonal paga o próprio custo.

Quando usar arquitetura hexagonal (e quando é over-engineering)

A arquitetura hexagonal compensa em sistemas com domínio complexo, múltiplos pontos de entrada e saída, e exigência alta de testabilidade. Por outro lado, ela é claramente over-engineering num CRUD simples. Da mesma forma, o mesmo vale para um MVP que você talvez jogue fora em um mês. Vamos ser honestos: aplicar hexagonal num cadastro básico só adiciona camadas de indireção que ninguém vai agradecer.

Recomendamos adotar o padrão quando pelo menos alguns destes sinais aparecem no seu projeto:

  • A regra de negócio é o coração do produto e tende a crescer, indo além de repassar dados do banco para a tela.
  • Existem vários adaptadores de entrada ou saída: REST, GraphQL, filas, jobs, integrações com terceiros.
  • Testes rápidos e isolados da lógica são um requisito real, não um desejo vago.
  • Há chance concreta de trocar tecnologias de infraestrutura ao longo da vida do sistema.

Em contrapartida, preferimos o bom e velho CRUD em camadas quando o domínio é raso, o prazo é curto e o time é pequeno. Como resume o livro Arquitetura de software: as partes difíceis, quase toda decisão de arquitetura é uma análise de trade-off. Portanto, não existe escolha certa universal. Logo, a pergunta honesta não é “qual arquitetura é a melhor”, mas “qual problema eu tenho para resolver agora”.

Essa mentalidade de trade-offs é o que separa o júnior que decora padrões do sênior que decide bem. Por isso, vale internalizar que arquitetura é sobre acoplamento, granularidade de serviços e comunicação entre partes. Além disso, são exatamente esses pontos que a hexagonal ajuda a organizar no dia a dia.

Para aprofundar nesse raciocínio de trade-offs, uma boa referência em português é o livro Arquitetura de software: as partes difíceis (Alta Books), que destrincha justamente as decisões de acoplamento, granularidade de serviços e comunicação que a hexagonal ajuda a organizar.

Capa do livro Arquitetura de Software: As Partes Dificeis, da O'Reilly
Arquitetura de Software: As Partes Dificeis
★ 4,9 (487) · Neal Ford, Mark Richards, Pramod Sadalage & Zhamak Dehghani · O’Reilly / Alta Books

Conclusão

A arquitetura hexagonal resolve um problema antigo de forma elegante: manter a regra de negócio limpa e independente do framework, do banco e da interface. Portanto, guarde apenas uma ideia deste guia: a analogia da tomada. De fato, a porta é o contrato na parede; o adaptador é o plug do país. Você troca o plug quando muda de tecnologia, nunca a parede que é o seu domínio.

Portanto, para colocar isso em prática, siga um caminho simples. Primeiro, isole seu domínio sem anotações de framework. Em seguida, declare as portas de entrada e de saída como interfaces. Por fim, empurre toda a “sujeira” técnica para adaptadores na borda. Além disso, comece pequeno, aplicando num módulo que realmente tenha regra de negócio e sinta o ganho na hora de escrever testes. E lembre-se: hexagonal é uma ferramenta, não uma religião. Use quando o problema pedir, e não terá arrependimentos.

Publicidade

O que é o formato hexagonal do padrão?
O hexágono é apenas uma metáfora visual escolhida por Alistair Cockburn para mostrar o domínio no centro com várias portas nas bordas. O número seis não tem significado técnico; ele só evita o diagrama de camadas empilhadas e deixa espaço para desenhar múltiplas portas de entrada e saída ao redor do núcleo.
Qual a diferença entre arquitetura hexagonal e clean architecture?
A arquitetura hexagonal foca na comunicação entre o núcleo e o mundo externo por portas e adaptadores, sendo mais simples. A Clean Architecture organiza o código em camadas concêntricas com regras de dependência mais detalhadas. Ambas seguem o mesmo princípio: dependências apontam para dentro e o domínio fica isolado da infraestrutura.
Arquitetura hexagonal serve para projeto pequeno?
Geralmente não compensa. Em CRUDs simples ou MVPs descartáveis, a hexagonal só adiciona camadas de indireção sem retorno real. O padrão vale a pena quando há domínio complexo, múltiplos pontos de entrada e saída, e necessidade concreta de testes isolados e troca de tecnologias.
Como aplicar arquitetura hexagonal no Spring Boot?
Crie o domínio em classes puras sem anotações. Declare portas como interfaces: a porta primária que o mundo externo chama e a porta secundária que o domínio usa para persistência. O caso de uso implementa a porta primária e depende só da secundária. Por fim, o controller REST vira adaptador primário e o repositório JPA vira adaptador secundário.
Ports and adapters é o mesmo que arquitetura hexagonal?
Sim. Ports and adapters é exatamente o mesmo padrão que arquitetura hexagonal. Ports and Adapters foi o nome original dado por Alistair Cockburn em 2005; hexagonal pegou depois por causa do desenho em hexágono. Não são padrões distintos, apenas dois nomes para o mesmo conceito.

Este artigo contém links de afiliado. Se você comprar por eles, podemos receber uma comissão sem custo adicional para você. Isso ajuda a manter o techknow no ar e não influencia nossa opinião editorial.