A Arquitetura Hexagonal, também conhecida como Ports and Adapters (Portas e Adaptadores), proposta por Alistair Cockburn, é um padrão de projeto de software que visa criar sistemas fracamente acoplados, onde a lógica de negócio (o “coração” da aplicação) é isolada de preocupações externas, como bancos de dados, interfaces de usuário (UI) ou APIs de terceiros.
O Conceito Fundamental Link para o cabeçalho
Em uma arquitetura tradicional em camadas, muitas vezes a lĂłgica de negĂłcio acaba “vazada” ou dependente de frameworks e tecnologias especĂficas. Na Arquitetura Hexagonal, invertemos essa dependĂŞncia:
1. Core (Aplicação/DomĂnio): O centro do hexágono. ContĂ©m as regras de negĂłcio e nĂŁo conhece nada sobre o mundo externo.
2. Ports (Portas): Interfaces que definem como o mundo externo pode interagir com o seu sistema.
3. Adapters (Adaptadores): Implementações concretas que conectam o mundo externo (Web, CLI, SQL, Redis) às suas portas.
Organização de Pastas (Estrutura de Projeto) Link para o cabeçalho
Uma das maiores vantagens da arquitetura hexagonal é que ela sugere uma organização de diretórios que separa claramente o que é regra de negócio do que é detalhe técnico.
src/
├── Application/ # Casos de uso e lógica de orquestração
│ └── RegisterUser.php # Atua como service
├── Domain/ # O Coração: Entidades e Portas (Interfaces)
│ ├── Model/
│ │ └── User.php
│ └── Repository/
│ └── UserRepositoryInterface.php
└── Infrastructure/ # Adaptadores (Implementações técnicas)
├── Persistence/
│ └── MySqlUserRepository.php
└── Presentation/
└── Http/
└── UserController.php
Explicação dos diretórios: Link para o cabeçalho
-
Domain: Contém o que faz o seu sistema ser o que ele é. Não deve ter referências a bancos de dados, frameworks ou bibliotecas HTTP. É puro PHP.
-
Application: Onde orquestramos as regras de negócio. Se o seu sistema tem um fluxo como “Validar dados -> Salvar no repositório -> Enviar e-mail de boas-vindas”, isso acontece aqui.
-
Infrastructure: Onde a mágica técnica acontece. É aqui que você coloca o código que fala com o MySQL, Redis, APIs de terceiros (como Stripe ou AWS) ou o framework que você está usando (como Laravel ou Symfony).
Diagrama de Fluxo (Representação Conceitual) Link para o cabeçalho
Para visualizar melhor o fluxo, imagine a comunicação sempre entrando pelo “adaptador” e respeitando a “porta”:
graph TD
A[Adaptador HTTP / CLI] -->|Chama| B(Porta: UserRepositoryInterface)
B -->|Implementada por| C[Adaptador: MySqlUserRepository]
D[Domain: UserService] -->|Depende de| B
subgraph Core [Núcleo da Aplicação]
D
B
end
Exemplo Prático em PHP Link para o cabeçalho
Vamos imaginar um sistema simples de Registro de Usuário.
1. O Core (DomĂnio) Link para o cabeçalho
O core define uma Porta (interface) para salvar o usuário. Ele não sabe se estamos usando MySQL, um arquivo de texto ou uma API externa.
// src/Domain/UserRepositoryInterface.php
interface UserRepositoryInterface {
public function save(string $email): void;
}
// src/Domain/UserService.php
class UserService {
public function __construct(private UserRepositoryInterface $repository) {}
public function register(string $email): void {
// Regra de negĂłcio simples
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new Exception("E-mail inválido");
}
$this->repository->save($email);
}
}
2. O Adaptador (Infraestrutura) Link para o cabeçalho
Aqui criamos a implementação real que conversa com o banco de dados.
// src/Infrastructure/MySqlUserRepository.php
class MySqlUserRepository implements UserRepositoryInterface {
public function save(string $email): void {
echo "Salvando '$email' no banco de dados MySQL...\n";
}
}
3. O Ponto de Entrada Link para o cabeçalho
Este é o adaptador que dispara a ação (ex: uma requisição HTTP ou comando CLI).
// public/index.php
$repository = new MySqlUserRepository();
$userService = new UserService($repository);
$userService->register("contato@exemplo.com");
Por que utilizar essa abordagem? Link para o cabeçalho
- Testabilidade: VocĂŞ pode facilmente criar um
InMemoryUserRepositorypara testes unitários, sem precisar de um banco de dados real. - Flexibilidade: Se amanhã você decidir trocar o MySQL pelo MongoDB, basta criar um novo Adaptador que implemente a
UserRepositoryInterface. OUserServicepermanece intacto. - Isolamento: As mudanças na tecnologia (frameworks, drivers) não impactam suas regras de negócio.