Onde colocar a validação de formato em um modelo de domínio “elegante” da CQRS?

5

Parece certo colocar a validação de formato dentro dos objetos de domínio (VOs ou entidades) porque é o local natural para alta coesão e o domínio sabe melhor o que cada descrição / atributo / propriedade de domínio significa. Muitos praticantes de DDD e autores de livros (Vaugh Vernon, Dan Bergh - e até mesmo Eric Evans sugerem, mas em um aspecto diferente: autorização, para modelar o domínio para refletir estes assuntos) sugerem projetar o modelo de domínio de uma forma a refletir e reforçar um bom estado do negócio.

Concordo que a validação de formato (por exemplo, a propriedade de endereço em EmailAddress VO deve ter no máximo 250 caracteres e deve corresponder a uma regex) deve ser implementada dentro dos objetos de domínio. Mas essas verificações de validação funcionam melhor com um modelo de domínio que será usado para alterações de estado e consultas de estado.

E sobre o CQRS, onde o lado do comando (onde o modelo de domínio é) tem pouco ou nenhum conhecimento sobre o lado da leitura. Deve-se reimplementar as mesmas verificações de formato de entrada no lado da consulta do aplicativo? No CQRS existem algumas responsabilidades comuns para o lado do comando e da consulta (como a validação do formato de entrada), de modo que as implementações usuais de validação de formato sugeridas pela maioria dos profissionais de DDD serão duplicadas.

Como se deve lidar com isso, sem tornar o modelo de domínio (do lado do comando) anêmico e sem saber o estado dos atributos que ele terá.

Um exemplo: pode haver um recurso que permita que um proprietário da conferência agende uma conferência e altere o número de assentos disponíveis. Mas como a sala de conferências não é grande o suficiente, o número máximo permitido de assentos seria 100. Assim, uma regra comercial seria: o proprietário de uma conferência não pode adicionar mais de 100 assentos para uma conferência agendada (também é necessário um assento mínimo para a conferência). estar em um estado válido). Então, um método estaria em um ConferenceAR:

changeNumberOfAvailableSeats(numberOfAvailableSeats) {
    if(!isNumber(numberOfAvailableSeats) || numberOfAvailableSeats > 100 ||   
            numberOfAvailableSeats < 1) {
        throw new DomainException ...
    }  

    // Change the number of available seats ...
}

No lado da consulta, pode haver uma página de interface do usuário na qual você pode encontrar todas as conferências agendadas com um determinado número de lugares disponíveis. Então, novamente, no lado de consulta do servidor do aplicativo, deve haver uma validação de formato que irá verificar se a consulta para conferências agendadas com um número de assentos disponíveis é um número e está no intervalo de 1-100. Esta consulta pode ser necessária por alguém que queira reservar um determinado número de lugares para uma conferência. Também conferências podem ser sobre o mesmo tópico, então pode-se ver uma conferência com o mesmo tópico várias vezes e escolher a mais barata ou com mais assentos disponíveis.

Então, novamente, deve-se reimplementar a validação de formato nos lados de consulta e de comando ou há outra solução?

P.S. : há muitas duplicatas de validação de formato (no lado de comando e de consulta), como a validação de formato de email ou uma validação de formato de moeda (se a moeda é: USD || CAD || AUD etc ...)

P.P.S. : Outra questão que apareceu: O lado da consulta do aplicativo requer alguma validação de formato de entrada? Se a entrada não for um formato válido, ela não retornará nada, a consulta não encontrou dados relacionados à solicitação. Eu vejo que a validação de formato no lado da consulta é puramente uma medida de segurança (ou seja, para estouros de buffer). Então, a validação do formato de entrada é realmente necessária no lado da consulta?

    
por Tudor 19.06.2014 / 21:23
fonte

2 respostas

3

Eu acho que, se os objetos do seu domínio no lado do comando estiverem sempre em um estado válido, você não precisará se preocupar com o fato de as consultas retornarem resultados inválidos.

O que você faria, de qualquer forma, se descobrisse uma invalidez no lado de leitura, afinal? Diga ao repositório de leitura para reinserir os valores? ; -)

Se o lado de leitura tivesse checagem, ele pensaria que estaria na área de algum tipo de unidade ou teste de integração, porque ao invés de uma mensagem de erro de entrada de dados, é um erro.

Uma das coisas sobre o CQRS é extrair essas preocupações, mais apenas ter coisas em um só lugar. Caso contrário, torna-se mais difícil, não mais fácil (na verdade, pode ser tão fácil ou mais fácil, caso contrário, procure uma maneira melhor de implementá-lo ou continuar estudando-o).

    
por 10.07.2014 / 03:49
fonte
0

Se você estiver usando eventos para transferir dados, provavelmente poderá tratar muitas dessas preocupações como simplesmente outro tipo de dados que o modelo de leitura precisa armazenar e organizar de uma maneira conveniente. Por exemplo,

  • Você já desejará um ouvinte de eventos como RoomCreated e RoomDisabled do domínio, porque você está mantendo algum tipo de representação rápida de consulta sobre quais salas estão disponíveis, certo? Por que não manter uma variável biggestActiveRoomSize ao mesmo tempo?
  • Ver um evento ContactCreated ou ContactEmailUpdated ? Verifique o tamanho e atualize um maxEmailCharacters armazenado.
  • Ver um evento PricingPosted ? Verifique se a moeda dentro do evento está presente / adicionada à sua própria lista knownCurrencies . Isso significa que logo após ser usado, ele se tornará uma opção com a qual as pessoas podem pesquisar.

Em outras palavras, o que vier do domínio é automaticamente válido e tudo o que você vê expande o envelope do que você deseja permitir que o usuário digite.

Concedido, isso não funciona para certas coisas complexas, como expressões regulares ou lógica if / then. Para esses casos, talvez:

  • Como parte do processo de criação, a compilação do modelo de domínio emite um arquivo de configuração que o lado da consulta pode carregar e usar.
  • Duplicação direta da lógica. Não é o ideal, mas é viável, desde que o lado da consulta seja muito claro sobre onde a fonte autoritativa está e você terá um procedimento para atualizar os valores que os humanos seguirão.
  • Idéia mais louca: faça com que o modelo de domínio armazene / transmita um evento sempre que ele for iniciado, contendo esse tipo de informação. Múltiplos modelos de leitura podem decidir o que (se alguma coisa) eles querem fazer com ele.

Eu acho que você deve planejar uma duplicação alguma (sempre há algo), mas quando se trata de "quais valores ou intervalos estão sendo realmente usados", eu tentaria fazer apenas outra parte do modelo de leitura.

    
por 17.07.2014 / 08:29
fonte