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 um 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 alteração. 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 de negócios.
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 externo 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, então é 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 haveria necessidade de alterar nada no modelo de domínio. Portanto, a arquitetura hexagonal se adapta facilmente aos requisitos não funcionais.
Adaptando-se 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. A vantagem da inversão de dependências é 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 comercial que você está tentando resolver, atualizar o modelo de domínio para se adaptar às mudanças nos requisitos comerciais não é um problema.
Quando você desenvolve software, a separação de interesses é 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 pelos 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 filas síncronas APIs ou assíncronas, para executar comandos. Recomendamos que você use comandos e manipuladores de comando para cada operação no domínio. Ao seguir 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 livremente as solicitações de leitura e gravação recebidas dos clientes ao domínio. Há duas maneiras de obter esse acoplamento frouxo: usando um padrão de fachada de serviço ou usando o padrão de segregação de responsabilidade por consulta de comando (CQRS).
O padrão de 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ço 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 em várias operações. No entanto, ao usar a fachada de serviço, é mais difícil seguir os princípios de responsabilidade única e de aberto-fechado. 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ço se estende, todas as operações são reunidas 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 manipuladores 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 a 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 que seja 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 que você avalie seu projeto cuidadosamente 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 as 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 dessa 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. Estruturar equipes com base em características técnicas cria silos desnecessários na organização, o que resulta em comunicações precárias, 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 de software. Por exemplo, equipes multifuncionais são responsáveis por um conjunto específico de contextos limitados, que são identificados usando DDD e event storming. 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 pouco unidas, para que 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, para que recursos complexos possam ser atribuídos a mais engenheiros.