Arquitetura hexagonal (portas e adaptadores) para iniciantes
Portas e adaptadores isolam a lógica de negócio da infraestrutura. Entenda a arquitetura hexagonal, seus benefícios e quando o overhead não compensa.
Neste artigo
Imagine abrir o código de uma aplicação para entender a regra central do negócio — como um pedido é validado, como um empréstimo é aprovado, como um preço é calculado — e descobrir que essa regra está entrelaçada com chamadas ao banco de dados, com o formato de uma requisição HTTP e com detalhes de uma fila de mensagens. Para entender a lógica, você precisa desviar de detalhes de infraestrutura a cada linha. Para testá-la, precisa subir um banco. E para trocar o banco por outro, ou expor a mesma regra por um novo canal, você precisa mexer no coração do sistema, arriscando quebrar o que funciona.
Esse emaranhado é o problema que a arquitetura hexagonal, proposta por Alistair Cockburn, se propõe a resolver. O nome oficial dela, mais descritivo, é portas e adaptadores. A imagem do hexágono é só um recurso visual; o que importa é a ideia central, que é ao mesmo tempo simples e transformadora: manter a lógica de negócio isolada num núcleo protegido, e empurrar toda a tecnologia — banco, web, filas, arquivos — para fora, conectada a esse núcleo por interfaces bem definidas.
Este artigo apresenta a arquitetura hexagonal para quem está começando, sem jargão desnecessário. Vamos entender o que são portas e adaptadores, por que o núcleo de domínio deve ficar isolado, qual a diferença entre os lados driving e driven, os benefícios concretos que essa separação traz, como ela se relaciona com a clean architecture e as arquiteturas em camadas, e — porque nenhuma abordagem é grátis — quando o overhead dela simplesmente não compensa.
O problema: infraestrutura invadindo o domínio#
Para valorizar a solução, é preciso sentir o problema. Numa aplicação sem essa separação, a lógica de negócio tende a se contaminar com detalhes técnicos. O método que calcula se um cliente pode receber crédito acaba contendo a consulta SQL que busca o histórico, o parsing do corpo da requisição que trouxe os dados e a serialização da resposta. Três preocupações completamente distintas — a regra, o armazenamento, o transporte — coabitam o mesmo trecho de código.
As consequências são acumulativas. A regra fica difícil de ler, porque está soterrada em ruído técnico. Fica difícil de testar, porque exercitá-la exige um banco real, um servidor web, talvez uma fila. Fica difícil de evoluir, porque trocar qualquer tecnologia — migrar de um banco para outro, adicionar uma API nova, mudar de fila — obriga a cirurgia no núcleo. E, o mais insidioso: a tecnologia, que muda rápido e por razões alheias ao negócio, arrasta consigo a regra de negócio, que deveria ser estável. O rabo passa a abanar o cachorro.
A ideia central: um núcleo protegido#
A arquitetura hexagonal inverte a relação de poder. Em vez de a infraestrutura estar no centro com a regra grudada nela, a regra de negócio fica no centro, pura, sem nenhum conhecimento sobre banco, web ou filas. Esse núcleo — o domínio — contém as entidades, as regras e os casos de uso, expressos na linguagem do negócio e em nada mais. Ele não importa bibliotecas de banco, não sabe o que é uma requisição HTTP, não conhece a existência de uma fila.
A pergunta imediata é: se o núcleo não conhece o banco, como ele persiste dados? Se não conhece a web, como recebe requisições? A resposta é o mecanismo que dá nome à arquitetura: portas e adaptadores. O núcleo define o que precisa em termos abstratos — portas — e a tecnologia concreta se pluga nessas portas por meio de adaptadores. O núcleo fala apenas com abstrações que ele mesmo define; o mundo externo se conforma a elas.
Portas: as interfaces do domínio#
Uma porta é uma interface — no sentido de contrato — definida pelo núcleo, que descreve uma interação com o mundo externo em termos do próprio domínio, sem mencionar tecnologia. Uma porta de persistência de pedidos poderia declarar operações como "salvar um pedido" e "buscar um pedido por identificador", expressas com os conceitos do domínio, sem uma palavra sobre SQL, tabelas ou conexões. A porta diz o que o núcleo precisa, nunca como isso é realizado.
O ponto sutil e poderoso é que a porta pertence ao núcleo, não à infraestrutura. É o domínio que declara suas necessidades e dita a forma do contrato; a tecnologia é que precisa se encaixar. Isso inverte a dependência: em vez de o negócio depender do banco, o banco passa a depender de uma interface que o negócio definiu. Essa inversão é o coração de tudo, porque é ela que mantém o núcleo livre para não conhecer o mundo externo.
Adaptadores: as implementações concretas#
Um adaptador é a implementação concreta que conecta uma porta a uma tecnologia real. Para a porta de persistência de pedidos, um adaptador poderia implementá-la usando um banco relacional específico, traduzindo as operações abstratas do domínio em comandos SQL concretos. Se amanhã você quiser trocar por outro banco, ou por armazenamento em memória para testes, ou por um serviço remoto, você escreve um adaptador novo que satisfaz a mesma porta — e o núcleo não percebe diferença nenhuma, porque ele só conhece a porta.
É aqui que a arquitetura entrega sua promessa de flexibilidade. A tecnologia vira um detalhe plugável na borda. O mesmo núcleo pode ser servido por um adaptador HTTP e por um adaptador de linha de comando; pode persistir num banco relacional hoje e num documento amanhã; pode receber eventos de uma fila ou de um webhook. Cada uma dessas variações é um adaptador diferente encaixado na mesma porta, sem tocar no domínio.
Os dois lados: driving e driven#
Um detalhe que confunde iniciantes é que existem dois tipos de porta e adaptador, distinguidos por quem inicia a interação. A distinção é fundamental para entender a arquitetura de verdade.
- Lado driving (condutor), ou primário: é o lado que aciona a aplicação, de onde vêm os estímulos. Um usuário clicando numa interface, uma requisição HTTP chegando, um comando de terminal, um teste automatizado invocando um caso de uso. Aqui, o adaptador externo chama uma porta do núcleo. A porta driving é a interface dos casos de uso que a aplicação oferece ao mundo; o adaptador driving — o controlador HTTP, por exemplo — traduz o estímulo externo em chamadas a essa porta.
- Lado driven (conduzido), ou secundário: é o lado que a aplicação aciona para cumprir sua tarefa, aquilo de que ela depende. Bancos de dados, filas de mensagens, serviços externos, envio de e-mail. Aqui, o núcleo chama uma porta, e o adaptador driven a implementa contra uma tecnologia concreta. A porta driven é a necessidade do domínio; o adaptador driven — o repositório sobre um banco, por exemplo — a satisfaz.
Visualmente: os estímulos entram pela esquerda (driving), atravessam o núcleo, e as dependências saem pela direita (driven). Em ambos os lados, o núcleo só toca portas; os adaptadores ficam do lado de fora, e a direção da dependência sempre aponta para dentro, na direção do domínio. Essa simetria com direções opostas de controle é o que a imagem do hexágono tenta comunicar.
Os benefícios concretos#
Tudo isso soa elegante, mas o valor real está nos ganhos práticos que a separação produz.
- Testar o domínio sem infraestrutura. Como o núcleo só conhece portas, você pode testá-lo substituindo os adaptadores reais por implementações falsas ou em memória. Os testes das regras de negócio rodam em milissegundos, sem subir banco nem servidor, e são estáveis porque não dependem de rede. A testabilidade deixa de ser uma luta e vira consequência natural do desenho.
- Trocar tecnologia sem tocar no negócio. Migrar de banco, substituir um provedor de e-mail, adicionar um novo canal de entrada — cada uma dessas mudanças é um adaptador novo encaixado numa porta existente. O núcleo permanece intocado, e com ele todo o valor e todo o risco concentrado nas regras de negócio.
- Clareza e foco. O código do domínio expressa a regra de negócio e nada mais, sem ruído técnico. Quem lê entende a lógica; quem mantém sabe onde cada preocupação vive. A estrutura comunica a intenção.
- Adiar decisões técnicas. Você pode desenvolver e validar o núcleo antes de fixar qual banco ou qual framework usar, mantendo essas escolhas como detalhes tardios em vez de fundações precoces. Decisões irreversíveis ficam para quando há mais informação.
- Longevidade. Frameworks e bancos vêm e vão; a regra de negócio, se bem isolada, sobrevive às trocas de tecnologia ao seu redor. Você protege o ativo mais valioso e mais caro de reescrever.
A relação com clean architecture e camadas#
Quem estuda arquitetura logo encontra nomes vizinhos — clean architecture, arquitetura cebola (onion), arquitetura em camadas — e se pergunta como tudo se conecta. A boa notícia é que há um princípio comum por baixo de todas.
A arquitetura em camadas tradicional empilha apresentação, negócio e dados, com cada camada dependendo da de baixo. O problema clássico é que, nessa disposição, a camada de negócio acaba dependendo da camada de dados, e portanto da tecnologia de persistência — a mesma contaminação que a hexagonal combate. A camada tradicional organiza, mas não protege o domínio da infraestrutura.
A clean architecture, de Robert Martin, e a arquitetura cebola são, em espírito, formulações do mesmo princípio da hexagonal, com ênfases e vocabulário próprios: círculos concêntricos onde as dependências apontam sempre para dentro, do externo (frameworks, banco, web) para o interno (entidades, casos de uso), e nunca o contrário. A regra do domínio no centro, ignorante da tecnologia; a tecnologia na borda, dependente das abstrações do centro. A hexagonal enfatiza a simetria driving/driven e a metáfora dos plugues; a clean enfatiza os anéis e a regra de dependência. Mas o coração — inversão de dependência para proteger a lógica de negócio da infraestrutura — é o mesmo. Entender uma facilita muito entender as outras, porque são dialetos de uma ideia só.
Quando o overhead não compensa#
Nenhuma arquitetura é gratuita, e apresentar a hexagonal sem seus custos seria desonesto. A separação em portas e adaptadores adiciona indireção: mais interfaces, mais camadas de tradução, mais arquivos, mais cerimônia entre o estímulo e o efeito. Essa estrutura se paga quando há complexidade de domínio real para proteger e quando a flexibilidade tecnológica tem valor concreto. Quando não há, ela vira peso morto.
Pense num aplicativo pequeno, essencialmente um CRUD, cuja "regra de negócio" é pouco mais do que ler e gravar dados, sem lógica sofisticada, com uma única tecnologia de persistência que não vai mudar. Aplicar hexagonal ali cria uma constelação de interfaces e adaptadores que não protegem nada relevante — não há regra complexa para isolar, não há troca de tecnologia no horizonte. Você pagou o custo da indireção e comprou uma flexibilidade que nunca vai exercer. É o mesmo erro de aplicar um padrão de projeto sem ter o problema que ele resolve.
O julgamento fica mais fácil com algumas perguntas. Há lógica de negócio rica que se beneficia de ficar isolada e testável em separado? É plausível trocar tecnologias ou oferecer múltiplos canais de entrada e saída? O sistema é longevo o suficiente para que a proteção do domínio se pague ao longo do tempo? Quanto mais respostas afirmativas, mais a hexagonal vale a pena. Para scripts, protótipos, ferramentas descartáveis e CRUDs triviais, a simplicidade direta costuma vencer, e forçar a arquitetura é over-engineering.
Vale ainda a nota de que a adoção não precisa ser tudo ou nada. Você pode aplicar o isolamento onde há domínio rico e deixar as partes triviais simples, ou introduzir portas e adaptadores de forma incremental à medida que a complexidade cresce e a necessidade se manifesta — deixando a estrutura emergir da pressão real, em vez de impô-la por princípio no primeiro dia.
Conclusão#
A arquitetura hexagonal condensa uma verdade profunda sobre software num arranjo prático: a lógica de negócio é o ativo mais valioso e mais durável de um sistema, e merece ser protegida da tecnologia volátil ao seu redor. Colocando o domínio num núcleo puro, expressando suas necessidades como portas e plugando a tecnologia como adaptadores intercambiáveis nas bordas, você ganha um domínio testável sem infraestrutura, tecnologias trocáveis sem cirurgia no negócio e um código que comunica sua intenção com clareza. Os lados driving e driven organizam de onde vêm os estímulos e do que a aplicação depende, sempre com as dependências apontando para dentro.
Ela não é, porém, uma obrigação universal, e sim uma ferramenta cujo valor cresce com a complexidade do domínio e com a necessidade real de flexibilidade tecnológica e longevidade. Para sistemas ricos e duradouros, é um dos investimentos de arquitetura mais recompensadores que existem, aparentado da clean architecture e da onion pela mesma inversão de dependência no núcleo. Para o pequeno e o efêmero, a indireção extra pode custar mais do que entrega, e a honestidade de reconhecer isso faz parte de aplicá-la bem. Como quase tudo em engenharia, o mérito não está em usar a arquitetura, mas em julgar com precisão quando a proteção que ela oferece vale o preço que ela cobra.