Ports & Adapters Architecture ou Arquitetura Hexagonal

Desmistificando alguns conceitos

Augusto Marinho
Bemobi
7 min readMay 5, 2020

--

Imagem obtida em https://dzone.com

Imergir em um conceito de negócio e transformá-lo em software é uma das principais habilidades que o engenheiro de software trabalha para evoluir ao longo de sua carreira.

Iniciar um novo projeto ou refatorar algo que já exista, pensando em modernizar o software tanto com relação à arquitetura (conceito) quanto o design (implementação), não esquecendo que é necessário trazer junto com estes novos pensamentos melhores práticas, que viabilizem a testabilidade e manutenibilidade deste software é sempre uma questão de muitos questionamentos de prós e contras.

Uma decisão equivocada neste início, pode gerar um software que já nasce com débito técnico — A palavra que todo engenheiro de software adora discutir.

Pensando nestes desafios de maximizar o resultado da entrega e minimizar possíveis decisões não tão bem dimensionadas, abstrair conceitos de interação com o sistema e identificar com clareza o que é o seu negócio é uma das propostas do tema deste artigo.

Ports & Adapters Architecture ou Arquitetura Hexagonal ?

Nada melhor para iniciar este artigo, desmistificando alguns conceitos sobre os nomes envolvidos nesta arquitetura.

O nome definido por Alistair Cockburn em seu artigo Hexagonal Architecture foi Port & Adapters (Perceba que no próprio artigo existe essa confusão dos nomes).

A explicação para isso, segundo Cockburn, foi inicialmente pensar na arquitetura como um hexágono, porém ainda sem saber o que este hexágono significava, ou até mesmo que a arquitetura precisaria ter seis faces.

O real entendimento de que este hexágono deveria significar, veio em 2015 quando Cockburn entendeu que as faces desta figura geométrica seriam os “Ports” e os objetos que os “Ports” deveriam se comunicar, seriam os “Adapters”.

Mais um mito dentro da arquitetura é com o nome “Adapters”. Este termo não está diretamente relacionados ao Design Pattern Adapter. Dentro do hexágono, a aplicação de qualquer padrão de projeto é bem-vinda.

Origem do Ports & Adapters

A idéia por trás da arquitetura Port & Adapters foi um aprimoramento de um outro modelo arquitetural conhecido como Four Layer Architeture.

A proposta do Four Layer Architecture já era uma evolução do tradicional modelo MVC, onde a proposta era pensar numa arquitetura que houvesse uma separação bem definida, como: View Layer, Application Model, Domain Layer e Infrastructure Layer.

Na visão de Cockburn, seria mais interessante ter um modelo mais genérico (flexível), onde não precisaríamos pensar na arquitetura, obrigando o software a ter uma camada de View (View Layer) e separar o Application e Domain.

A explicação para este novo pensamento é que, na visão de Cockburn, não haveria muita diferença de se ter na aplicação uma comunicação com banco de dados e troca de dados via redes, com a interface do usuário, por exemplo. Estas duas interações poderiam ser substituídas no sistema por qualquer outra forma de interação.

Cockburn cita ainda no artigo que poderia substituir a UI de um sistema, por um enorme arquivo de casos de testes e a comunicação com o banco de dados e redes, poderiam ser substituídas por um banco de dados experimental, instalado localmente, ou o envio de dados por satélite. Estas mudanças não deveriam impactar em nada a arquitetura do software.

O pensamento de Cockburn que resume estas divergência entre o Four Layer Architecture e o Ports & Adapters era simetria. A proposta para esta simetria era pensar numa arquitetura que permitisse a interação com o sistema da seguinte forma:

OUTSIDE <-> Transformer <-> (Application <-> Domain)

Resumidamente, nesta proposta, podemos entender que a View/UI e Banco de dados / Redes estavam fora (OUTSIDE) do sistema. Uma visão bem interessante que deu foco ao negócio e convida sempre o engenheiro de software a se perguntar: Para que o sistema existe? O que ele resolve?

Os demais requisitos que não sejam respondidos por estas perguntas, podemos dizer que são secundários. Será apenas uma forma de entrada e saída de dados.

A figura abaixo materializa o pensamento inicial de Cockburn para arquitetura Ports & Adapters, conforme suas próprias citações.

Primeiro pensamento do Ports & Adapters — Associação com hexágonos concêntricos

O objetivo da arquitetura é receber, no sistema, eventos externos (OUTSIDE), transformá-los e entregá-los à aplicação (Application Model) para interagir com o domínio (Domain).

A arquitetura foi idealizada com o pensamento de hexágonos concêntricos, onde cada face do hexágono mais externo representa uma forma de comunicação com o mundo exterior (Ports) e as faces do hexágono mais interno, as formas de comunicação com o domínio (Adapters, que inicialmente foram citados na figura acima como Transformers).

A figura abaixo mostra uma evolução deste conceito e nos deixa mais próximos de uma implementação real.

Imagem criada por Chris Richardson

E o Infrastructure Layer ?

Até este ponto do estudo, acredito já termos definido bem o que são os “Ports” and “Adapters”. Vamos entender um pouco melhor o que é este Infrastructure Layer.

De uma forma bem resumida, o Infrastructure layer deve conter todas as classes que permitem (implementam) a comunicação do sistema para o mundo exterior (OUTSIDE).

Fazem parte também das características deste layer, a construção (implementação) de funcionalidades (OUTSIDE) que algum “Adapter” precise para ser inicializado.

Um bom exemplo deste cenário, são scripts SQL de criação de banco de dados, abstrações para troca de arquivos via AWS S3, ou até mesmo, algumas classes de configuração para atender algum framework específico, como por exemplo: configurações do Spring, Swagger, leitura de arquivos YAML.

Estes são exemplos muito associados ao mundo Java/Kotlin, mas é apenas um exemplo, faça o “Adapter” deste exemplo para sua linguagem de programação preferida.

O que o Ports & Adapters resolve ?

Analisando esta forma de pensar, percebemos que a arquitetura cria uma flexibilidade no uso de tecnologias para entrada e saída de informações (onde toda esta interação está fora do sistema), sem deixar o software refém da tecnologia e que possíveis substituições, destas tecnologias, não impactem o Application e o Domain.

Caso seja necessário utilizar novas tecnologias para resolver um problema específico, seria apenas a necessidade de “adaptar” o sistema, conectando o “Port” a este novo “Adapter”, sem impactar as regras de negócio.

A arquitetura Ports & Adapters torna o Domain individualizado, onde nenhuma modificação de interação ou mudança de tecnologia (OUTSIDE) possa afetar o Application ou Domain.

Talvez não seja tão simples de visualizar, mas um grande problema que o Ports & Adapters resolve é a testabilidade do software.

Questões relacionados a inserção de tecnologia estão muito bem definidas (Adapters) e implementar testes unitários e/ou integrados (mockados ou não) torna o dia a dia de desenvolvimento mais fácil.

Existe alguma desvantagem ?

Implementar o Ports & Adapters exige um esforço maior de escrita. Mais classes serão necessárias para criar as abstrações. Apesar de citar este ponto como uma desvantagem, essa mesma característica vai nos ajudar a escrever melhores testes (No pain no gain).

A questão dos Layers das aplicações que utilizam esta arquitetura não são definidos. Com isso, é possível criar quantos Layers foram necessários. Neste ponto, sempre chamo a atenção para o Overengineering.

Minha sugestão é: critique sempre as soluções dadas nesta arquitetura, pois é fácil perder a mão quando vemos os “Adapters” bem isolados e melhorando testabilidade. Criar uma funcionalidade que tenha que interagir com vários Ports num sistema com uma infinidade de abstrações, pode virar um pesadelo.

Com relação ao tamanho do sistema que implementa Ports & Adpaters, podemos dizer que o modelo de Micro Serviços ajuda muita na adoção desta arquitetura, tendo em vista o isolamento de domínios (pensando num produto que tenham que interagir com diferentes domínios de informações).

Outro ponto que merece destaque é: não existe um guideline. Isso não necessariamente é uma desvantagem, mas torna a vida de quem quer iniciar com esta arquitetura mais difícil. Existem vários artigos na internet com diferentes visões de como implementar e em diferentes linguagens de programação. Extrair o conceito da arquitetura analisando código nem sempre é uma tarefa fácil.

Uma dica para a questão do guideline é: pense em interfaces (Ports) e implementações / frameworks (Adapters). Acho que vale a pena dizer: Resolva um problema de cada vez.

É fácil perder o foco durante a implementação, quando estamos implementando a arquitetura pensando em Frameworks. Tenha cautela na adoção de alguns Frameworks que possam lhe oferecer alguma “licença poética”, com o JPA, por exemplo.

Conclusão

Pensar numa proposta de tornar as regras de negócio protagonista do sistema é algo importante e necessário para tornar a aplicação manutenível, testável etc. Oferecer ao sistema todas as características é o que nós, engenheiros de software, desejamos entregar em cada projeto.

Somar este protagonismo a uma “blindagem tecnológicas”, na minha visão, é uma das grandes sacadas do Ports & Adapters. Apenas separar as implementações em interfaces não teríamos este comportamento, se não tivermos pensando no todo (O que estou resolvendo?).

Não existe uma única forma de resolver problemas de software e esta arquitetura é mais uma destas propostas. Mas, se você está numa estrutura de micro serviços e pensa em criar algo novo, ou até mesmo refatorar algum outro micro serviço que já exista, o Ports & Adapters pode trazer bons resultados.

Lembrem-se: Ports & Adapters não estão associados à micro serviços, mas funcionam muito bem juntos.

--

--

Augusto Marinho
Bemobi
Writer for

Software Engineer especialista na implantação de sistemas na AWS. IoT maker nas horas vagas.