Devo usar uma raiz agregada ao projetar meu repositório?

8

Eu tenho uma entidade chamada Mestre que é composta por um número de entidades Escravo.

Só pode haver um mestre no meu banco de dados e desejo consultar repositórios para obter o escravo para um determinado ID.

Inicialmente, criei um SlaveRepository e o perguntei por ID. Isso parece bom e funciona e outros desenvolvedores podem usar meu repositório.

Depois pensei em raízes agregadas, criei um MasterRepository, retornei o Master e fiz um loop para obter a entidade Slave necessária. O problema que senti aqui é que, quando eu expô-lo a outros desenvolvedores, eles precisam fazer o mesmo; então, acabei tendo um método no MasterRepository chamado GetSlaveByID (id da string) e então pude obter o Slave diretamente (oculta a funcionalidade do loop )

Agora, meu repositório deve retornar um Escravo, mesmo que seja chamado de MasterRepository? E mais importante, qual é o caminho certo a seguir?

Eu estou nos estágios iniciais de tentar aplicar DDD e TDD, então provavelmente há muitas coisas em que preciso pensar antes de decidir qual é a maneira correta, eu acho.

JD01
fonte

Respostas:

9

De acordo com a maneira de Eric Evans de Design Orientado a Domínio, você deve evitar repositórios para raízes não agregadas.

Ele afirma claramente:

Somente Raízes Agregadas podem ser obtidas diretamente com consultas ao banco de dados. Tudo o resto deve ser feito através da travessia.

Mas isso também significa que o repositório para a raiz precisa preencher todos os requisitos. Se você precisar de acesso direto a partes do agregado, um objeto raiz agregado ou seu repositório será responsável por fazê-lo.

Portanto, é perfeitamente bom ter métodos como o seguinte em um repositório raiz agregado:

Slave GetSlave(string id)

Mas essa assinatura é um pouco perigosa, pois as identidades de crianças no DDD só fazem sentido no contexto de um objeto raiz real e são superficiais sem a raiz.

Isso nos leva a uma abordagem melhor e mais semelhante a DDD para uma implementação em um repositório:

Slave GetSlaveOfMaster(Master master, string slaveId)
// or
Slave GetSlaveOfMaster(Identity masterId, Identity slaveId)

Mas eu provavelmente nem teria esse método no repositório, mas na própria entidade mestre para acessar rapidamente os escravos. Possivelmente até exposto como uma hashtable. Essa é a abordagem mais limpa que consigo pensar.

//within the Master entity
Slave GetSlave(Identity slaveId);

Espere, este não é o fim da história. Se você precisar buscar escravos sem o conhecimento do mestre, pense em seus agregados e no seu modelo de objeto. Talvez você precise de um segundo agregado em que o escravo seja uma raiz e, em seguida, você deve ter um repositório personalizado para eles. O escravo é, então, não apenas um filho do mestre, mas uma hierarquia separada que provavelmente também faz referência a um mestre. É importante saber se um objeto escravo pode existir sem um mestre. Se possível, um agregado separado é provavelmente o caminho a percorrer.

Falcão
fonte
Muito obrigado por todas as informações. Vou tentar me apossar do livro de Eric para entender mais.
JD01
você mencionou um segundo agregado, isso é possível? Você está dizendo que temos mestre como agregado raiz e também escravo no mesmo modelo?
JD01
1
@ JD01: Absolutamente. Você pode ter um agregado escravo separado em que o escravo é a raiz. Isso está de acordo com o DDD, desde que você tenha em mente que apenas objetos raiz são expostos. Isso significa que você não pode ter uma terceira classe que não seja raiz e faça parte de várias agregações. Mas você pode ter um agregado escravo que também é referenciado a partir do agregado mestre como filho. No entanto, é aqui que as coisas ficam complicadas (relacionamentos complexos etc.). Tentamos simplificar isso aqui apenas referenciando objetos DTO quando alguma raiz precisa fazer referência a outra raiz. Os DTOs são somente leitura e não podem ser alterados.
Falcon
1
@ JD01: É claro que essas referências de DTOs podem ser trocadas, mas os DTOs são imutáveis. Portanto, se eu obtiver meu SlaveDto de um mestre, não posso alterá-lo. Quando eu quero mudar, preciso buscar seu próprio agregado e alterá-lo lá. Esses DTOs contêm apenas dados simples, sem hierarquias e apenas o necessário.
Falcon
1
@ JD01: Além disso, você deve se perguntar se um escravo pode existir sem um mestre. Se não puder, não será uma raiz agregada. Veja minha pequena atualização.
Falcon
1

Em geral, dentro do limite agregado, deve haver apenas um repositório. E - como Falcon disse - você pode acabar com dois agregados separados, mestre e escravo.

No entanto, parece que o foco principal da sua pergunta é a recuperação de dados, enquanto no DDD deve ser um comportamento. Os limites agregados são uma conseqüência de restrições impostas pelo comportamento (coisas que mudam juntas e invariantes devem ser impostas); a estrutura interna do agregado é uma conseqüência dessa escolha.

Por exemplo, se você agrupar as coisas corretamente de acordo com a necessidade de mudança, não será necessário chamar um Repositório externo. Na maioria dos casos, os dados necessários para uma operação de negócios no Agregado já devem estar dentro dos limites agregados; a necessidade de acessar agregados diferentes é provavelmente o cheiro de um limite inconsistente.

ZioBrando
fonte