| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 10/05/2009 15:45:28
|
danielbussade
JavaEvangelist
Membro desde: 13/09/2007 09:26:21
Mensagens: 415
Localização: Itaperuna -RJ
Offline
|
Olá pessoal relendo alguns posts do GUJ, como este http://www.guj.com.br/posts/list/15/60916.java
e outros do blog da caelum como este http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto entre outros lugares, comecei a me questionar sobre a maneira como tenho arquiteturado minhas aplicações WEB.
Atualmente quando vou fazer um CRUD, faço da seguinte maneira, tentando ser o mais simples possível, utilizando algum framework MVC.
REQHTTP - > Action -> DAO -> SGDB
OBS
*Quando os dados chegam na Action, o POJO já vem populado pelo meu framework, como mentawai ou VRaptor.
*Minha classe Action não tem um Dao como atributo, o mesmo é instanciado dentro de cada método, isso porque utilizo um Dao generico(antes utilizava um dao para cada classe e injetava o mesmo por IoC), mas hoje prefiro a abordagem de um Dao generico, uma vez que consegui diminuir muito os numeros de .java na minha aplicação.
Quando preciso de uma funcionalidade mais "complexa", digamos logo apos o cadastro de um usuario mandar um e-mal para o mesmo. Neste caso crio um service, como no exmplo;
Uma nova abordagem que estou pensando a utilizar é a seguinte:
REQHTTP -> Action -> Modelo de Negocio > Repository(interface) > Dao> SGB
Como neste artigo http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto onde o autor fala ao inves de ter um codigo como este:
Pode ser substituido por
<c:forEach items="${fornecedor.ContasPagasDoMes}" var="contas">
<c:out value="${conta.qualquerCoisa}"/>
</c:forEach>
Onde Fornecedor tem um repository de contas!
Realmente fica bem mais OO, mais vejo algumas desvantagens, isso não seria uma violação de camada ou seja a view, está acessando diretamente o DAO, pode argumentar que repository é um conceito de negocio, tudo bem, mas no caso seria so um delegate para o DAO, isso não seria violar camadas?
Estou pensando em usar a segunda abordagem, mas antes queria ouvir sugestões. Qual estrutura geralmente vcs usam para acessar um SGDB:
REQHTTP -> Action ->Dao > SGB
REQHTTP -> Action -> Modelo de Negocio > Repository(interface) > Dao> SGB
ou ainda
req HTTP -> Action -> Modelo -> Repository -> Implementação concreta de Repository -> DAO -> Implementação concreta de UserDAO -> Banco de dados
Valeu
|
When you steal from one author, is called plagiarism, when you steal from many is called research.
|
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 10/05/2009 16:16:31
|
saoj
JWizard
![[Avatar]](/images/avatar/2e7ceec8361275c4e31fee5fe422740b.png)
Membro desde: 09/03/2004 23:34:46
Mensagens: 2665
Localização: Chicago, EUA
Offline
|
Eu mesmo já embazei diversas vezes o WEB -> Action -> Service/Logic -> DAO/Repository -> DB
Mas muitas vezes isso é um overkill, um tédio de redundancia e classes desnecessárias.
Dependendo do projeto eu hoje faço WEB -> Action -> DAO -> DB. Teoricamente isso não é o mais certo, mas na prática e disparado o mais conveniente. Muitos projetos RoR são feitos assim.
Se vc está preocupado com acoplamento, dê uma olhada nesse artigo:
http://www.theserverside.com/news/thread.tss?thread_id=48304
This message was edited 1 time. Last update was at 10/05/2009 16:16:57
|
Sergio A Oliveira Jr. - saoj
ExperiMENTA:
Mentawai = http://www.mentaframework.org - Full-stack Java Web Framework com Configuracão Programática
MentaQueue = http://mentaqueue.soliveirajr.com - Queue de alta-performance.
MentaLog = http://mentalog.soliveirajr.com - Non-intrusive, fast, garbage-less, colored and straightforward logging
MentaBean = http://mentabean.soliveirajr.com - Tiny ORM with SQL Builder
MentaRegex = http://mentaregex.soliveirajr.com - Perl-style regex for Java.
MentaContainer = http://mentacontainer.soliveirajr.com - Straightforward IoC, DI e Auto-Wiring
Space4J = http://www.space4j.org - Banco-de-dados de Objetos em Memória
Options-Lib = https://github.com/saoj/options-lib - Ruby classes para ter acesso as opcoes do Yahoo Finance
Selleto = http://www.selleto.com.br
Flipinion = http://www.flipinion.com
Kawai = http://www.kawaiwiki.org
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/05/2009 12:13:27
|
Rubem Azenha
GUJ Master
![[Avatar]](/images/avatar/cb953f6ca5923f7517125db46ed1293d.jpg)
Membro desde: 28/06/2004 00:10:43
Mensagens: 1933
Localização: São Paulo, SP
Offline
|
saoj wrote:Eu mesmo já embazei diversas vezes o WEB -> Action -> Service/Logic -> DAO/Repository -> DB
Mas muitas vezes isso é um overkill, um tédio de redundancia e classes desnecessárias.
Dependendo do projeto eu hoje faço WEB -> Action -> DAO -> DB. Teoricamente isso não é o mais certo, mas na prática e disparado o mais conveniente. Muitos projetos RoR são feitos assim.
Se vc está preocupado com acoplamento, dê uma olhada nesse artigo:
http://www.theserverside.com/news/thread.tss?thread_id=48304
Eu também acho que as vezes podemos chamar o DAO\Repository direto da Action (telas de pesquisa, por exemplo), mas isso acaba sendo um problema sério para manutenção.
Mesmo que você diga que se um dia precisar de mais coisas você vai refatorar e colocar num objeto de negócio, muitas vezes isso não é feito, é muito mais fácil fazer certo da primeira vez do que deixar pra depois "quando precisar".
Geralmente mesmo para CRUDs, as operações de "update" eu prefiro colocar em classes de negócio. Sempre tem uma verificação, uma validação, um fluxo, um workflow que deve ser executado antes ou depois de criar ou alterar uma entidade e fazer dao.save na action é medir pra vir um code monkey depois e colocar código na action que não deveria estar na action... Já deixar tudo separado corretamente orienta melhor quem for dar manutenção no código depois.
|
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/05/2009 14:19:50
|
Leonardo3001
GUJ Ranger
Membro desde: 04/07/2007 18:28:58
Mensagens: 975
Offline
|
Depende do estilo que você quer fazer.
Se a lógica de sua aplicação estão em classes comumente chamadas "de negócio" (não gosto desse termo, prefiro classes de serviço). Então é natural pensar que toda Action sempre invoca um método da classe de Serviço.
Agora, ao colocarmos as lógicas nas próprias entidades (e, segundo alguns, deixando mais OO), então as classes de serviço desaparecem e não é nada de errado a Action obter uma entidade de um repositório e depois invocar um método desse objeto retornado.
É importante frisar que DAO não é repositório. DAO possui uma abstração puramente de persistência e repositório é uma abstração de negócio. Pode-se implementar o Repositório como uma interface da camada de negócio e o DAO como uma classe que a implementa da camada de persistência. Mas não é o único jeito e não precisa ser assim por toda a sua aplicação.
Como relação ao fato de, se a view chamar algo do objeto do domínio, então ocorreria alguma violação, a resposta é não. Pelo MVC é permito a view acessar o model. Pela arquitetura em camadas, a camada de apresentação (sua action e seu jsp) pode ter acesso à camada de negócio (suas entidades, repositórios, eventuais serviços e factories).
This message was edited 1 time. Last update was at 11/05/2009 14:20:20
|
Leonardo Veríssimo
-------------------------------------------------
Objectzilla |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/05/2009 14:37:23
|
Rubem Azenha
GUJ Master
![[Avatar]](/images/avatar/cb953f6ca5923f7517125db46ed1293d.jpg)
Membro desde: 28/06/2004 00:10:43
Mensagens: 1933
Localização: São Paulo, SP
Offline
|
Leonardo3001 wrote:
É importante frisar que DAO não é repositório. DAO possui uma abstração puramente de persistência e repositório é uma abstração de negócio. Pode-se implementar o Repositório como uma interface da camada de negócio e o DAO como uma classe que a implementa da camada de persistência. Mas não é o único jeito e não precisa ser assim por toda a sua aplicação.
Por favor, não vamos voltar nessa ladainha de que DAO não é repositório. Já foi inumeras vezes discutidas aqui e ficou claro que o ponto não é esse.
|
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/05/2009 15:24:38
|
danielbussade
JavaEvangelist
Membro desde: 13/09/2007 09:26:21
Mensagens: 415
Localização: Itaperuna -RJ
Offline
|
Rubem Azenha wrote:
saoj wrote:Eu mesmo já embazei diversas vezes o WEB -> Action -> Service/Logic -> DAO/Repository -> DB
Mas muitas vezes isso é um overkill, um tédio de redundancia e classes desnecessárias.
Dependendo do projeto eu hoje faço WEB -> Action -> DAO -> DB. Teoricamente isso não é o mais certo, mas na prática e disparado o mais conveniente. Muitos projetos RoR são feitos assim.
Se vc está preocupado com acoplamento, dê uma olhada nesse artigo:
http://www.theserverside.com/news/thread.tss?thread_id=48304
Eu também acho que as vezes podemos chamar o DAO\Repository direto da Action (telas de pesquisa, por exemplo), mas isso acaba sendo um problema sério para manutenção.
Mesmo que você diga que se um dia precisar de mais coisas você vai refatorar e colocar num objeto de negócio, muitas vezes isso não é feito, é muito mais fácil fazer certo da primeira vez do que deixar pra depois "quando precisar".
Geralmente mesmo para CRUDs, as operações de "update" eu prefiro colocar em classes de negócio. Sempre tem uma verificação, uma validação, um fluxo, um workflow que deve ser executado antes ou depois de criar ou alterar uma entidade e fazer dao.save na action é medir pra vir um code monkey depois e colocar código na action que não deveria estar na action... Já deixar tudo separado corretamente orienta melhor quem for dar manutenção no código depois.
Rubem, só para ficar claro para mim, quando você disse "classes de negócio" quer dizer tipo UsuarioService, ou quis dizer a propria entidade Usuario?
|
When you steal from one author, is called plagiarism, when you steal from many is called research.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/05/2009 16:38:27
|
Rubem Azenha
GUJ Master
![[Avatar]](/images/avatar/cb953f6ca5923f7517125db46ed1293d.jpg)
Membro desde: 28/06/2004 00:10:43
Mensagens: 1933
Localização: São Paulo, SP
Offline
|
danielbussade wrote:
Rubem, só para ficar claro para mim, quando você disse "classes de negócio" quer dizer tipo UsuarioService, ou quis dizer a propria entidade Usuario?
Hum... digamos que tanto faz. Se a regra de negócio precisa ser "orquestrada", UsuarioService, caso contrario, vai na própria entidade Usuario mesmo.
|
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/05/2009 19:15:18
|
danielbussade
JavaEvangelist
Membro desde: 13/09/2007 09:26:21
Mensagens: 415
Localização: Itaperuna -RJ
Offline
|
Rubem Azenha wrote:
danielbussade wrote:
Rubem, só para ficar claro para mim, quando você disse "classes de negócio" quer dizer tipo UsuarioService, ou quis dizer a propria entidade Usuario?
Hum... digamos que tanto faz. Se a regra de negócio precisa ser "orquestrada", UsuarioService, caso contrario, vai na própria entidade Usuario mesmo.
Supondo então que a regra de negócio não precise ser orquestrada. Ai você coloca as operacoes de CRUD todas na classes do seu Domain?
E no domain você acesso o que, uma interface Dao? Ou coloca a implementação Dao direto?
|
When you steal from one author, is called plagiarism, when you steal from many is called research.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/05/2009 20:17:00
|
Leonardo3001
GUJ Ranger
Membro desde: 04/07/2007 18:28:58
Mensagens: 975
Offline
|
danielbussade wrote:Supondo então que a regra de negócio não precise ser orquestrada. Ai você coloca as operacoes de CRUD todas na classes do seu Domain?
E no domain você acesso o que, uma interface Dao? Ou coloca a implementação Dao direto?
Talvez eu leve uma segunda "patada" por desviar o tópico, mas enfim... vamos lá.
Se você tem apenas CRUD, então toda a arquitetura é desnecessária, e basta fazer uma tela refletir as operações do banco. Mas a realidade não é essa, CRUD é superenfatizado, e na realidade, operações estritamente CRUDs são mais raras do que muita gente imagina. Afinal, não é tudo que pode excluído, atualizações podem exigir regras de carência, inserções são seguidas de validações e só podem ser feitas por um seleto grupos de pessoas, e etc.
Mas entendo a sua dúvida, você quer saber se a própria entidade deve lidar com sua própria persistência. Pois bem, certas coisas são impossíveis - exemplo: o SELECT - porque um objeto não pode consultar a si mesmo, se este ainda não existe. É necessário um outro objeto pra isso, o Repositório. As outras operações até podem ser feitas pelo próprio objeto, mas como é difícil injetar infraestrutura em objetos de domínio (você dependeria de factories), é melhor ter o repositório fazer as operações de escrita também.
|
Leonardo Veríssimo
-------------------------------------------------
Objectzilla |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/05/2009 20:35:06
|
danielbussade
JavaEvangelist
Membro desde: 13/09/2007 09:26:21
Mensagens: 415
Localização: Itaperuna -RJ
Offline
|
Leonardo3001 wrote:
danielbussade wrote:Supondo então que a regra de negócio não precise ser orquestrada. Ai você coloca as operacoes de CRUD todas na classes do seu Domain?
E no domain você acesso o que, uma interface Dao? Ou coloca a implementação Dao direto?
Talvez eu leve uma segunda "patada" por desviar o tópico, mas enfim... vamos lá.
Se você tem apenas CRUD, então toda a arquitetura é desnecessária, e basta fazer uma tela refletir as operações do banco. Mas a realidade não é essa, CRUD é superenfatizado, e na realidade, operações estritamente CRUDs são mais raras do que muita gente imagina. Afinal, não é tudo que pode excluído, atualizações podem exigir regras de carência, inserções são seguidas de validações e só podem ser feitas por um seleto grupos de pessoas, e etc.
Mas entendo a sua dúvida, você quer saber se a própria entidade deve lidar com sua própria persistência. Pois bem, certas coisas são impossíveis - exemplo: o SELECT - porque um objeto não pode consultar a si mesmo, se este ainda não existe. É necessário um outro objeto pra isso, o Repositório. As outras operações até podem ser feitas pelo próprio objeto, mas como é difícil injetar infraestrutura em objetos de domínio (você dependeria de factories), é melhor ter o repositório fazer as operações de escrita também.
Leonardo , obrigado pelas respostas. Estava com esta idéia de colocar metodos CRUD na Entity,mas ainda acho muito esquisito as Entity, terem metodos de CRUD, acho melhor as entity refletir estritamente o Negócio, tendo somente atributos e metodos referentes ao negocio.
Da maneira como faço:
REQHttp -> Action - > DAO -> SGBD
A minha unica duvida é se ao invés de chamar um Dao direto da action, chamar um Façade como GerenciadorUsuario onde teria um metodo create(parametros_do_usuario) e neste FAçade chamaria o Dao, ou ate mesmo um Service, se precisa de alguma "orquestração", como obserevou o rubem.
Este Dao seria uma interface assim não acoplo nem minha action, nem o Façade a infraestrutura de persistencia.
Ao inves de tornar isso padrão, so crio um service ou um Façade, quando preciso de algo a "mais" assim evito delegação de camadas desnecessária.
|
When you steal from one author, is called plagiarism, when you steal from many is called research.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 14/05/2009 09:43:06
|
renanreismartins
GUJ Ranger
![[Avatar]](/images/avatar/b43a306ca1e27299a57727ff5c0d4998.jpg)
Membro desde: 19/09/2007 15:19:38
Mensagens: 807
Localização: São Paulo - SP
Offline
|
Rubem Azenha wrote:
danielbussade wrote:
Rubem, só para ficar claro para mim, quando você disse "classes de negócio" quer dizer tipo UsuarioService, ou quis dizer a propria entidade Usuario?
Hum... digamos que tanto faz. Se a regra de negócio precisa ser "orquestrada", UsuarioService, caso contrario, vai na própria entidade Usuario mesmo.
Como assim orquestrada ?
...
otimo topico galera... bom sempre fiz acesso aos DAOs pela action mesmo, mas ultimamente tenho criado os service. Acho que desta forma fica até mais facil de desenvolver os testes.
|
http://renanreismartins.blogspot.com/ - Para apaixonados por desenvolvimento de software |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 14/05/2009 10:55:40
|
danielbussade
JavaEvangelist
Membro desde: 13/09/2007 09:26:21
Mensagens: 415
Localização: Itaperuna -RJ
Offline
|
Pense em "orquestrada", como o seguinte. Digamos que tenha uma regra de Negocio em duas classes diferentes e você precisa executar as duas regras de negocio para formar uma terceira.
Ai usamos um Service, pois ele não tem estado apenas fornece um serviço , que não é responsabilidade "unica" de ninguem, mas sim responsabilidades combinadas, entre duas ou varias classes;
Qualquer duvida, pergunte!
Valeu
|
When you steal from one author, is called plagiarism, when you steal from many is called research.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 14/05/2009 12:22:37
|
renanreismartins
GUJ Ranger
![[Avatar]](/images/avatar/b43a306ca1e27299a57727ff5c0d4998.jpg)
Membro desde: 19/09/2007 15:19:38
Mensagens: 807
Localização: São Paulo - SP
Offline
|
muito obrigado pela explicação e atençao amigo.
seguindo este ponto de vista, como vc gerencia transacoes ?
como pode usar 2 regras para formar uma terceira entao o melhor seria abrir e fechar transacoes no inicio e fim dos metodos das actions, estou certo?
abraços
|
http://renanreismartins.blogspot.com/ - Para apaixonados por desenvolvimento de software |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 18/05/2009 00:42:33
|
danielbussade
JavaEvangelist
Membro desde: 13/09/2007 09:26:21
Mensagens: 415
Localização: Itaperuna -RJ
Offline
|
Olá, na minha opinião o correto seria ter um filtro para controlar a transação, visto que qualquer uma das operações que falhasse teria que efetuar rollback na outra.
|
When you steal from one author, is called plagiarism, when you steal from many is called research.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 18/05/2009 06:50:30
|
renanreismartins
GUJ Ranger
![[Avatar]](/images/avatar/b43a306ca1e27299a57727ff5c0d4998.jpg)
Membro desde: 19/09/2007 15:19:38
Mensagens: 807
Localização: São Paulo - SP
Offline
|
mas ai eu abriria uma transacao para cada request ? isso nao seria ruim ?
abraços
|
http://renanreismartins.blogspot.com/ - Para apaixonados por desenvolvimento de software |
|
|
 |
|
|