Os Objetos de Domínio no Design Orientado a Domínio devem ser apenas de gravação?

13

Eu leio sobre Design Orientado a Domínio por quase dois anos e venho introduzindo cautelosamente alguns conceitos em meu trabalho diário ou, pelo menos, fazendo planos de como as coisas que faço regularmente podem ser feitas dentro de um Design Orientado a Domínio.

Uma conclusão que comecei a chegar, especialmente em resposta à leitura mais sobre CQRS (Segmentação de Eventos e CQRS), de que talvez os objetos de domínio sejam usados ​​apenas para fins de gravação. Para ser mais claro, parece que o que as pessoas estão sugerindo sutilmente em grande parte da documentação que li que os objetos de domínio são responsáveis ​​por realizar operações / cálculos, validação e validação, e então existem principalmente para fornecer um caminho para a persistência através a infraestrutura fornecida em uma implementação do Repositório. Embora eu goste do fato de que isso pode simplificar muito o modelo de domínio, pois elimina a responsabilidade de expor o estado.

Se é realmente correto que objetos de domínio sejam usados ​​principalmente como objetos somente gravação, isso levanta algumas questões para mim que espero que alguém possa responder.

  1. Como se executa testes de unidade em um objeto que possui setters ou métodos que modificam o estado de um objeto, mas que não fornecem nenhuma interface pública externa para ler o estado, como getters de propriedade em C #? Tudo bem expor o estado apenas com o objetivo de tornar esse objeto testável?
  2. Como alguém mostra ao usuário os resultados dos cálculos ou operações realizados no domínio sem ter que persistir e depois extrair os resultados do armazenamento persistente fora do contexto do domínio? Tudo bem expor o estado apenas com o objetivo de mostrar resultados.

A regra geral é que os únicos getters de propriedade (obter acessadores) devem ser aqueles que também podem ser gravados no domínio? Ou dito de maneira diferente, as propriedades somente leitura devem ser a única coisa a evitar, pois elas existem apenas para fins de leitura e, portanto, não desempenham um papel necessário no modelo de domínio real?

Material relacionado:

  1. TDD, DDD e encapsulamento
jpierson
fonte

Respostas:

9

Não tenho certeza de que existe uma resposta "única e verdadeira" para uma abordagem de design que, para ser justa, ainda está evoluindo. Primeiro, DDD e CQRS não são a mesma coisa, embora o pessoal do CQRS pareça ter derivado de um ponto de partida influenciado pelo DDD.

Há muita coisa acontecendo na mentalidade do DDD e muito disso tem a ver com limites de problemas adequadamente definidos, comunicação entre as partes interessadas e interação entre sistemas, não necessariamente uma implementação específica no código, então não acho que seja muito difícil. núcleo é uma virtude.

Talvez você esteja assistindo a um debate sobre se e como os objetos de domínio devem ser alteráveis ​​e que função um objeto de domínio serve em um sistema como um todo. O CQRS divide um sistema em caminhos de leitura e gravação, por isso é sensato concluir que você realmente não precisa de acesso de leitura quando está no caminho de gravação. A leitura se torna algo que você faz contra os eventos gerados por alguns objetos de domínio e consumidos (manipulados) por outros. Se você voltar um pouco na história do CQRS, encontrará argumentos de que os objetos do domínio não devem ter setters, apenas getters e um único método 'manipulador'. A lógica aqui é que apenas o consumo de eventos deve resultar em mudança de estado, e essa mudança é totalmente tratada internamente pelo objeto de domínio.

Você mostra os resultados da mudança tratando-os como artefatos de mudança separados, colocando-os em uma estrutura persistente plana e separada (por exemplo, uma tabela) e lendo-a como se estivesse lendo um relatório sobre o estado atual e histórico do sistema . Por exemplo, você pode consumir um evento extraindo os dados necessários para lê-los e salvando-os em uma tabela de banco de dados que mapeia de perto uma única visualização (por exemplo, uma tela) do seu sistema.

Se você experimenta esse estilo, saiba que outros programadores provavelmente não estarão familiarizados com essa abordagem e que existem relativamente poucos cenários (mas interessantes) em que é justificável como uma abordagem de design.

Para testes de unidade, existem algumas abordagens que podem funcionar para você. A primeira e mais natural é verificar se os eventos que você espera ver gerados pelos objetos do seu domínio estão corretos. Um objeto de domínio pode gerar um evento alterado genérico contendo informações sobre a alteração. Você pode verificar isso. Você pode verificar o fato de que o evento foi gerado e que outros eventos não foram gerados.

Outra abordagem é usar o Test Spies que expõe atributos legíveis no objeto do seu domínio para que você possa verificar as alterações de estado. Por exemplo, você pode herdar do seu objeto de domínio, adicionar alguns acessadores para ler o que seria o estado encapsulado e verificar se está correto.

Novamente, você está confuso porque essas abordagens são confusas. Se você deseja adotar algumas boas idéias em sua programação, leve os detalhes interessantes primeiro. Os limites do DDD e a explicitação de funções são alterações na sua maneira de pensar em se comunicar com seu código. O CQRS, no mínimo, sugere que a leitura e gravação de dados são operações segregáveis. Essa percepção leva você a pensar com muita clareza sobre qual é o papel dos dados que você precisa apresentar, quanto você realmente precisa, quem os está consumindo, qual a atualização necessária, etc ... Você não precisa de um implementação completa de Event Sourcing para adotar um melhor encapsulamento em sua codificação. Você pode começar concentrando-se apenas nas operações atômicas do seu objeto, abordagens "Diga, não pergunte" ao design da interface do objeto,

pfries
fonte
1
+1 para começar com os bits jucy. Além disso: morder apenas o CQS (pulando a parte dos 'eventos' por enquanto) pode ser um bom ponto de partida.
cottsak
1

Os Objetos de Domínio no Design Orientado a Domínio devem ser apenas de gravação?

Não. O CQRS pode ser usado junto com o DDD.

NimChimpsky
fonte
Mas a parte Query do CQRS trata de consultar dados usados ​​pelo modelo de domínio para gravar alterações no modelo ou pode ser usado para consultar dados da camada de aplicativo que, por exemplo, mostra os valores para o usuário? Estou ouvindo de alguns que o DDD tem tudo a ver com coordenar alterações e não deve ser usado para ler para nenhum outro propósito além de coordenar alterações em outro objeto no modelo de domínio. A decisão, de uma maneira ou de outra, significaria um design de modelo radicalmente diferente, uma vez que os dados expostos nos objetos do domínio teriam uma variação limitada, se consumidos apenas no domínio.
jpierson
0

Os testes de unidade do modelo de domínio devem verificar se, para cada comando executado, os eventos corretos do domínio são gerados. Seus comandos de domínio e eventos capturados podem ser interrogados quanto ao estado.

Você também pode substituir ToString()os comandos e eventos do seu domínio para fornecer relatórios automáticos e legíveis do estado do estado.

Para responder à sua segunda pergunta, para exibir os resultados dos comandos, você deve organizar para que os eventos do domínio sejam 'publicados' no seu modelo de leitura.

Ed James
fonte
Você poderia elaborar um pouco sobre se isso ainda se aplica quando você não está usando a fonte de eventos?
jpierson
1
Sem a fonte do evento, talvez minha sugestão não funcione; Não sei os caminhos do seu código. Para um objeto de domínio que idealmente não expõe nenhuma propriedade, talvez você possa implementar explicitamente uma interface de teste que expõe as propriedades que deseja testar. Somente seu código de teste 'saberá' converter esses objetos de domínio na interface de teste.
Ed James
Obrigado por essa sugestão. Sinto-me um pouco desconfortável com a ideia de modificar minhas classes de domínio especificamente para testabilidade, mas suponho que essa possa ser uma daquelas áreas cinzentas que ainda estão no Design Orientado a Domínio, se você quiser que seja testável. Outro pensamento é que, se alguém expuser estabilizabilidade e testabilidade através da mesma interface, pelo menos você apresentará apenas uma dependência de infraestrutura em vez de duas. O que os outros pensam disso?
precisa saber é o seguinte