As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Adaptando-se à mudança
Os sistemas de software tendem a ficar complicados. Uma razão para isso pode ser mudanças frequentes nos requisitos de negócios e pouco tempo para adaptar adequadamente a arquitetura do software. Outro motivo pode ser o investimento insuficiente para configurar a arquitetura de software no início do projeto para se adaptar às mudanças frequentes. Seja qual for o motivo, um sistema de software pode ficar complicado a ponto de ser quase impossível fazer uma mudança. Portanto, é importante criar uma arquitetura de software sustentável desde o início do projeto. Uma boa arquitetura de software pode se adaptar facilmente às mudanças.
Esta seção explica como projetar aplicativos sustentáveis usando uma arquitetura hexagonal que se adapta facilmente aos requisitos não funcionais ou comerciais.
Adaptação aos novos requisitos não funcionais usando portas e adaptadores
Como núcleo do aplicativo, o modelo de domínio define as ações que são exigidas do mundo exterior para atender aos requisitos de negócios. Essas ações são definidas por meio de abstrações, chamadas de portas. Essas portas são implementadas por adaptadores separados. Cada adaptador é responsável por uma interação com outro sistema. Por exemplo, você pode ter um adaptador para o repositório do banco de dados e outro adaptador para interagir com uma API de terceiros. O domínio não está ciente da implementação do adaptador, portanto, é fácil substituir um adaptador por outro. Por exemplo, o aplicativo pode mudar de um banco de dados SQL para um banco de dados NoSQL. Nesse caso, um novo adaptador precisa ser desenvolvido para implementar as portas definidas pelo modelo de domínio. O domínio não tem dependências no repositório do banco de dados e usa abstrações para interagir, portanto, não seria necessário alterar nada no modelo de domínio. Portanto, a arquitetura hexagonal se adapta aos requisitos não funcionais com facilidade.
Adaptação aos novos requisitos de negócios usando comandos e manipuladores de comandos
Na arquitetura clássica em camadas, o domínio depende da camada de persistência. Se você quiser alterar o domínio, também precisará alterar a camada de persistência. Em comparação, na arquitetura hexagonal, o domínio não depende de outros módulos no software. O domínio é o núcleo do aplicativo, e todos os outros módulos (portas e adaptadores) dependem do modelo de domínio. O domínio usa o princípio de inversão de dependência para se comunicar com o mundo externo por meio de portas. O benefício da inversão de dependência é que você pode alterar o modelo de domínio livremente sem ter medo de quebrar outras partes do código. Como o modelo de domínio reflete o problema de negócios que você está tentando resolver, atualizar o modelo de domínio para se adaptar às mudanças nos requisitos de negócios não é um problema.
Quando você desenvolve software, a separação de preocupações é um princípio importante a ser seguido. Para conseguir essa separação, você pode usar um padrão de comando ligeiramente modificado. Esse é um padrão de design comportamental no qual todas as informações necessárias para concluir uma operação são encapsuladas em um objeto de comando. Essas operações são então processadas por manipuladores de comando. Os manipuladores de comando são métodos que recebem um comando, alteram o estado do domínio e, em seguida, retornam uma resposta ao chamador. Você pode usar clientes diferentes, como APIs síncronas ou filas assíncronas, para executar comandos. Recomendamos que você use comandos e manipuladores de comandos para cada operação no domínio. Seguindo essa abordagem, você pode adicionar novos recursos introduzindo novos comandos e manipuladores de comandos, sem alterar sua lógica comercial existente. Assim, o uso de um padrão de comando facilita a adaptação aos novos requisitos de negócios.
Desacoplamento de componentes usando a fachada de serviço ou o padrão CQRS
Na arquitetura hexagonal, os adaptadores primários são responsáveis por acoplar vagamente as solicitações de leitura e gravação recebidas dos clientes ao domínio. Há duas maneiras de obter esse acoplamento solto: usando um padrão de fachada de serviço ou usando o padrão de segregação de responsabilidade por consulta (CQRS) de comando.
O padrão da fachada de serviço fornece uma interface frontal para atender clientes, como a camada de apresentação ou um microsserviço. Uma fachada de serviços oferece aos clientes várias operações de leitura e gravação. É responsável por transferir as solicitações recebidas para o domínio e mapear a resposta recebida do domínio para os clientes. Usar uma fachada de serviço é fácil para microsserviços que têm uma única responsabilidade com várias operações. No entanto, ao usar a fachada de serviços, é mais difícil seguir a responsabilidade única e os princípios abertos e fechados. O princípio de responsabilidade única afirma que cada módulo deve ser responsável por apenas uma única funcionalidade do software. O princípio aberto-fechado afirma que o código deve ser aberto para extensão e fechado para modificação. À medida que a fachada de serviços se estende, todas as operações são coletadas em uma interface, mais dependências são encapsuladas nela e mais desenvolvedores começam a modificar a mesma fachada. Portanto, recomendamos usar uma fachada de serviço somente se estiver claro que o serviço não se estenderia muito durante o desenvolvimento.
Outra forma de implementar adaptadores primários na arquitetura hexagonal é usar o padrão CQRS, que separa as operações de leitura e gravação usando consultas e comandos. Conforme explicado anteriormente, os comandos são objetos que contêm todas as informações necessárias para alterar o estado do domínio. Os comandos são executados por métodos de manipulador de comandos. As consultas, por outro lado, não alteram o estado do sistema. Seu único objetivo é devolver dados aos clientes. No padrão CQRS, comandos e consultas são implementados em módulos separados. Isso é especialmente vantajoso para projetos que seguem uma arquitetura orientada por eventos, porque um comando pode ser implementado como um evento processado de forma assíncrona, enquanto uma consulta pode ser executada de forma síncrona usando uma API. Uma consulta também pode usar um banco de dados diferente, otimizado para ela. A desvantagem do padrão CQRS é que ele leva mais tempo para ser implementado do que uma fachada de serviço. Recomendamos usar o padrão CQRS para projetos que você planeja escalar e manter a longo prazo. Comandos e consultas fornecem um mecanismo eficaz para aplicar o princípio de responsabilidade única e desenvolver software fracamente acoplado, especialmente em projetos de grande escala.
O CQRS tem grandes benefícios a longo prazo, mas requer um investimento inicial. Por esse motivo, recomendamos avaliar cuidadosamente o projeto antes de decidir usar o padrão CQRS. No entanto, você pode estruturar seu aplicativo usando comandos e manipuladores de comandos desde o início, sem separar as operações de leitura/gravação. Isso o ajudará a refatorar facilmente seu projeto para o CQRS se você decidir adotar essa abordagem posteriormente.
Escalabilidade organizacional
Uma combinação de arquitetura hexagonal, design orientado por domínio e (opcionalmente) CQRS permite que sua organização escale rapidamente seu produto. De acordo com a Lei de Conway, as arquiteturas de software tendem a evoluir para refletir as estruturas de comunicação de uma empresa. Historicamente, essa observação teve conotações negativas, porque grandes organizações geralmente estruturam suas equipes com base em conhecimentos técnicos, como banco de dados, barramento de serviços corporativos e assim por diante. O problema com essa abordagem é que o desenvolvimento de produtos e recursos sempre envolve questões transversais, como segurança e escalabilidade, que exigem comunicação constante entre as equipes. A estruturação de equipes com base em características técnicas cria silos desnecessários na organização, o que resulta em comunicações deficientes, falta de propriedade e perda de visão do panorama geral. Eventualmente, esses problemas organizacionais se refletem na arquitetura do software.
A Manobra Inversa de Conway, por outro lado, define a estrutura organizacional com base em domínios que promovem a arquitetura do software. Por exemplo, as equipes multifuncionais são responsáveis por um conjunto específico de contextos limitados, que são identificados usando DDD e evasão de eventos. Esses contextos limitados podem refletir características muito específicas do produto. Por exemplo, a equipe da conta pode ser responsável pelo contexto de pagamento. Cada novo recurso é atribuído a uma nova equipe que tem responsabilidades altamente coesas e vagamente acopladas, para que eles possam se concentrar apenas na entrega desse recurso e reduzir o tempo de lançamento no mercado. As equipes podem ser escaladas de acordo com a complexidade dos recursos, portanto, recursos complexos podem ser atribuídos a mais engenheiros.