Estou mergulhando nos conceitos do Domain-Driven Design (DDD) e achei alguns princípios estranhos, especialmente no que diz respeito ao isolamento do domínio e do modelo de persistência. Aqui está o meu entendimento básico:
- Um serviço na camada de aplicativo (fornecendo um conjunto de recursos) solicita objetos de domínio de um repositório necessário para executar sua função.
- A implementação concreta desse repositório busca dados do armazenamento para o qual foi implementado
- O serviço informa ao objeto de domínio, que encapsula a lógica de negócios, para executar determinadas tarefas que modificam seu estado.
- O serviço informa ao repositório para persistir o objeto de domínio modificado.
- O repositório precisa mapear o objeto de domínio de volta para a representação correspondente no armazenamento.
Agora, dadas as suposições acima, o seguinte parece estranho:
Anúncio 2:
O modelo de domínio parece carregar o objeto de domínio inteiro (incluindo todos os campos e referências), mesmo que não sejam necessários para a função que o solicitou. Carregar completamente pode nem ser possível se outros objetos de domínio forem referenciados, a menos que você carregue também esses objetos de domínio e todos os objetos a que se referem, e assim por diante. O carregamento lento vem à mente, o que significa que você começa a consultar seus objetos de domínio, que devem ser de responsabilidade do repositório.
Dado esse problema, a maneira "correta" de carregar objetos do domínio parece ter uma função de carregamento dedicada para cada caso de uso. Essas funções dedicadas carregariam apenas os dados exigidos pelo caso de uso para o qual foram projetados. Aqui é onde o embaraço entra em jogo: primeiro, eu precisaria manter uma quantidade considerável de funções de carregamento para cada implementação do repositório, e os objetos de domínio acabariam em estados incompletos, carregando null
em seus campos. Tecnicamente, este último não deve ser um problema porque, se um valor não foi carregado, não deve ser exigido pela funcionalidade que o solicitou. Ainda é estranho e um risco potencial.
Anúncio 3:
Como um objeto de domínio verificaria restrições de exclusividade na construção, se ele não tem nenhuma noção do repositório? Por exemplo, se eu quisesse criar um novo User
com um número de previdência social exclusivo (fornecido), o conflito mais antigo ocorreria ao solicitar ao repositório que salve o objeto, apenas se houver uma restrição de exclusividade definida no banco de dados. Caso contrário, eu poderia procurar um User
com a previdência social fornecida e relatar um erro, caso exista, antes de criar uma nova. Mas as verificações de restrição permaneceriam no serviço e não no objeto de domínio ao qual pertencem. Acabei de perceber que os objetos de domínio estão muito bem autorizados a usar repositórios (injetados) para validação.
Anúncio 5:
Eu percebo o mapeamento de objetos de domínio para um back-end de armazenamento como um processo intensivo de trabalho, em comparação com os objetos de domínio modificando diretamente os dados subjacentes. É, obviamente, um pré-requisito essencial para dissociar a implementação concreta do armazenamento do código de domínio. No entanto, isso realmente tem um custo tão alto?
Aparentemente, você tem a opção de usar ferramentas ORM para fazer o mapeamento para você. No entanto, isso geralmente exige que você projete o modelo de domínio de acordo com as restrições do ORM ou introduza uma dependência do domínio para a camada de infraestrutura (usando anotações do ORM nos objetos de domínio, por exemplo). Também li que os ORMs introduzem uma sobrecarga computacional considerável.
No caso de bancos de dados NoSQL, para os quais quase não existem conceitos semelhantes a ORM, como você monitora quais propriedades foram alteradas nos modelos de domínio save()
?
Editar : Além disso, para que um repositório acesse o estado do objeto de domínio (ou seja, o valor de cada campo), o objeto de domínio precisa revelar seu estado interno que quebra o encapsulamento.
Em geral:
- Para onde iria a lógica transacional? Isso é certamente persistência específica. Algumas infra-estruturas de armazenamento podem nem mesmo suportar transações (como repositórios simulados na memória).
- Para operações em massa que modificam vários objetos, eu precisaria carregar, modificar e armazenar cada objeto individualmente para passar pela lógica de validação encapsulada do objeto? Isso se opõe à execução de uma única consulta diretamente no banco de dados.
Gostaria de receber alguns esclarecimentos sobre este tópico. Minhas suposições estão corretas? Caso contrário, qual é a maneira correta de resolver esses problemas?