DDD: Regras de negócio nos repositórios?

Ontem eu estava assistindo a um vídeo de uma palestra do Giovanni Bassi sobre DDD (http://unplugged.giggio.net/unplugged/post/Video-sobre-Domain-Driven-Design.aspx), em geral achei muito boa mas não consegui engolir uma coisa:
O Giovanni diz que repositórios não podem ter regras de negócio.

Mas o repositório não faz parte da camada de negócios? Nesse caso, por que não poderia ter regras de negócio?

Segundo o que tenho lido, a diferença entre um repositório e um DAO é justamente essa: O DAO é infra-estrutura, e por isso não pode ter regras de negócio. Já o repositório faz parte do negócio, por isso pode executar validações e tudo mais

Já começa errado dizer que seu domínio esta em uma camada. Esqueça esse negócio de camada. Pense em um domínio de negócio. E nem o repositório e nem ninguém possui a regra de negócio como era feito com os BO (business objects) as regras de negócios estão implícitas no domínio como um todo.

Ok… Então quais classes devem validar estas regras?

Cite um exemplo de validação !!!

Vejamos…

Em um sistema de hoteis, não pode haver mais de uma conta para o mesmo quarto no mesmo período

Legal…agora qual é o nosso domínio ?

Quarto
Hotel
Despesa
Serviço
Periodo
Reserva
etc…

Um quarto possui várias reservas, cada reserva é composta por um período. Cada reserva só pode conter uma conta por período. Onde isso deveria ser feito ??? Se eu estivesse escrevendo este sistema seria na reserva do quarto, após a reserva ninguém mais pode entar neste quarto até o término do período, o que garante que este período só tera uma conta.

Tem uma Thread que fala sobre isso e apesar de um pouco antiga tem bastante conteúdo pra te ajudar, creio eu.

http://www.guj.com.br/posts/list/85604.java

[]s

[quote=magnomp]Vejamos…

Em um sistema de hoteis, não pode haver mais de uma conta para o mesmo quarto no mesmo período[/quote]

Num modelo orientado a objetos invariantes sao implementadas advinha, nos objetos. Encapsulamento é seu amigo.

Pelo pouco que sei de DDD domain driver designer é que vc deixa o modelo anemico de lado e adota as regras de negocio na camada de modelo, onde possui suas entidades.

Emerson Macedo,
Eu já havia lido essa thread, foi uma discussão realmente boa

Giulliano,
Isso implica que o quarto tenha que acessar o repositório, para poder consultar as reservas. Correto?
Não há nenhum problema nisso?

[quote=magnomp]Emerson Macedo,
Eu já havia lido essa thread, foi uma discussão realmente boa

Giulliano,
Isso implica que o quarto tenha que acessar o repositório, para poder consultar as reservas. Correto?
Não há nenhum problema nisso?[/quote]

Sim…se o quarto precisar acessar qualquer informação ele pode recorrer aos repositórios que por sua vez podem recorrer a um DAO se for necessário.

Mas olha só…no mundo real vc não cria um quarto e busca uma reserva para ele. Vocẽ cria uma reserva e associa ela a um quarto disponível.

; )

Acho radicalismo dizer que repositórios não podem conter regras de negócio, uma vez que eles pertencem ao negócio. O que acontece é que muitos desenvolvedores adotam a implementação em Java onde repositório é uma interface implementada diretamente por um DAO, neste caso regras de negócio na camada de infraestrutura pode não ser uma boa. Mas o crédito disto é da implementação e não do padrão em si.

[quote=Giulliano][quote=magnomp]Emerson Macedo,
Eu já havia lido essa thread, foi uma discussão realmente boa

Giulliano,
Isso implica que o quarto tenha que acessar o repositório, para poder consultar as reservas. Correto?
Não há nenhum problema nisso?[/quote]

Sim…se o quarto precisar acessar qualquer informação ele pode recorrer aos repositórios que por sua vez podem recorrer a um DAO se for necessário.

; ) [/quote]

Ou seja, abusando da abstração, poderia enxergar o repositório como uma “facade” para um DAO ou outras implementações de consultas a arquivos, banco de dados, WS, etc…?

Aproveitando a discução:

imaginem um caso, onde é necessário buscar todos os quartos que estarão disponíveis para uso em um período futuro.
Com certeza esta busca teria um certo grau de complexidade que, inevitavelmente, iria colocar lógica de negocio no repositorio. Se o repositório não tiver acesso a nem isso da lógica de negócio, seria necessário trazer todos os quartos, todas as reservas e o que mais fosse necessário, fazer um processamento via linguagem de programação, o que geraria um overhead grande.

Neste caso, o que é recomendado?

Abraços

[quote=Daniel_MV]
Ou seja, abusando da abstração, poderia enxergar o repositório como uma “facade” para um DAO ou outras implementações de consultas a arquivos, banco de dados, WS, etc…?[/quote]

No livro de DDD do Eric Evans (o livro azul) ele diz para enxergarmos os reposiórios como Coleções com métodos epecializados para seu negócio, exemplos:

adicionar
retornarTodosOsQuartos()
retornarQuartosDisponiveis()

etc.

[quote=marvinla][quote=Daniel_MV]
Ou seja, abusando da abstração, poderia enxergar o repositório como uma “facade” para um DAO ou outras implementações de consultas a arquivos, banco de dados, WS, etc…?[/quote]

No livro de DDD do Eric Evans (o livro azul) ele diz para enxergarmos os reposiórios como Coleções com métodos epecializados para seu negócio, exemplos:

adicionar
retornarTodosOsQuartos()
retornarQuartosDisponiveis()

etc.[/quote]

Então considerando que exista um DAO que já utiliza esse tipo de nomenclatura em vez de termos técnicos (como eu costumo fazer normalmente).

DAOHotel{ void adicionarReserva(Cliente c); List<Quartos> retornarTodosOsQuartos(); List<Quartos> retornarQuartosDisponiveis(); }

Qual seria a grande vantagem? A não ser isolar negócio da implementação da consulta. Mas isso um Negocio já faz.

[code]NegocioHotel{

List retornarTodosOsQuartos(){

/// Consulta mais regras de negócio.
return new DAOHotel().retornarTodosOsQuartos();

}

}[/code]

Ao meu ver o benefício que vejo dos repositórios nesse caso (lembrando que ainda estou tentando entender o DDD) seria essa “facade”, tendo uma camada a mais para abstração.

Seria isso?

[quote=Daniel_MV][quote=marvinla][quote=Daniel_MV]
Ou seja, abusando da abstração, poderia enxergar o repositório como uma “facade” para um DAO ou outras implementações de consultas a arquivos, banco de dados, WS, etc…?[/quote]

No livro de DDD do Eric Evans (o livro azul) ele diz para enxergarmos os reposiórios como Coleções com métodos epecializados para seu negócio, exemplos:

adicionar
retornarTodosOsQuartos()
retornarQuartosDisponiveis()

etc.[/quote]

Então considerando que exista um DAO que já utiliza esse tipo de nomenclatura em vez de termos técnicos (como eu costumo fazer normalmente).

DAOHotel{ void adicionarReserva(Cliente c); List<Quartos> retornarTodosOsQuartos(); List<Quartos> retornarQuartosDisponiveis(); }

Qual seria a grande vantagem? A não ser isolar negócio da implementação da consulta. Mas isso um Negocio já faz.

[code]NegocioHotel{

List retornarTodosOsQuartos(){

/// Consulta mais regras de negócio.
return new DAOHotel().retornarTodosOsQuartos();

}

}[/code]

Ao meu ver o benefício que vejo dos repositórios nesse caso (lembrando que ainda estou tentando entender o DDD) seria essa “facade”, tendo uma camada a mais para abstração.

Seria isso?
[/quote]

Os repositórios podem acessar DAOs convencionais, acessando um banco de dados, pode encapsular o acesso a um WEB Service, um XML, etc. Como disse, como se fosse uma coleção de objetos de um tipo, não importando de onde vem o resultado.
Além disso, para entender melhor o uso de repositórios, é importante também o conceito de Aggregates e Aggregate Roots[1]. Em DDD você tem um repositório para cada Aggregate Root. Este repositório (como unico componente da camada de negocios a enxergar a infra-estrutura) pode conter N DAOs. Os DAOs você tem em uma base de 1 DAO por classe a ser persistida(não necessáriamente…).

Fugindo um pouco do setor de hotelaria, que não conheço, um exemplo mais tradicional:

Classes Pedido e ItemPedido (clássico). O Pedido é seu Aggregate Root (a raiz do Aggregate). Você teria um RepositorioPedido. Porém, poderia ter um DAOPedido e DAOItemPedido, cada um responsável por persistir suas respectivas classes.

[1] http://en.wikipedia.org/wiki/Domain-driven_design#Building_Blocks_of_DDD

Concordo com o post anterior.

Só para reforçar, na minha opinião, DAO não é a mesma coisa que Repositorio. DAO se torna interessante quando vc precisa de acessos a vários tipos de banco de dados. Repositorios são para a manipulação dos dados (consultas e alterações), lembrando que se você utilizar DAOs os Repositorios irão depender deles para obter os dados. Regras nos Repositorios só se forem de acesso aos dados (critérios).

O titulo do tópico passa a impressão de que não se sabe exatamente onde as regras serão descritas.

Considero a resposta um pouco complicada de formular tambem.

Na minha opinião tem que analisar bem a regra para perceber onde ela “se encaixa” melhor: Ela pode ser colocada no Repositorio (critério = regra?), nas fachadas, nos serviços, em um local especifico para regras quando existem DTOs envolvidos e principalmente nas entidades. O ideal é que a decisão seja tomada pela equipe no momento de indecisão.

flws

E a diferença entre regra de negócio e regra de domínio?

[quote=Daniel_MV][quote=Giulliano][quote=magnomp]Emerson Macedo,
Eu já havia lido essa thread, foi uma discussão realmente boa

Giulliano,
Isso implica que o quarto tenha que acessar o repositório, para poder consultar as reservas. Correto?
Não há nenhum problema nisso?[/quote]

Sim…se o quarto precisar acessar qualquer informação ele pode recorrer aos repositórios que por sua vez podem recorrer a um DAO se for necessário.

; ) [/quote]

Ou seja, abusando da abstração, poderia enxergar o repositório como uma “facade” para um DAO ou outras implementações de consultas a arquivos, banco de dados, WS, etc…?[/quote]

Esse abuso esta errado. Repositório NÃO é um facade para o DAO se vc o usa assim ou o enxerga assim esta com dificuldades para entender um repositório. ESQUEÇA que um repositório tenha qualquer ligação com DAO. Se vc conseuir esquecer isso consiguirá pensar melhor. Um repositório pode trazer informações de um request, de um atributo estático, de um arquivo, da memória, a sua função é trazer as informações que eu preciso. DAO é usado para realizar o trabalho sujo, por exemplo, se precisamos ler um arquivo txt, toda a infra estrutura de abrir um File, FileReader e todo o resto fica no DAO, o repositório só precisa trazer estes dados, e se precisar mesclar estes dados com outros dados que estão em um BD, o mesmo método no repositório deve ter a inteligência de buscar essas infomaões adicionais e mesclar todas. Mas nem sempre usamos um DAO, o repositório poderia buscar informações num HttpServletRequest, que não tem nada haver com DAO.

O repositório deve trazer a informação e ter inteligẽncia e capacidade de buscar essa informação nem que seja no inferno (rs).

E para finalizar o repositório reside no DOMÍNIO da sua aplicação, enquanto que o DAO é uma classe de infra estrura.