# 3 camadas da arquitetura hexagonal explicadas

> Published 2026-10-11T13:56:07.595Z on https://www.crazystack.com.br/pt/p/3-camadas-da-arquitetura-hexagonal-explicadas/
> Source video: https://www.youtube.com/watch?v=ovyra_83iCo

Nem toda arquitetura 'famosa' exige over-engineering, e a arquitetura hexagonal é o contraponto: ela desacopla sem multiplicar pastas e camadas cerimoniais. Você mantém rotas, controllers, use cases e repositórios em um arranjo simples em que a regra de negócio define interfaces e a infraestrutura as implementa.

## O que é arquitetura hexagonal e por que ela resolve o acoplamento

A arquitetura hexagonal é um padrão que isola a regra de negócio da infraestrutura usando ports and adapters, nome pelo qual o padrão também é conhecido. A ideia foi publicada por Alistair Cockburn em 2005, no artigo [Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/), e o objetivo original continua atual: impedir que lógica de negócio dependa de banco de dados, interface ou biblioteca externa.

Na prática, o problema que ela resolve é o acoplamento excessivo. Quando seu use case chama diretamente o ORM, testar a regra de negócio exige banco rodando, e trocar de tecnologia vira um projeto. Com hexagonal, a regra de negócio define uma interface e a infraestrutura implementa essa interface — a dependência aponta para dentro, nunca para fora.

Esse padrão aparece em conversas de arquitetura junto com [clean architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html), e a semelhança não é por acaso: as duas preservam a regra de negócio no centro. A hexagonal tende a ser mais enxuta, o que a torna um bom ponto de partida para APIs que precisam de desacoplamento sem cerimônia extra.

## As três camadas: drivers, application e resources

Uma aplicação hexagonal se divide em três regiões com responsabilidades bem definidas. A tabela abaixo resume o papel de cada uma antes de entrar no fluxo de uma requisição real.

| Camada | Papel | Exemplos |
| --- | --- | --- |
| Drivers (esquerda) | Recebem requisições externas | Rotas, controllers |
| Application (centro) | Regra de negócio | Use cases, services |
| Resources (direita) | Recursos externos | Banco de dados, filas, SQS, [RabbitMQ](https://www.rabbitmq.com/) |

O fluxo é direto: uma rota `POST /users` chega pela borda de drivers, o controller valida os dados da requisição e repassa para um use case da camada de application. O use case executa a regra de negócio e, quando precisa persistir ou consultar algo, chama um repositório — que na borda direita conversa com o banco ou com uma fila como o [Amazon SQS](https://aws.amazon.com/sqs/).

O detalhe que muda tudo é a direção das dependências. O controller conhece o use case, mas o use case não conhece o controller nem o banco. Ele conhece apenas a interface que o repositório assina. Esse é o motivo de o padrão se chamar ports and adapters: a interface é a porta, e cada implementação concreta é um adaptador encaixado nela.

## Ports and adapters na prática com repository pattern

O padrão mais comum de adapter é o repository pattern. O repositório recebe os dados enviados pelo use case e grava no banco. A diferença em uma arquitetura hexagonal é que o use case nunca importa a classe concreta do repositório: ele declara uma interface, e o repositório real implementa essa interface.

Em TypeScript, isso significa que o construtor do use case recebe um tipo como `UserRepository`, e classes como `PrismaUserRepository` ou `DrizzleUserRepository` implementam esse contrato. Ferramentas de acesso a dados como o [Prisma](https://www.prisma.io/) e o [Drizzle ORM](https://orm.drizzle.team/) ficam confinadas ao adaptador, onde pertencem.

Esse desenho também facilita testes. Como a regra de negócio depende só da interface, você escreve um repositório em memória nos testes e a suíte roda rápido, sem banco e sem rede. Frameworks como o [Fastify](https://fastify.dev/) seguem confinados à borda de drivers, cuidando de rotas e do protocolo HTTP.

## Inversão e injeção de dependência: o par que sustenta tudo

Dois princípios trabalham juntos para a arquitetura funcionar, e confundi-los é comum. A inversão de dependência é estrutural: o módulo de baixo nível, que é a regra de negócio, define a interface, e o módulo de mais alto nível, que toca recursos externos, implementa essa interface. A dependência é invertida em relação ao intuitivo.

A injeção de dependência é mecânica: o use case recebe o repositório pronto no construtor, em vez de instanciá-lo internamente. Um sinal prático de violação aparece quando você vê um `new` de repositório dentro do construtor do use case — nesse momento, a classe concreta voltou a vazar para a regra de negócio.

Onde as instâncias são criadas, então? Na composição da aplicação, geralmente no entry point ou em um container. É lá que você escolhe `new DrizzleUserRepository()` ou `new InMemoryUserRepository()` e passa o resultado para o use case. O resto do código nem fica sabendo da troca.

## Trocar de banco sem quebrar o código: um exemplo concreto

O teste real do desenho aparece quando você troca a infraestrutura. Suponha uma API de eventos em que o use case `CreateEvents` valida regras como 'não é possível criar um evento no passado' e persiste por meio de um repositório que usava Drizzle.

Para migrar para uma implementação em memória, você cria uma classe `EventsRepositoryMemory` que implementa a mesma interface usada pelo use case. Depois, no ponto onde o use case é instanciado, você passa o novo repositório no lugar do antigo. O use case, os services e todas as validações permanecem intactos, porque nada neles sabia qual era o banco.

Esse mesmo mecanismo serve para testes automatizados: a regra de negócio roda contra o repositório em memória, e a camada que fala com o banco real é exercitada separadamente em testes de integração. Você ganha velocidade na suíte e ganha um limite claro entre o que é lógica e o que é infraestrutura.

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

Arquitetura hexagonal funciona bem quando você quer uma aplicação escalável sem cair no excesso de camadas. Se sua API tem regra de negócio que tende a crescer, integrações externas ou necessidade de testes rápidos, o custo de criar interfaces e adaptadores se paga rapidamente.

Já em scripts pequenos, protótipos descartáveis ou CRUDs triviais sem lógica, criar ports e adapters para tudo pode ser over-engineering. O padrão existe para proteger regra de negócio; sem regra de negócio relevante, não há muito a proteger.

Uma forma de reduzir o custo de aderência é automatizar o desenho. O Felipe Rocha, do Full Stack Club, relata em vídeo ter criado uma skill no [Claude Code](https://claude.com/product/claude-code), ferramenta de codificação agêntica da Anthropic que roda no terminal, para gerar APIs já seguindo esse padrão, com entry point em Fastify. Automação não substitui entender o desenho, mas elimina o trabalho repetitivo de montar a estrutura a cada projeto.

## Onde aprender: comunidades e trilhas de estudo

Dominar inversão e injeção de dependência costuma marcar a passagem de dev júnior para pleno, e dá para estudar o tema por caminhos diferentes conforme seu momento. O [Crazystack Typescript](https://crazystack.com.br) é uma das trilhas que trabalham esse tipo de arquitetura em projetos práticos com TypeScript.

Outra porta de entrada comunitária é o Bootcamp do Dev Doido, do Gustavo Dev Doido, que cobre fundamentos de backend e padrões de projeto em formato acessível para quem está começando. O essencial, em qualquer trilha, é aplicar os padrões em uma API real em vez de só assistir: crie um use case, uma interface de repositório e duas implementações, uma com banco e uma em memória.

Esse exercício curto fixa mais do que horas de teoria, porque expõe na prática onde cada dependência deve nascer e por que o construtor do use case não pode ter um `new` de classe concreta.

## Perguntas frequentes sobre arquitetura hexagonal

- **Arquitetura hexagonal e clean architecture são a mesma coisa?** Não. As duas isolam a regra de negócio da infraestrutura, mas a hexagonal é mais enxuta, focando em ports and adapters. A clean architecture adiciona camadas e regras adicionais de dependência entre entidades, use cases e adaptadores.

- **Ports e adapters significam o quê, exatamente?** Port é a interface definida pelo núcleo da aplicação, como um `UserRepository`. Adapter é a implementação concreta dessa interface, como um repositório com Prisma, Drizzle ou em memória. Cada recurso externo ganha seu adaptador.

- **Preciso de framework especial para aplicar o padrão?** Não. O padrão é sobre direção de dependências, não sobre ferramentas. Funciona com Fastify, Express, Nest ou qualquer stack; o que importa é o use case receber interfaces e as classes concretas viverem na borda.

- **Como testar a regra de negócio sem banco de dados?** Você injeta um repositório em memória que implementa a mesma interface do repositório real. O use case roda igual, a suíte fica rápida e os testes de integração com banco real ficam isolados em outra camada.

- **Arquitetura hexagonal serve para projetos pequenos?** Depende da regra de negócio. Em CRUDs triviais, o custo das interfaces pode ser over-engineering. Em APIs com validações, integrações e evolução prevista, o padrão mantém o código testável e facilita trocas de infraestrutura.

## Do vídeo para o artigo: transforme explicações técnicas em conteúdo

O que você leu aqui nasceu de uma explicação em vídeo sobre fluxo de trabalho e arquitetura hexagonal — o tipo de conhecimento que costuma ficar preso em lives, mentorias e palestras, acessível apenas a quem estava assistindo naquele momento.

Se você também ensina programação, arquitetura ou qualquer tema técnico em vídeos, o [Skala Blog](https://skalablog.com) transforma esse material em artigo: você cola a URL do YouTube, o vídeo é transcrito e vira um texto estruturado, pronto para revisar e publicar. As explicações que já existem nos seus vídeos passam a alcançar quem pesquisa e lê, e não só quem assiste.

[Source video](https://www.youtube.com/watch?v=ovyra_83iCo)
