Injeção de Dependência em Domain Model (ServiceLayer+DomainModel+Repository)

Você entendeu Fabio, é isso mesmo a duvida que tinha quando criei o tópico.

[quote=fabio.patricio][quote=Taz]

Belez…

“O pior cego é aquele que não quer ver” (ditado popular)

Abraço e boa sorte (vc vai precisar se não estudar os exemplos) :wink: [/quote]

O problema é que as duvidas dele nao sao referentes ao Sean mas sim se tem como aplicar DDD com o Sean. Ai faz sentido ter repositorios dentro dos entities (entities do DDD).

]['s[/quote]

Ok, vamos falar em DDD.

Seguem trechos do capítulo “Repositories” do Livro do Eric Evans (Domain Driven Design Complexity In Software):

Onde ele fala que são os Entitys que acessam os malditos Repositories!? Todos os diagramas que ele desenha no livro mostram os “Clients” acessando os REPOSITORIES.

[quote=Evans]Clients request objects from the REPOSITORY using query methods that select objects based on
criteria specified by the client, typically the value of certain attributes. The REPOSITORY retrieves
the requested object, encapsulating the machinery of database queries and metadata mapping.

(…)

Provide REPOSITORIES only for AGGREGATE roots
that actually need direct access. Keep the client focused on the model, delegating all
object storage and access to the REPOSITORIES.
[/quote]

Sabe o que são AGGREGATES!? Procure no mesmo livro que ele te explica.

Traduzindo: Vc não precisa criar um repositório para cada classe.

Traduzindo: Como ficaria o controle da transação se ele não fosse feito pelo cliente!?

E caso vc ainda acredite que esteja subvertendo seu modelo de domínio, o que é muito difícil quando se faz o uso correto do Hibernate…

[quote=Evans]In general, don’t fight your frameworks. Seek ways to keep the fundamentals of domain-driven
design and let go of the specifics when the framework is antagonistic. Look for affinities between
the concepts of domain-driven design and the concepts in the framework
[/quote]

Por esses e outros motivos, repito…

Capacidade de abstração, ou neste caso a falta dela, é uma coisa muito interessante. É fácil perceber quando algum trecho foi pego sem entendimento do contexto (especialmente quando o contexto é composto por 500+ páginas de texto denso) pela forma como alguém se atem à trechos que sozinhos não têm qualquer significado.

Entity é um padrão, página 89. Repository é um padrão, página 147. Aggregate também, página 125. Não existe um padrão ‘client’. por que será? Porque o cliente de algo é simplesmente o que precisa de acesso a este, no caso específico cliente pode ser um Entity. Claro que poderiam haver diagramas mostrando cada uma das possibilidades, entity x repository, service x repository, specification x xrepository… só que haveriam algumas dezenas de páginas a mais a toa.

O texto não traz uma definição de ‘cliente’, talvez porque… uhm… seja bem obvio quando se tenta… uhm… ler o dito cujo. Por exemplo quando factories são definidas temos:

ou seja: o cliente pode ser Camada de Aplicação, mas não necessariamente.

Mas para entender mais profundamente o texto de Evans (coisa que só é necessária quando você está estudando DDD em um nível mais profundo ou quando precisa refutar uma desinformação, que é o caso) é necessário pesquisar no seu antecessor, amplamente referenciado por este: Fowler no seu POEAA. E uma das coisas mais legais do Fowler é que ele consegue responder este tipo de dúvida com um exemplo claro, como este retirado do livro (pagina 325, no capítulo sobre Repository):

public class Person { 
   public List dependents() {
      Repository repository = Registry.personRepository();
      Criteria criteria = new Criteria();
      criteria.equal(Person.BENEFACTOR, this);
      return repository.matching(criteria);
   }
}

Veja que curioso: uma entidade referenciando a seu próprio Repositório. Onde mesmo que havia visto isso? E veja só, ainda usa Registry.

Uma coisa que vem ficando cada vez mais frequente no GUJ é certos usuários acharem que só eles leram os livros/artigos/papers/coloque aqui sua fonte preferida. Essa resposta do Taz fazendo como se ele fosse o unico e ter lido esse livro me fez procurar o e-mail da primeira vez que eu ouvi falar dessa obra do Evans. Quem me falou disso a primeira vez foi o Marcos Pereira (usuario aqui do GUJ tb) la em 2004 acredito que pouco tempo depois do livro ter sido lancado.

Ps.: Desculpem o desabafo, mas esse tipo de coisa no GUJ vem se tornando frequente e enche um pouco o saco.

]['s

Eu tenho quase certeza que a pimeira referência que vi foi aqui no GUJ pelo cv (e vindod e quem vem não estranharia se fosse a primeira vez que isso apareceu num site em português :P). Infelizmente o grande apagamento dos posts de uns dois anos atrás levou a mensagem para o limbo.

Não deveria haver motivos para mágoas. Eu não disse que só eu havia lido… :wink:

Quanto ao outro rapaz, percebo certa rispidez em sua réplica, o que já é um comportamento histórico que pode ser ocasionado por uma certa insegurança… Por outro lado, o mesmo reclama de lidar com pessoas que não se atêm à bibliografias. Quando encontra alguém que lê, deveria ter uma postura mais aberta…

Uma pena que ele não percebe que o Hibernate converte aquilo que ele escreveu:

public class Person { public List dependents() { Repository repository = Registry.personRepository(); Criteria criteria = new Criteria(); criteria.equal(Person.BENEFACTOR, this); return repository.matching(criteria); } }

por isso (obviamente em um contexto “managed”)…

public class Person { public List getDependents() { return dependents; } }

Ou seja, o Hibernate contém o próprio Repositorio em si…

Lembrem-se:

[quote=Evans]In general, don’t fight your frameworks. Seek ways to keep the fundamentals of domain-driven
design and let go of the specifics when the framework is antagonistic. Look for affinities between
the concepts of domain-driven design and the concepts in the framework[/quote]

Após aquele post todo cheio de referências e autoridade completamente furado (e pedir ‘abertura’ para engolir sua presunção) colar um trecho de um livro que já mostrou que não entende (ou será ‘leu’?) é muita cara de pau.

Quem quiser entender melhor sobre Hibernate & Repositories é legal olhar a lista de DDD, o que a pessoa escreveu aí em cima (pra variar) não condiz com a realidade da técnica. O trecho que ele postou substitui Registry por algum meio automático (talvez IoC) de injeção, mas a tecnologia utilizada não tem nada a ver com a aplicação ou não do padrão. Repositories podem ser criados para lidar diretamente com Hibernate, JDBC, search engines ou não, provavelmente delegando seu trabalho à DAOs e DataMappers em geral. Mas nem adianta tentar refutar com argumentos ou até mesmo referências bibliográficas, como se pôde perceber. O bichinho não anda, simples assim.

O outro rapaz aqui (que você já chamou de desonesto neste fórum só por birra) não precisa ter insegurança, pelo menos não quanto à você. Seu histórico aqui já o condena (inclusive profissionalmente, mas tudo bem, você não revela seu nome exatamente para não te reconhecerem, certo?), isso sem contar o portal Java…

Apenas respondendo a sua pergunta Taz, sim eu conheço o que é Aggregate, assim como tbm sei que Repository não é um para cada classe. Agora o que não sei mesmo é o que isso tem haver com o que tenho postado ou oq já rolou neste tópico.

Alguma vez afirmei que iria construir repositorios a torto direito para cada entidade minha?

E que porcaria que você andou digitando sobre “Clients”?

Quanto aos “clients”, apenas completando o que Shoes já disse… vale comentar tbm que além de usar uma entidade (People), no livro de Fowler (POEAA) ele tbm usa duas classes “Strategy” com um Repository, o que nos mostra a flexibilidade do padrão.

Mas é claro, não espero que Taz concorde com estas afirmações… Já discordou de mim, do Fabio Kung, do Sergio, do Phillip, do fabio.patricio, não duvido que ele discorde de Fowler tbm…

Só é bom focarmos que discordar é ótimo. Eu discordo do Fowler bastante em DSLs, por exemplo. O ponto é ter um mínimo de respeito pelos outros e darmos base às nossas discordâncias, seja usando uma bibliografia ou argumentando. Pela minha experiência muitas discordâncias contra conceitos são na verdade falta de entendimento (desconfio que meu ponto de divergência com a coisa das DSLs seja exatamente porque ainda não as compreendo bem) e uma conversa e/ou debate ético e profissional são proveitosos para todos.

O que não dá é atirar pedra em todo mundo sem sequer entender o que fala.

O problema Phillip é quando o “discordar” parece ser mais importante do que “compreender”. Só depois de compreender um problema podemos “discordar” de alguma solução para tal, o que não ocorreu por aqui.

PS: Você não apóia o uso de DSLs ? Eu particularmente detestava, até conhecer o Drools e como fazer regras de segurança com ele (o ruim não eram as DSLs e sim como cria-las , IMHO).

[quote=Lezinho]
PS: Você não apóia o uso de DSLs ? Eu particularmente detestava, até conhecer o Drools e como fazer regras de segurança com ele (o ruim não eram as DSLs e sim como cria-las , IMHO).[/quote]

Sim, apóio e minha linha de estudo atual é exatamente sobre os conceitos envolvidos em LOP e DSLs: http://fragmental.tw

Eu discordo de alguns conceitos do Fowler, por exemplo o conceito dele de LOP==DSL

Ataques pessoais!? Lamentável um moderador adotar essa postura.

Magina, acho que vc havia cometido um engano ao falar que havia bloqueado meus e-mails, apesar de nunca ter te enviado qualquer coisa. Não precisa forçar neh!?

Quanto à discussão, cada um faz suas escolhas e assume as consequências.

Assunto encerrado.

Só uma dúvida Lezinho…

Estou usando Seam e EJB 3 e não tenho tido a necessidade de injetar Repositories nos Entities e sim alguns Services. (tenho um exemplo para aplicação Desktop em http://www.aspercom.com.br/bitshop). Como são poucos casos, criei um Factoryzinho para injetar isso (se fosse muitos recorreria a AOP como vc fez).

Quais situações você está sentindo a necessidade de injetar repositories? Seria para navegar numa associação derivada? Ou para “simular” uma associação n-aria?

Abraços!

Olá Rodrigo …

O repositório na entidade deve executar métodos de negócio a fim de recuperar elementos relevantes ao comportamento desta Entity, não precisa necessariamente ter uma ordem de relacionamento com a entidade.

Agora uma Service, é um padrão que encapsula seu Domain MOdel. Ele antecede as Entidades e controla o fluxo das execuções. O comportamento da entidade (seus métodos de negócio) possui lógica, um service apenas opera como uma fachada. Sendo assim, uma entidade não deve invocar um service, e sim ser invocada por um.

Para você visualizar o modelo de camadas proposto por Fowler e descrito no POEEA, veja uma breve descrição e um diagrama que aponta isso aqui:

http://martinfowler.com/eaaCatalog/serviceLayer.html

PS: Veja que “DataSource Layer”, que deve ser abstraída pelo Repository, esta encapsulada no Domain.

[]´s

Veja,

Digamos que tenho repositórios de entidades diferentes (PessoaRepository e ContaRepository, por exemplo). Aih desejo que um mesmo DAO genérico implemente esses repositórios ( ao menos nos métodos que equivalem a operações CRUD ).

Que estratégia devo tomar para conseguir isso? Dá pra usar interfaces e spring? Devo usar fachada? Como se daria isso?

[quote=rodrigoy]Só uma dúvida Lezinho…

Estou usando Seam e EJB 3 e não tenho tido a necessidade de injetar Repositories nos Entities e sim alguns Services. (tenho um exemplo para aplicação Desktop em http://www.aspercom.com.br/bitshop). Como são poucos casos, criei um Factoryzinho para injetar isso (se fosse muitos recorreria a AOP como vc fez).

Quais situações você está sentindo a necessidade de injetar repositories? Seria para navegar numa associação derivada? Ou para “simular” uma associação n-aria?

Abraços!

[/quote]

Essa história de Repositories tá confundindo a cabeça do pessoal… :wink:

É verdade. No meu caso, como estou acostumado a utilizar um DAO genérico com hibernate e somente criar DAO’s específicos quando desejo uma consulta mais específica, estou pensando como se daria para as interfaces de Repositório do DomainModel serem implementadas pelo DAO genérico (ao menos nas funcionalidades que equivalem a CRUD) e só serem implementadas por DAO’s específicos em caso de consultas específicas.

Como poderia fazer isso?

Herança?

[code]Repository
public void store(Object obj){
dao.save(obj);
}

ContaRepository extends Repository
PessoRepository extends Repository[/code]

Beleza, e como faço para desacoplar o repositório da implementação com DAO’s?

A estratégia que eu uso é realmente utilizar Strategy :wink:

Eu tenho uma interface DAO expondo métodos como do tipo (exemplificando):

  • read(String stringQuery);
  • read(String stringQuery, Object[] params);
  • read(String stringQuery, Map<String, Object> params);
  • getAll(Class clazz);
  • getById(Object id);
  • save(Object obj);
  • delete(Object obj);
    (etc)

A implementação do DAO faz uso de JPA, Hibernate, Prevayler, ou seja lá o que for …

Tenho interfaces Repositories do tipo (RepositoryUser):

  • findUserByNameAndPassword(String name, String password);
  • addUsersWithValidRegisters(List<User> users);
    (etc)

A implementação do repositório possui como atributo minha interface DAO definida anteriormente, e utilizo D.I.P. (no momento Seam) da implementação DAO desejada.

Quando o repositório precisa realizar acesso ao framework de persistencia (ou outro recurso de persistencia) ele faz o uso do seu Dao injetado como Strategy.

Assim o DAO continua com seu encapsulamento de acesso a dados, o repositório continua com a lógica, e a leitura do programa fica coesa.