| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 14:03:13
|
brunohansen
JavaEvangelist
![[Avatar]](/images/avatar/1e0feeaff84a19bf3936e693311fa66d.jpg)
Membro desde: 27/03/2006 11:11:34
Mensagens: 391
Offline
|
Lezinho wrote:Pense da seguinte forma, Fornecedores não se salvam nem se deletam.
Isso não seria um pouco controverso?
Seguindo o Padrão GRASP Especialista na Informação, poderiamos dizer que: Quem tem os dados deve ser responsável por manipula-los. Com isso, conseguimos um boa divisão de responsábilidades, conseguimos fornecer um bom encapsulamento, evitamos inveja dos dados enfim, conseguimos evitar modelos anêmicos.
Muitas vezes olhando para o Especialista da Informação fiz reflexões parecidas com esta: O objeto Fornecedor conhece seus dados logo seria responsabilidade dele se salvar, assim manteriamos o encapsulamento etc.. etc...
Mas como persistência é um problema de infra vamos voltar lá no mundo de bobject...
reflexões...
|
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 14:19:48
|
bonfarj
Java Ninja
![[Avatar]](/images/avatar/1454ca2270599546dfcd2a3700e4d2f1.jpg)
Membro desde: 28/03/2006 09:55:47
Mensagens: 298
Offline
|
brunohansen wrote:
Lezinho wrote:Pense da seguinte forma, Fornecedores não se salvam nem se deletam.
Isso não seria um pouco controverso?
Seguindo o Padrão GRASP Especialista na Informação, poderiamos dizer que: Quem tem os dados deve ser responsável por manipula-los. Com isso, conseguimos um boa divisão de responsábilidades, conseguimos fornecer um bom encapsulamento, evitamos inveja dos dados enfim, conseguimos evitar modelos anêmicos.
Muitas vezes olhando para o Especialista da Informação fiz reflexões parecidas com esta: O objeto Fornecedor conhece seus dados logo seria responsabilidade dele se salvar, assim manteriamos o encapsulamento etc.. etc...
Mas como persistência é um problema de infra vamos voltar lá no mundo de bobject...
reflexões...
É, Bruno, controverso. Eu entendo os dois lados, não é fácil decidir. Neste momento, eu vejo mais benefícios em fazer com que a classe Fornecedor saiba como salvar e recuperar seus objetos. Com AspectJ eu vi uma forma bem legal de fazer isso, o código na classe Fornecedor não seria alterado, ela apenas herdaria uma interface.
Como o Bruno falou, reflexões...
|
IGOR BRITO ALVES
@igoralves
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 14:47:39
|
Alessandro Lazarotti
Virtual Machine Man
![[Avatar]](/images/avatar/2aaaddf27344ee54058548dc081c6541.jpg)
Membro desde: 21/01/2004 14:12:54
Mensagens: 718
Offline
|
Se trabalhar com Domain Model não é pré-requisito para a modelagem, tbm não vejo problema em utilizar Active Record.
Ë puramente uma questão de escolha de design.
|
... Lezinho
------------------------
twitter: @lazarotti
http://alessandrolazarotti.wordpress.com/
http://jbossbrasil.org/
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 14:58:06
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3420
Offline
|
brunohansen wrote:
Lezinho wrote:Pense da seguinte forma, Fornecedores não se salvam nem se deletam.
Isso não seria um pouco controverso?
Seguindo o Padrão GRASP Especialista na Informação, poderiamos dizer que: Quem tem os dados deve ser responsável por manipula-los. Com isso, conseguimos um boa divisão de responsábilidades, conseguimos fornecer um bom encapsulamento, evitamos inveja dos dados enfim, conseguimos evitar modelos anêmicos.
Muitas vezes olhando para o Especialista da Informação fiz reflexões parecidas com esta: O objeto Fornecedor conhece seus dados logo seria responsabilidade dele se salvar, assim manteriamos o encapsulamento etc.. etc...
Isso é uma falácia.
O fornecedor realmente tem conhece os seus dados, mas não conhece a localização da persistência. Entenda que essa localização pode mudar e ver variada. Se o fornecedor conhecer essa localização ele está puxando para si uma responsabilidade que não lhe cabe. Não é que o forncedor não se possa persistir, é que ele não sabe onde.
Compara com Serializable. Vc pode implementar no objecto um write e um read para substituir a seriaização padrão. Aqui o objeto está chamando para si a responsabilidade de quais dados e em que ordem os vai serializar, mas o processo não é da responsabilidade dele, o Objectstream que sabe a localização e o algoritmo para a serialização.
No caso do fornecedor ele não tem meios de sobreecrever as operações crud, mas tb não precisa, já que tudo é feito pelo sistema de persistência.
Então sim, existem uma forte necessidade de separar a persistencia da entidade porque ela não detalhes da persistencia e como tal não pode ter essa responsabilidade.
O encapsulamento não tem nada a ver com o problema já que tanto em entidade.save() como em algo.save(entidade) ninguem está vendo como o save acontece realmente.
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 15:03:14
|
fabim
GUJ Master
![[Avatar]](/images/avatar/d4e3e8180a65648886ff348c7a6bbff5.jpg)
Membro desde: 14/12/2006 19:30:03
Mensagens: 1234
Localização: Vitoria - Espirito Santo
Offline
|
sergiotaborda wrote:
bonfarj wrote:
sergiotaborda wrote:Não. Em O não ha "relacionamentos", ha objetos contendo objetos. Isso é um grafo.
(...)
2) A relação entre cliente e pedido não forma um grafo fixo.
Eu realmente fiquei confuso com essa concepção de grafo, não entendi. Imagine que uma classe Pedido possui um atributo Cliente. Isso não pode ser visto como um relacionamento entre as duas classes? Seguindo o que você falou, Cliente pertence ou não ao grafo de Pedido? Se você tiver um link falando sobre grafos nesse contexto eu gostaria de ver, não consegui entender bem.
Pedido contém um atributo do tipo Cliente. Sim. Cliente pertence ao grafo de Pedido e eu faço pedido.getCliente().
O cliente do pedido reponde a "Quem fez o pedido?"
Mas se eu quiser responder a "Quais pedidos o cliente fez?" ai eu uso cliente.getPedidos().
Com estas duas coias eu posso responder a "Que pedidos o cliente que fez este pedido, fex?" apenas com pedido.getCliente().getPedidos().
Isto é uma regra de dominio.
O facto de pedido ter um atributo ter um cliente sim pode ser encarado como um relacionamento entre as duas entidades, mas esse relacionamento é "virtual" ou seja, não existe um objeto Relacionamento que tenha um referencia a cada um. (Poderia haver, mas normalmente não ha). O que ha é uma Referencia de pedido a cliente , mas não de cliente a pedidos. Quando executa Cliente.getpedidos() vc está executando uma regra de negocio que é muito mais complexa que pedido.getCliente(). cliente.getPedido() implica num raciocinio "procura os pedidos onde o cliente é this"
Em codigo :
Embora do lado de fora pareça que Set<Pedidos> existe dentro de cliente, ele não existe de fato. Isso é a vantagem de encasulação.
O que tudo isto interessa?
Quando vc salva o pedido , ha um campo na tabela Pedido que diz respeito ao cliente. Logo o sistema tem que averiguar se o cliente está tb salvo. Se não, salva-o ( ou salva-o logo por default e pronto)
Mas quando o sistema salva o cliente ele não salva a coleção de pedidos. Porque ele não salava? porque não ha nenhum atributo desse tipo em cliente.
Então getPedidos() parece igual a getCliente(), mas não são. Mas o objetivo do DDD é exatamente que pareçam, mesmo que internamente não sejam.
Agora que eu não entendi mesmo. Necessidade de andar com uma lista? Mas isso não está relacionado a forma como você implementa? Também não entendi o porquê de Cliente não conter uma coleção de pedidos, porque o que você descreveu, para mim, indica claramente que existe um relacionamento bidirecional entre as duas classes.
!
Se o cliente contivesse um lista de pedidos cada vez que vc salva o cliente salvaria os pedidos e cada vez que retorna um cliente, retorna todos os pedidos tb. Entenda que isso cria um cliclo vicioso. Salvar o pedido salva o cliente que salva o pedido, que salva o cliente ... Claro que a sua ferramente de persistencia pode evitar isso, mas o ponto aqui é que Pedido não pertence ao grafo de cliente. Pedido não especifica o cliente. Mas cliente especifica o pedido. Essa é a diferença.
E não, ninguém anda com uma lista. Sim, depende de como implementa. Mas se vc implementar diferente vai ter muita dor de cabeça por causa do paradoxo que falei antes.
Em termos de banco de modelo E-R existe um relacionamento bidirecional, mas em termos de DDD e OO não. Isso porque não é a mesma coisa vc obter pedidos a partir de um cliente e o cliente ter uma referencia a esses pedidos. E em OO o que conta são as referencias e não os relacionamentos.
Pense assim : vc poderia executar PedidosRepository.findByCliente(Cliente c) sempre que precisasse em qq ponto da aplicação. Mas isso é uma falha de encasulamento. Isso é equivalente a usar o objeto cliente como um DTO e isso é contra a ideia do DDD. É mais claro , e simples , que seja cliente.getPedidos().
Espero ter esclarecido.
Uau. Excelente explicação Sérgio.
Com código ainda que facilita bastante o entendimento.
|
ειπεν αυτη ο ιησους εγω ειμι η αναστασις και η ζωη ο πιστευων εις εμε καν αποθανη ζησεται
Sun Certified Web Component Developer
Sun Certified Java Programmer
Sun Certified Java Associate
Sun Certified Business Component Developer - Em Andamento
Bacharelando em Sistemas de Informacao
 |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 15:08:22
|
bonfarj
Java Ninja
![[Avatar]](/images/avatar/1454ca2270599546dfcd2a3700e4d2f1.jpg)
Membro desde: 28/03/2006 09:55:47
Mensagens: 298
Offline
|
sergiotaborda wrote:Isso é uma falácia.
O fornecedor realmente tem conhece os seus dados, mas não conhece a localização da persistência. Entenda que essa localização pode mudar e ver variada. Se o fornecedor conhecer essa localização ele está puxando para si uma responsabilidade que não lhe cabe.
Concordo plenamente, sem ressalvas.
sergiotaborda wrote:Não é que o forncedor não se possa persistir, é que ele não sabe onde.
E se fizermos isso com DI? A classe Fornecedor continua sem saber como persistir, isso seria injetado nela. Isso é uma boa solução?
|
IGOR BRITO ALVES
@igoralves
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 15:48:40
|
Alessandro Lazarotti
Virtual Machine Man
![[Avatar]](/images/avatar/2aaaddf27344ee54058548dc081c6541.jpg)
Membro desde: 21/01/2004 14:12:54
Mensagens: 718
Offline
|
Domain Model com Entidades contendo save, persist, ... ?
Se você acredita que estas assinaturas de métodos faz sentido estar nas entidades, sua equipe e Expert Domain concordarem com você, tudo bem.
Eu simplemente acho que um EntidadeRepository.add(entidade) resolve o problema, sem ter que comprometer a modelagem da Entidade a.k.a. ActiveRecord desnecessário.
Isso não é falácia, é ponto de vista.
|
... Lezinho
------------------------
twitter: @lazarotti
http://alessandrolazarotti.wordpress.com/
http://jbossbrasil.org/
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 16:45:44
|
Rodrigo Carvalho Auler
Virtual Machine Man
Membro desde: 14/02/2003 15:59:17
Mensagens: 576
Localização: Rio de Janeiro
Offline
|
Lezinho wrote:Eu simplemente acho que um EntidadeRepository.add(entidade) resolve o problema, sem ter que comprometer a modelagem da Entidade a.k.a. ActiveRecord desnecessário.
Uma pergunta: nesse caso, como vc faz a validação dos dados do objeto?
Cria um método entidade.validar() e chama dentro do EntidadeRepository.add(entidade)?
[]'s
Rodrigo C. A.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 16:45:49
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3420
Offline
|
bonfarj wrote:
sergiotaborda wrote:Não é que o forncedor não se possa persistir, é que ele não sabe onde.
E se fizermos isso com DI? A classe Fornecedor continua sem saber como persistir, isso seria injetado nela. Isso é uma boa solução?
Se vc usar injeção de dependência vc continua tendo dependência. Apenas não é vc que seta as referencias dos objetos manualmente. Não muda nada em termos de responsabilidade.
Se vc injetar um objeto que tenha essa responsabilidade de saber onde persistir vc estará implicitamente retirando essa responsabilidade de Fornecedor. Ai fica pior, a responsabilidade é de outro objeto mas vc está forçando o uso atravéz de Fornecedor como um façade. Ou seja se vc tiver
Vc está usando Fornecedor como um Façade para DAO só porque vc gostaria de escrever:
Porque não fazer logo:
Em vez de complicar a vida com ActiveRecord ?
Eu concordo com a afirmação do Lezinho:
Lezinho wrote:
Eu simplemente acho que um EntidadeRepository.add(entidade) resolve o problema, sem ter que comprometer a modelagem da Entidade a.k.a. ActiveRecord desnecessário.
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 16:58:30
|
brunohansen
JavaEvangelist
![[Avatar]](/images/avatar/1e0feeaff84a19bf3936e693311fa66d.jpg)
Membro desde: 27/03/2006 11:11:34
Mensagens: 391
Offline
|
sergiotaborda wrote:
Isso é uma falácia.
Rs... Engraçada essa afirmação!
Você esta dizendo que um padrão GRASP é uma falácia?
Eu discordo. Acho que os padrões de responsábilidades GRASP nos ajudam a aplicar a base da orientação a objeto, ainda mais se tratando do especialista da informação que é o mais importante.
sergiotaborda wrote:
O fornecedor realmente tem conhece os seus dados, mas não conhece a localização da persistência. Entenda que essa localização pode mudar e ver variada. Se o fornecedor conhecer essa localização ele está puxando para si uma responsabilidade que não lhe cabe. Não é que o forncedor não se possa persistir, é que ele não sabe onde.
Ele não precisa saber onde se persitir... é só criar uma indireção e utilizar injeção de dependencia...
sergiotaborda wrote:
O encapsulamento não tem nada a ver com o problema já que tanto em entidade.save() como em algo.save(entidade) ninguem está vendo como o save acontece realmente.
Acho que você esta enganado. Há uma quebra de encapsulamento! Sorte que a quebra é feita com reflexão ou aspectos... Senão teriamos que fazer fazer manutenção com espingarda!
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 18:33:58
|
cmoscoso
Virtual Machine Man
Membro desde: 23/10/2007 10:08:29
Mensagens: 687
Offline
|
brunohansen wrote:
Seguindo o Padrão GRASP Especialista na Informação, poderiamos dizer que: Quem tem os dados deve ser responsável por manipula-los. Com isso, conseguimos um boa divisão de responsábilidades, conseguimos fornecer um bom encapsulamento, evitamos inveja dos dados enfim, conseguimos evitar modelos anêmicos.
Muitas vezes olhando para o Especialista da Informação fiz reflexões parecidas com esta: O objeto Fornecedor conhece seus dados logo seria responsabilidade dele se salvar, assim manteriamos o encapsulamento etc.. etc...
Mas como persistência é um problema de infra vamos voltar lá no mundo de bobject...
reflexões...
Manipular os dados não significa persisti-los mas aplicar invariantes e regras de negócio. Isso que torna o modelo não anêmico.
Eu vejo que no DDD essa coisa de persistir a si mesmo é desestimulada. Eu (digamos entity) posso até usar o repositório para ler a persistencia e resolver alguma regra de negocio, ou seja, eu conheco a persistencia (por meio do repositorio), mas eu nao me persisto porque não é minha responsabilidade, eu faco parte de uma unit of work.
This message was edited 1 time. Last update was at 26/11/2007 18:36:36
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 20:08:34
|
Alessandro Lazarotti
Virtual Machine Man
![[Avatar]](/images/avatar/2aaaddf27344ee54058548dc081c6541.jpg)
Membro desde: 21/01/2004 14:12:54
Mensagens: 718
Offline
|
Rodrigo Carvalho Auler wrote:
Lezinho wrote:Eu simplemente acho que um EntidadeRepository.add(entidade) resolve o problema, sem ter que comprometer a modelagem da Entidade a.k.a. ActiveRecord desnecessário.
Uma pergunta: nesse caso, como vc faz a validação dos dados do objeto?
 Cria um método entidade.validar() e chama dentro do EntidadeRepository.add(entidade)?
[]'s
Rodrigo C. A.
A questão da validação é relativa a cada caso.
Se a validação é sobre invariantes simples do contrato, eu utilizo Hibernate Validator (para contratos nulos, tamanho de campos, datas futuras ou passadas, regex, etc)
Ex:
Se a validação para um contrato for quanto a permissão de papeis do usuário, eu uso o Seam com Drools :
... agora se o contrato for algo que exige mais do negócio, entao eu evito colocar validações nos clientes e implemento no próprio negócio (por exemplo, quando um Entity faz um pedido ao Repository, quem vai verificar o contrato é o Repository).
Eu tento manter o código o mais limpo possível dos contratos, mas quando não é possível não se pode fazer muita coisa.
|
... Lezinho
------------------------
twitter: @lazarotti
http://alessandrolazarotti.wordpress.com/
http://jbossbrasil.org/
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 20:32:29
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3420
Offline
|
brunohansen wrote:
sergiotaborda wrote:
Isso é uma falácia.
Rs... Engraçada essa afirmação!
Você esta dizendo que um padrão GRASP é uma falácia?
Não. Estou dizendo que a frase a seguir é uma falácia.
brunohansen wrote:] O objeto Fornecedor conhece seus dados logoseria responsabilidade dele se salvar, assim manteriamos o encapsulamento etc.. etc...
'A' conhecer seus dados não implica em que é responsabilidade de 'A' fazer algo com eles.
Se formos por esse caminho eu poderia dizer que:
"O DefaultTableModel do Swing conhece seus dados logo ele teria a responsabilidade de se mostrar na tela."
Acho que é simples de entender que esse tipo de construção lógica é uma falácia.
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 26/11/2007 21:12:59
|
feliperod
JavaTeenager
![[Avatar]](/images/avatar/12d836bf64839f987338414ccbec657f.jpg)
Membro desde: 07/11/2006 14:10:54
Mensagens: 184
Offline
|
Fornecedor.insert() é errado do pontode vista de Domain Driven Design.
Porque?
Porque você não chega no mundo real e pede pelo telefone pra um fornecedor inserir dados, mas pede pra um fornecedor preencher um formulário. Portanto, Fonecerdor.preencheFormulario() seria cogitável, porém a melhor forma é colocar o metodo de inserção num repository ou num service.
Pense num repository como uma classe que administra uma coleção de objetos de um determinado tipo. Se você que adicionar um fornecedor a uma coleção (DB por exemplo), tem que adicionar pelo repository.
Nomes importam muito na abastração. Aliás acho que é isso que diferencia arquitetos de desenvolvedores. A capacidade de abstrair.
PS.: Você não é obrigado a utilizar DDD, mas não diga que está utilizando quando na verdade não está.
|
Felipe Rodrigues de Almeida
No Twitter: @felipero
www.fratech.net
The Fratech way |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 08/02/2009 15:06:53
|
F?io Henrique
Debugger
![[Avatar]](/images/avatar/ea370fd565d330b204134f3cd29adbdf.jpg)
Membro desde: 08/02/2009 11:11:33
Mensagens: 57
Localização: Rio de Janeiro
Offline
|
Qualquer padrão possui as contra-indicações, além de ser importante saber onde aplicar, devemos saber também onde não aplicar.
No caso, as classes de persistência são mais Especialistas na Informação para a tarefa de inserir no BD.
E você teria um problemas de Coesão Baixa e Alto Acoplamento, além de uma lógica similar fique duplicada em muitas classes persistêntes.
Por exemplo: uma venda pode informar seu total, mas ela não saber onde persistir (penso que ela nem deveria saber da existência do DAO), o DAO sabe onde persistir um objeto, e traze-lo de volta.
Estou com saudades do tempo que eu fazia tudo da minha cabeça. IMHO.
This message was edited 3 times. Last update was at 08/02/2009 15:40:10
|
Java until hell freezes over
1 ano de Java
Procurando Projeto |
|
|
 |
|
|