Pergunta

Depois de ler os livros de Evan e Nilsson, ainda não tenho certeza de como gerenciar o acesso a dados em um projeto controlado por domínio.Os métodos CRUD devem fazer parte dos repositórios, ou seja,OrderRepository.GetOrdersByCustomer(customer) ou devem fazer parte das entidades:Cliente.GetOrders().A última abordagem parece mais OO, mas distribuirá o acesso a dados para um único tipo de entidade entre vários objetos, ou seja,Customer.GetOrders(), Invoice.GetOrders(), ShipmentBatch.GetOrders(), etc.E quanto a Inserir e atualizar?

Foi útil?

Solução

Os métodos CRUD devem fazer parte do Repositório...ish.Mas acho que você deveria perguntar por que possui vários métodos CRUD.O que eles realmente fazer?O que eles são realmente para?Se você realmente identificar os padrões de acesso a dados que seu aplicativo usa, acho que isso torna o repositório muito mais útil e evita que você precise fazer uma cirurgia forçada quando certos tipos de alterações acontecem em seu domínio.

CustomerRepo.GetThoseWhoHaventPaidTheirBill()

// or

GetCustomer(new HaventPaidBillSpecification())

// is better than

foreach (var customer in GetCustomer()) {
    /* logic leaking all over the floor */
}

Os métodos do tipo "Salvar" também devem fazer parte do repositório.

Se você tiver raízes agregadas, isso evita que você tenha uma explosão no repositório ou que a lógica se espalhe por toda parte:Você não tem 4 x # de padrões de acesso a dados de entidades, apenas aqueles que você realmente usa nas raízes agregadas.

Esses são meus $ 0,02.

Outras dicas

DDD geralmente prefere o padrão de repositório ao padrão de registro ativo sugerido com Customer.Save.

Uma desvantagem do modelo Active Record é que ele praticamente pressupõe um único modelo de persistência, exceto alguns códigos particularmente intrusivos (na maioria das linguagens).

A interface do repositório é definida na camada de domínio, mas não sabe se seus dados estão armazenados em um banco de dados ou não.Com o padrão de repositório, posso criar um InMemoryRepository para poder testar a lógica do domínio isoladamente e usar injeção de dependência no aplicativo para que a camada de serviço instancie um SqlRepository, por exemplo.

Para muitas pessoas, ter um repositório especial apenas para testes parece bobagem, mas se você usar o modelo de repositório, poderá descobrir que realmente não precisa de um banco de dados para sua aplicação específica;às vezes, um simples FileRepository resolverá o problema.Casar-se com um banco de dados antes de saber que precisa dele é potencialmente limitante.Mesmo que um banco de dados seja necessário, é muito mais rápido executar testes em um InMemoryRepository.

Se você não tem muita lógica de domínio, provavelmente não precisa de DDD.ActiveRecord é bastante adequado para muitos problemas, especialmente se você tiver principalmente dados e apenas um pouco de lógica.

Vamos recuar por um segundo.Evans recomenda que os repositórios retornem raízes agregadas e não apenas entidades.Portanto, supondo que seu Cliente seja uma raiz agregada que inclui Pedidos, quando você buscou o cliente em seu repositório, os pedidos vieram junto com ele.Você acessaria os pedidos navegando no relacionamento de Cliente para Pedidos.

customer.Orders;

Então, para responder à sua pergunta, as operações CRUD estão presentes em repositórios raiz agregados.

CustomerRepository.Add(customer);
CustomerRepository.Get(customerID);
CustomerRepository.Save(customer);
CustomerRepository.Delete(customer);

Eu fiz isso das duas maneiras que você está falando. Minha abordagem preferida agora é o método persistente ignorante (ou PONO - Plain Ole '.Net Object), onde suas classes de domínio estão preocupadas apenas em serem classes de domínio.Eles não sabem nada sobre como persistem ou mesmo se persistem.É claro que você tem que ser pragmático sobre isso às vezes e permitir coisas como um Id (mas mesmo assim eu apenas uso um supertipo de camada que tem o Id para que eu possa ter um único ponto onde coisas como o valor padrão residem)

A principal razão para isto é que me esforço para seguir o princípio da Responsabilidade Única.Seguindo esse princípio, achei meu código muito mais testável e de fácil manutenção.Também é muito mais fácil fazer alterações quando necessárias, pois só tenho uma coisa em que pensar.

Uma coisa a ser observada é o inchaço do método que os repositórios podem sofrer.Obter pedido pelo cliente..Obter todos os pedidos..Obter pedidos com 30 dias de idade.etc etc.Uma boa solução para esse problema é observar o padrão Query Object.E então seus repositórios podem simplesmente receber um objeto de consulta para executar.

Eu também recomendo fortemente procurar algo como NHibernate.Inclui muitos dos conceitos que tornam os Repositórios tão úteis (Mapa de Identidade, Cache, objetos de consulta..)

Mesmo em um DDD, eu manteria as classes e rotinas de acesso a dados separadas das entidades.

As razões são,

  1. A testabilidade melhora
  2. Separação de preocupações e design modular
  3. Mais sustentável no longo prazo, à medida que você adiciona entidades, rotinas

Não sou especialista, apenas minha opinião.

O que é irritante em Aplicando DDD&P de Nilsson é que ele sempre começa com "Eu não faria isso em uma aplicação do mundo real, mas..." e então seu exemplo segue.De volta ao assunto:Acho que OrderRepository.GetOrdersByCustomer(customer) é o caminho a seguir, mas também há uma discussão na lista de discussão ALT.Net (http://tech.groups.yahoo.com/group/altdotnet/) sobre DDD.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top