Domain Driven Design - projetando raízes agregadas

5

Imagine que você esteja criando um aplicativo para organizar workshops. O workshop em si é bastante complicado - ele funciona como uma máquina de estados com múltiplos estados possíveis e transições entre eles.

Estamos usando DDD, CQRS e terceirização de eventos.

E agora, os casos de uso:

1) deve ser possível atribuir TodoItems a um Workshop e executar operações CRUD neles

2) deve-se poder enviar recursos adicionais para um determinado Workshop (slides, fotos, arquivos zip / tar.gz etc.) e também realizar operações CRUD neles

3) deve-se adicionar um PossibleTerm (com um palestrante, data e sala especificados) a um Workshop. Além disso, deve haver uma maneira de modificá-los / apagá-los.

Mais tarde, há uma votação sobre esses termos, o sistema tenta reservar espaço para alguns termos (digamos, para dois termos) que ganharam votação e os usuários devem ser divididos entre esses termos.

Aqui tenho as seguintes soluções:

1) Modele TodoItems, Recursos e PossíveisTermos como parte de um Workshop.

Prós:

  • tudo é onde conceitualmente pertence
  • sem consistência eventual (provavelmente não é um grande problema ...)

Contras:

  • O agregado do Workshop é cheio de todos os métodos CRUD para todas as coisas.
  • De acordo com a Implementing Domain Driven Design de Vaughn Vernon, a criação de enormes raízes agregadas é um antipadrão

2) Crie raízes agregadas para armazenar todos os "itens" (por exemplo, TodoItemList, PossibleTermList, Resources ou o que for que você vai chamá-los).

Prós:

  • O agregado do Workshop é menor, não está relacionado com essas listas (a única conexão seria que, por exemplo, o PossibleTermList contém uma referência ao WorkshopId)

Contras:

  • Quando o CreateWorkshopCommand chega, você é forçado a criar não apenas um Workshop, mas também agregados adicionais que precisam existir após a criação do Workshop. Para evitar isso, pode haver algum tipo de CreationalSaga, ouvir WorkshopCreatedEvent e produzir comandos adequados para criar parentes, mas não acho que seja uma boa ideia.

3) Modelo PossibleTerms, Resource, TodoItem como raízes agregadas em si

Prós:

  • não há necessidade de criar 'wrappers agregados' (como em 2))

Contras:

  • novamente, você está atravancando Workshop com pelo menos métodos de fábrica
  • é difícil implementar o recurso de escolha de termos - para contar votos e, posteriormente, atribuir User a um Termo específico para consultar seu repositório em busca de todos os Termos correspondentes ao Workshop ID e assim por diante - isso leva a operações em vários agregados dentro de uma transação.

Pergunta: qual solução soa melhor para você? Talvez você tenha idéias diferentes?

(Pergunta bônus: Eu preciso executar operações CRUD em Recursos individuais / TodoItem. Eu prefiro modelar então como objetos de valor, mas como eles são então identificados?)

    
por slnowak 28.03.2015 / 10:19
fonte

2 respostas

2

Acho que você está perdendo a análise transacional. Quais entidades serão modificadas por cada um dos seus casos de uso? Algum deles impactará mais de uma entidade?

Quais são seus invariantes? Alguns deles abrangem várias entidades (por exemplo, dois Term s não podem usar o mesmo Room na mesma data / hora)? Eles são invariantes verdadeiros ou a consistência final pode ser suficiente?

Vaughn Vernon tem uma boa abordagem passo a passo para agregar modelagem aqui: link

    
por 01.04.2015 / 15:14
fonte
0

Parece-me que a pior escolha é tentar modelar listas. O objetivo de um agregado é garantir uma invariante de negócios. Que invariante uma coleção aplica? Se o comando addItem for invocado, a lista pode dizer não?

Tornar todas as entidades parte do agregado do Workshop é uma opção natural - especialmente se as outras entidades não "fizerem sentido" fora do contexto de um workshop. Se você tiver uma invariante de negócios que restrinja várias entidades, precisará que essas entidades façam parte do mesmo agregado.

Mas isso significa que você tem contenção: Alice, trabalhando em ToDoItem: 1, e Bob, trabalhando em ToDoItem: 2, não pode salvar suas alterações "ao mesmo tempo" por causa do conflito de gravação. / p>

Opção # 3, onde cada entidade é seu próprio agregado, cuida do problema de contenção. Alice e Bob podem cometer suas alterações sem conflito, os ToDoItems podem impor sua própria invariante.

É verdade que as entidades têm diferentes ciclos de vida e você precisa estar bem com isso. Você também precisa trabalhar um pouco mais para reforçar uma invariável que abrange vários agregados.

A linguagem onipresente deve oferecer dicas sobre se os componentes de um workshop precisam fazer parte da mesma transação que o workshop em si (se já houver um processo de negócios para mitigar contingências, provavelmente você não tem consistência de transação exigência.

Dito isto, se o seu domínio é CRUD (se o modelo não puder vetar o julgamento dos operadores humanos), tentar inventar "agregados" a partir do nada pode não ser a melhor jogada.

    
por 12.01.2016 / 06:27
fonte