Hibernate e Domain-Driven Design

[quote=Luca]Olá

Só para citar uma outra opinião:

http://www.adam-bien.com/roller/page/abien?entry=jpa_ejb3_killed_the_dao

http://www.adam-bien.com/roller/page/abien?entry=to_layer_or_not_to

https://p4j5.dev.java.net/

Quero deixar claro que não é sempre que concordo com Adam Bien mas taí a opinião dele.

[]s
Luca[/quote]

hehehe,

na realidade ele corrobora o que eu disse… ele também usa Facades (Sessions), e ainda quer colocar o código dos DAOs dentro deles (Facades).

Embora os padrões existão vc não é obrigado a usá-los
Existem muitos padrões e muitos deles, ou viraram anti-patterns (DTO por exemplo) ou nunca foram realmente
utilizados (EJB EntityBeans) o que levou à criação de novos padrões (JPA, Dependency Container) que resolvem os problemas os anteriores

Quais frameworks/camadas vc usa nos seus projetos?

Sérgio,

Agora entendi pq Facades (Session Beans) e Repositories são conceitos bem parecidos. O pessoal do Spring simplesmente chama de Repositories o que EJB3 chama de Session Beans.

http://www.parleys.com/display/PARLEYS/Writing+JPA+applications?showComments=true

Tá vendo como padrões podem ajudar, até na comunicação.

Acho que vc exagerou quando disse: “Como todos os padrões eles estão ai para não serem usados”

Imagine que ZONA seria se não existissem padrões de codificação, por exemplo.

Quando vc fala que padrões não servem para nada, vc está falando que todos os profissionais que participam do JCP e de times que implementam suas especificações em empresas como Red Hat, BEA, IBM e Oracle, etc, etc fazem um trabalho inútil e em vão!!! E isso, absolutamente, não é verdade…

Hei! Eu nunca disse que eles não servem para nada. O que eu disse é que nem todos eles são usados. As pessoas não se sentem bem/gostam de usar certo padrão. Isso leva a que essas pessoas criem outros padrões, que por resolverem os problemas encontrados nos originais são mais aceites. Mas este ciclo é viciado e sempre existirá um padrão mais evoluido. Sobretudo quando se trata de padrões da industria (EJB,PJA, Hibernate)e não padrões teoricos (Singleton, Factory, etc).

Eu não uso hibernate se quer saber.

Mas o que eu uso ou deixo de usar não tem nada a ver com o assunto.

Na boa, acho que tem a ver. Se vc ciritca Hibernate e padrões, deve usar/defender algo melhor. Apresente sua sugestão…

[quote=Taz][quote=sergiotaborda]

Mas o que eu uso ou deixo de usar não tem nada a ver com o assunto.

[/quote]

Na boa, acho que tem a ver. Se vc ciritca Hibernate e padrões, deve usar/defender algo melhor. Apresente sua sugestão…[/quote]

Parece que ha algum mal entendido aqui. Eu não critico o hibernate nem os padrões. O hibernate é uma otima ferramenta para aquilo que se propõe resolver.

A questão é que no contexto do DDD usar annotations é violar a separação de responsabilidade.
No caso de usar annotations vc está implicitamente violando as fronteiras da camada de dominio e da de persistencia. A menos que vc coloque ambos na mesma camada isso é errado.
Então vc pode :

  1. Colocar dominio e persistencia no mesmo saco, anota as classes do dominio com annotations do hibernate/JPA
    usar o Repositorio como mapeador ou
  2. Criar um DAO generico que usa para acessar os dados e o Repositorio para orquestrar a conversa entre o dominio e o DAO. Generico significa que não obriga os objetos que lhe são passados a implementar nenhum contrato extra. Configure o seu DAO de forma independente do dominio. Por exemplo, tamahos de campos da tabela, indices, etc… Se vc puder realizar esta tarefa com hiberante/JPA maravilha, mas não obrigue o seu dominio a se submeter às regras das ferramentas.

o modelo é mais o menos assim

Applicação --usa regras do–> Dominio – que procura entidades usando -> Repositorio --que procura/guarda dados usando–> DAO

DAO --intrepreta comandos para linguagem SQL–> Banco
ou
DAO --intrepreta comandos para linguagem XQuery–> XML
ou
DAO --intrepreta comandos invocação remota --> HttP/RMI/Delegação --> (Servidor) --> DAO (outra implementação)
DAO --intrepreta comandos localmente e lê um cache em memoria

Além de usar o DAO o Repositorio é quem mapeia de/e para objetos conforme as regras do dominio.

OK. Seria isso?

Cliente->Pojos (Domínio)->Repositorio->DAO!?

Parece um Active Record, não!?

[quote=Taz][quote=sergiotaborda]

o modelo é mais o menos assim

Applicação --usa regras do–> Dominio – que procura entidades usando -> Repositorio --que procura/guarda dados usando–> DAO

[/quote]

OK. Seria isso?

Cliente->Pojos (Domínio)->Repositorio->DAO!?
[/quote]

Não. Porque o Dominio são mais coisas que apenas os Entity. São tb os serviços, por exemplo.
Portanto, não são apenas os Entity que usam o repositorio para encontrar Entitites.

Não.

Como não!? Foi o que vc escreveu não foi!?

Outra…

Ops, se os Entity usam repositórios ou DAOs ou seja lá o que for para buscar dados, estamos falando de Active Records.

Antes de responder deixe-me perguntar: o objetivo desta conversa … qual é ?

  1. Não confunda DAO com Repository. Achei que neste ponto estaria clara a diferença.
  2. Persistir significa carregar os dados de/guardar dados em meio não volátil. Encontrar/buscar/Procurar não tem nada a ver com persistir.
  3. ActiveRecord é um padrão em que os objetos se persistem a si mesmos, i.e. sem usar DAO nem nenhum outro padrão de dados. A logica de persistencia (load/save) está toda no próprio objeto. Donde, um objeto que não se persista a si mesmo não é um ActiveRecord. Como Entity não se persiste sozinho nem persiste nenhum outro objeto , ele não pode ser um ActiveRecord c.q.d.

Não sei de onde nasceu essa necessidade de inclui o ActiveRecorda na conversa, mas como já disse - e já me estou a repetir muitas vezes - ActiveRecord não é compativel com DDD. Sendo que o topico é sobre DDD esqueça ActiveRecord. Aliás, esqueça que este padrão existe. É uma atrapalhação no caso geral, sua utilidade é muito restricta.

Para deixar bem clara diferença:

// ActiveRecord
public class A {

 // get/set

 public void save(){ // codigo que persiste this}

 public void load() { // codigo que recupera this}

}


// DDD

public class B {

   // get/set 

}

public class BRepository {


public void store(B b){
    // codigo que coloca B disponivel a ser encontrado no metodo find
}

public B find (Object parametro ){
     // codigo que encontra um objeto da classe B com base no parametro
}

}

Se mesmo assim , vc acha que ActiveRecord e DAO são compativeis ou tem sequer algo a ver… tente implementar. rápidamente vc vai ver que 1) ou está duplicando codigo 2) ou está criando codigo redundante
e espero que chegue na conclusão que ao usar ActiveRecord não poderá usar DAO e vice-versa.

Seu exemplo é bastante rudimentar e omite o principal. Quem chama os métodos do Repository!?

De acordo com o campo “Assunto:” aí em cima é discutir a melhor implementação Hibernate + Domain-Driven Design.

Vc acha que tem que usar Repositories/DAOs, etc, de dentro de seus Entitys (e isso é ACTIVE RECORD!!!). Eu não acho isso. Prefiro fazer os acessos dos Services (no caso Session Beans) e uso diretamente DAOs pq só tenho dados em BD e é só de persistência em BD que eu preciso. OK?

Desisto. Vc já perdeu o fio da meada e parece bastante perdido.

Os Serviços e outros objetos do dominio. Já falei isso antes:
" Applicação --usa regras do–> Dominio – que procura entidades usando -> Repositorio --que procura/guarda dados usando–> DAO "
"Porque o Dominio são mais coisas que apenas os Entity. São tb os serviços, por exemplo. "

O seu problema é que está achando que repository é um façade implementado com EJB stateless.
Isso não é um Repository, é um Service.

Eu já expliquei 3 vezes. Tlv antes de continuar vc devesse ler o livro que vagueia ai pela internet sobre DDD
http://www.infoq.com/news/2006/12/domain-driven-design.Ao menos para não continuar chamando os Entity de ActiveRecord. Já expliquei porque os Entity não são AtiveRecord, mas vou-lhe dar mais um motivo: se entity fosse AtiveRecord para o quê seria necessário o Repository ? (pergunta retórica)

Eu não acho que tem que usar Repository/DAO dentro do Entity. Quem acha isso é o cara que inventou o DDD.
O que eu acho que é que deve existir um DAO e um Repository e não apenas um deles. (Nisso o Evans , nem ninguem do DDD é claro). E nesta prespectiva nenhum dos dois deve usar Hibernate/JPA con annotations. Como implementa DDD com Hibernate ? Não implementa. Ou menos não sem violar o principio de separação de responsabilidade. Mas como eu já disse, se implementou meia boca, funciona e está feliz, esqueça o que eu digo.
Vc prefere usar SessionBeans e DAO , otimo, mas isso não é DDD. Ok?

Eu estou perdido porque estou explicando N vezes a mesma coisa e vc não ainda entendeu e eu não sei porquê vc não entendeu.

[/quote]

Se vc se propõe a postar num tópico sobre DDD + Hibernate e a criticar uma solução que nem conhece, deveria pelo menos usar. :wink:

[quote=Taz][quote=sergiotaborda]

Eu não uso hibernate se quer saber.

[/quote]

Se vc se propõe a postar num tópico sobre DDD + Hibernate e a criticar uma solução que nem conhece, deveria pelo menos usar. :wink: [/quote]

Eu poderia entender essa frase como um argumento ad hominem, mas não vou.
Eu não o uso exatamente porque o conheço. Para mim, para aquilo que eu faço ele é limitativo.
Cada caso é um caso, e no meu caso, ele é mais um problema que uma solução.

Eu postei neste tópico relativamente ao DDD porque vários post apresentavam os conceitos de DDD de forma errada, incompleta ou ambígua. Eu só tentei esclarecer esses pontos, com o meu ponto de vista e baseado no que li de DDD por ai.

Não estou criticando nenhuma tecnologia, apenas as escolhas que foram apontadas e a coerência (ou não) dessas escolhas com princípios e padrões básicos.

No fim, quem decide é quem vai implementar.

Não está havendo uma confusão sobre a palavra “Entity”?

Realmente em DDD, entity não é um ActiveRecord… é um objeto com ID(uma identidade unica), diferente de um VO(vo do DDD) que não tem ID e só o valor interessa

Por outro lado, na spec ejb 2.1 o EntityBean é um ActiveRecord…

[quote=felipec]Não está havendo uma confusão sobre a palavra “Entity”?

Realmente em DDD, entity não é um ActiveRecord… é um objeto com ID(uma identidade unica), diferente de um VO(vo do DDD) que não tem ID e só o valor interessa [/quote]

Talvez sim. O pessoal confunde as terminologias e não sabe enxergar que “meia dúzia é 6”.

A vida é simples. Veja:

Teminologia do Eric Evans (DDD):

Cliente (delega) -> Service
Service (busca objetos) -> Repository
Service (manipula) -> Aggregates de Entities

Terminologia Java EE/JPA/Hibernate:

Cliente (delega) -> Facade (Session)
Facade (busca objetos) -> DAO
Facade (manipula) -> Pojos que contêm outros Pojos (que a JPA também chama de Entities)

[quote=felipec]
Por outro lado, na spec ejb 2.1 o EntityBean é um ActiveRecord…[/quote]

Não, não é. Ele é instanciado pelo Home.

[quote=Taz]

pela definição do fowler é sim…

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

Se foi isso o que vc entendeu, deve ser mesmo… :wink:

Bom… depois de muitas discussões, caimos novamente na
http://guj.com.br/posts/list/60/60916.java

Acho que o foco aqui deu uma escapada…
A discussão central aqui Hibernate e DDD, foi justamente para saber se devo ou não isolar o hibernate do meu Domínio (Não gosto de usar termos como VOs, BOs).
Se devo isolar o hibernate (que na minha opinião é o mais sensato de se fazer) como isolar?

Pelo que percebi, já que o hibernate “carrega” tudo sozinho, todas as minhas relações entre classes no domínio são controladas por ele. Logo para eu utilizá-lo e ao mesmo tempo não depender dele, sou obrigado a fazer um certo mix de funções como eu citei logo no começo da discussão.

class Cliente 
{ 
	/*...Inicializações, variáveis, etc...*/ 


	private List<Endereco> enderecos; 

	public List<Endereco> obterEnderecos() 
	{ 
		if (enderecos == null)  
		enderecos = EnderecoRepositorio.getEnderecosCliente(this); 

		return enderecos; 
	} 

} 

Se focando no Hibernate e no DDD eu pergunto.

Este seria o melhor jeito de isolá-lo?
Já que faz-se a pergunta - se meus endereços não foram carregados pelo hibernete, carregue-os.

Sei sim esta é uma das idéias do Active Record, (que ao mesmo tempo em que temo o método save dentro do objeto do domínio, temos também que aparentemente todas as relações estão sendo “automaticamente” persistidas.) e não gosto muito deste padrão, mas seria esta forma uma das mais sensatas?

Até agora vocês não conseguiram me passar uma forma que eu achasse mais viável que esta.

Gostaria de saber, se possível com algum exemplo simples, como vocês fazem o isolamento.

Abraço pessoal!