BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Utilizando o DDD para validação de regras de negócio

Utilizando o DDD para validação de regras de negócio

Pontos Principais

  • As regras de negócios representam parte do conhecimento que um sistema tem sobre um domínio específico;

  • Estruturar apropriadamente as regras de negócio reduz a possibilidade de erros e facilita a manutenção;

  • Regras de negócio possuem diversas responsabilidades, como fornecer validações ou gerar resultados;

  • Decidir como processar os eventos impacta o design geral e as consequências devem ser entendidas antes de tomar qualquer decisão;

  • Uma abordagem por comandos deve ser estruturada com base nas ações do usuário fornecendo um resultado claro.

Quando pensamos sobre regras de negócio, especialmente se somos da área técnica, provavelmente imaginamos linhas de código ou um mecanismo de regras de negócio (se utilizarmos um). No entanto, regras estão mais relacionadas com gerenciamento de conhecimento do que com o código. Por exemplo, uma pessoa trabalhando no setor de construção sabe que existem várias regras relacionadas ao tamanho mínimo de um quarto ou as características necessárias para o ambiente ser considerado um quarto, não uma sala de TV. O conhecimento dessas regras e de como aplicá-las, faz da pessoa uma especialista nessa área. Nosso objetivo é criar aplicações de software que simulam o comportamento dos especialistas.

Ao longo deste artigo, utilizaremos um sistema de reservas de recursos compartilhados de uma empresa. O objetivo deste sistema será ajudar os empregados a fazer reservas de coisas como notebooks, projetores, mesas de tênis etc.

Apenas lendo a primeira frase, provavelmente levantamos uma série de perguntas, como: O que é um recurso? O que significa reservar um recurso? O sistema aceita que recursos sejam reservados mais do que uma vez? Questões como essas devem ser respondidas pelo especialista do negócio e serão as regras de negócio que irão ditar o comportamento do sistema.

Elas também guiarão a definição de entidades, valores dos objetos, comandos e outros elementos do sistema. O escopo deste artigo não irá abranger a definição de cada um destes elementos.

Existem livros dedicados a este tópico, como Domain-Driven Design: Atacando as Complexidades no Coração do Software de Eric Evans e, se vamos implementar usando o .NET, recomendo Hands-On Domain-Driven Design with .NET Core

Este artigo irá cobrir apenas o método de estruturação das regras de negócio que:

  1. São consistentes. Organizar regras de negócio de maneira que qualquer desenvolvedor consiga entender é primordial para quaisquer mudanças futuras. É melhor considerar que os sistemas sempre mudam e que as aplicações devem estar preparadas para essas mudanças;
  2. São fáceis de testar. Construir regras testáveis é a única maneira de garantir que mudanças não irão quebrar funcionalidades existentes;
  3. Mantém a consistência dos dados. Manter a consistência dos dados é uma das principais responsabilidades das regras de negócio. Por experiência própria, muitos problemas de qualidade estão relacionados ao manuseio errado das regras do sistema;
  4. São fáceis de serem diagnosticadas. Devemos evitar erros indesejados; no entanto, exceções sempre vão acontecer. Esses erros são ainda piores quando a única informação de diagnóstico que temos é object reference null.

Este artigo utiliza o modelo entrada-processamento-saída para descrever regras de sistema, no qual uma entrada é fornecida ao sistema; um processador interno usa essa entrada para executar operações, as quais criam uma saída. Mas antes do processador executar qualquer ação, ele deve validar se a informação fornecida é válida. As próximas seções descrevem como lidar com essas validações.

Modelo detalhado

O modelo base para lidar com validações utilizando uma abordagem baseada no domínio, que aqui é mostrado como sendo um comando enviado ao sistema.

Este modelo fornece um exemplo de implementação de tratamento de regras de negócio em um sistema. Esta abordagem é baseada no domain-driven design (design orientado a domínio, DDD), mas pode ser aplicada em outros modelos. A sequência de execução é a seguinte:

Comando enviado ao sistema

1. O cliente envia um comando

Para modelar comandos que podem ser executados por clientes, precisamos identificá-los através dos nomes. Um exemplo de comando pode ser Reservar. Observe que estamos mesclando definições de design de software com design de negócios. Pode parecer algo comum, mas quando especificamos desta maneira, estamos ajudando a deixar o design do sistema mais eficiente para ser entendido. A ideia se baseia no conceito HCI (human-computer interaction, interação homem-computador) de desenvolvimento de sistemas com uma tarefa em mente. O comando ajuda os designers a pensar sobre uma tarefa específica que o sistema precisa ter.

O comando pode ter parâmetros adicionais, como data, nome do recurso e descrição de uso. O Command and Query Responsibility Segregation (CQRS) é um padrão que usa comandos para modelar interações com o sistema. Embora na imagem modelo o cliente seja um usuário, ele também poderia ser outro sistema. O comando também dá a possibilidade do sistema ter comportamentos diferentes, para ações que mudam o estado do sistema, daquelas que apenas retornam dados.

Validação da sintaxe de um comando

2. Validação das regras de sintaxe

O próximo estágio é a validação da sintaxe. Sintaxe, de acordo com Merriam-Webster, é a forma como elementos linguísticos (como palavras) são unidos para formar elementos (como frases e cláusulas). No nosso contexto, isto significa que o comando faz sentido para o contexto do domínio.

Esta validação garante que os dados fornecidos são coerentes para o sistema. Um exemplo dessa validação é a data inicial para fazer a reserva, cujo valor não pode estar no passado e não pode ser nulo. Há inúmeras maneiras de retornar os erros no estágio de validação. Vladimir Khorikov fornece alguns exemplos de como realizar estas validações. Esta validação também pode acontecer em diversas camadas do sistema. Por exemplo, é melhor validar a data na interface do usuário para que ela não esteja no passado, ao invés de enviar esses valores para o backend, para então ser validado. Isto não significa que a validação não deve ser feita no backend também, pelo contrário, as validações em locais diferentes previnem qualquer mau uso de demais clientes.

Validação de regras de semântica utilizando o estado do sistema

3. Validação de regras semânticas

Validação semântica depende do estado do sistema. Este tipo de validação pretende checar se o comando enviado faz sentido com base no estado do sistema, o qual é normalmente salvo e recebido através de entidades. Continuando com o exemplo do comando Reservar, uma validação possível seria, checar se outro cliente já reservou o recurso solicitado. Esta validação também pode existir do lado do cliente. Entretanto, existem várias razões para que o domínio ainda possa receber reservas do mesmo recurso. A responsabilidade do sistema é garantir a consistência dos dados.

Processando regras de produção que alteram o estado do sistema

4. Regras de produção

Regras de produção são o coração do sistema. Até aqui, o comando passou através de diferentes estágios que devem garantir que a requisição pode ser processada. Regras de produção especificam as ações que o sistema deve realizar para atingir o estado desejado. Elas lidam com a tarefa que o cliente está tentando completar. Usando o comando Reservar como referência, as regras de produção executam as modificações necessárias para registrar o recurso requisitado como reservado. Como uma consequência dessas alterações, entidades e serviços de domínio podem gerar eventos que informam a alteração para o cliente e para outros sistemas. No exemplo que estamos utilizando, o evento seria RecursoReservado.

Geração e processamento de eventos

5. Eventos

Eventos são um mecanismo de comunicação para interação com outros sistemas ou subsistemas. Entretanto, antes de implementá-los em nosso domínio, é necessário determinar como o sistema vai interagir com esses sinais. Há duas alternativas para processar os eventos. Cada uma tem seus prós e contras.

A primeira é através da utilização de consistência transacional. Neste modelo, o sistema mantém a coerência das entidades modificadas utilizando a mesma transação. Mesmo quando há mais de um agregado envolvido, a transação mantém o controle das alterações e as grava ao final do processo. Este padrão é conhecido como uma unidade de trabalho. Ele possui algumas vantagens como simplicidade e eficiência em termos de produção de código. Porém, às vezes, é totalmente impossível de ser feito. Um dos motivos é que ele mantém as entidades modificadas em memória, que, dependendo do tamanho, utilizará muito recurso e processamento. Além disso, se for realizada alguma comunicação fora do domínio, será necessário utilizar transações distribuídas, tornando a aplicação complexa.

A segunda opção é utilizar consistência eventual. Isto melhora a capacidade do sistema porque não está sendo utilizado um enorme histórico de entidade em memória enquanto um comando está sendo executado. No entanto, ela também possui certas consequências, como por exemplo, implica que o sistema de reserva complete as alterações e, caso outros subsistemas reportem uma falha, o sistema de reserva deve implementar uma transação de compensação que irá reverter a anterior. Isso também engloba a notificação do usuário sobre os erros em potencial. A decisão em utilizar uma ou outra deve considerar os pontos positivos e negativos, custo de desenvolvimento e a infraestrutura necessária. Por exemplo, pode ser necessário um message broker para receber e enviar mensagens de outros domínios.

Enviando notificações aos clientes

6. Notificações

Assim que o comando é finalizado, o sistema precisa informar ao cliente sobre o resultado. Se o cliente for outro sistema, esta parte pode ser omitida. Ainda sim, se for uma aplicação, provavelmente iremos precisar notificar o cliente sobre o sucesso ou a falha na execução de um comando, especialmente quando há um processo assíncrono envolvido. Ainda utilizando o comando Reservar, um dos requisitos é que os recursos específicos precisam da aprovação do dono antes para que possam ser atribuídos. Uma vez que a utilização do recurso é aprovada, o sistema deve enviar uma confirmação ao usuário. A notificação neste modelo começa quando o evento ReservaAprovada é gerado. Este evento é o resultado de outro comando que deve seguir a mesma lógica que descrevemos aqui, mas executado por outro usuário.

A ideia ao incluir isso no desenho é que a tarefa não é concluída até que a aprovação seja confirmada. Além disso, se a permissão for negada, o domínio provavelmente terá que reverter parte das alterações. Ao desenhar um sistema, devemos considerar todas as interações até que a tarefa esteja concluída.

Conclusão

Regras de negócio são as formas como aplicações expressam o conhecimento que têm sobre um determinado domínio. Estruturar regras de negócio com propriedade ajuda os desenvolvedores a entenderem o código e deve ser dividida em categorias diferentes de acordo com as responsabilidades. Além disso, estruturar o código de maneira a representar tarefas de usuário reduz o número de conceitos que a equipe de desenvolvimento precisa entender. Pelo fato das regras de negócio dependerem do desenho do sistema, um arquiteto de soluções deve considerar como o desenho irá suportá-las.

Sobre o autor

Fabian Lopez é um engenheiro de software e cursa mestrado em ciência da computação na faculdade Georgia Tech. Trabalha atualmente como arquiteto de soluções na Inter-American Development Bank, desenhando aplicações de gerenciamento de processos na indústria bancária. Lopez gosta de criar padrões de software porque fornecem um ponto de referência para resolver muitos problemas de desenvolvimento. Ele está regularmente envolvido em pesquisas com usuários para identificar padrões e desenvolver soluções que funcionam para os clientes. Lopez notou no passado que muitas soluções técnicas falharam porque os usuários se perderam enquanto as utilizavam, o que causava uma percepção ruim da qualidade da solução.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT