| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 09/01/2007 15:45:50
|
Filipe Sabella
Forum Spammer
Membro desde: 12/03/2003 11:25:57
Mensagens: 4641
Online
|
Excelente compilação, shoes. Obrigado
|
Former LIPE. |
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 01/02/2007 11:36:11
|
Renatov
What is classpath?
Membro desde: 29/01/2007 13:50:25
Mensagens: 7
Offline
|
Senhores,
Parabéns pelo excelente fórum e pela discussão em alto nível.
Gostaria de colocar algumas "gotas de pimenta" na conversa.
Desenvolvemos aqui na empresa alguns sistemas usando CMP 2.0 e posteriormente começamos a utilizar o Hibernate como framework de persistência. Nos primeiros sistemas fizemos uso intensivo de DTOs e nos sistemas Hibernate passamos a utilizar os próprios Domain Beans. Só pra contextualizar, as aplicações são divididas em camadas, onde os canais de interface com o usuários são desenvolvidas e implantadas em aplicações independentes das aplicações de negócio. Exemplo, aplicações clientes WEB e SWING, com as aplicações servidoras distribuídas através do uso de EJBs.
Alguns pontos sobre o uso dos Domain Beans como moeda de troca dos métodos com as aplicações clientes:
1. As aplicações se tornaram dependentes da solução de persistência. A biblioteca do Hibernate passou a ser necessária na implantação das aplicações clientes. Ou seja, se eu uso um TomCat para implementar minhas aplicações WEB preciso anexar o jar do Hibernate a um container que é somente WEB.
2. Os Domain Bean Hibernate (pois eles passam a ser objetos Hibernate) quando enviados ao cliente são passíveis de lançarem exceções Hibernate. Por exemplo, um objeto A que possua uma coleção de objetos B ( tipo Funcionário com Dependentes) e cuja a associação está marcada com LAZY. Neste caso, se o programador da aplicação cliente tentar acessar a coleção de Dependentes recebe uma exceção Hibernate avisando que não é possível "carregar" os objetos pois estão fora do "contexto" do Hibernate.
Esses problemas sempre me remetem a questão do isolamento entre as camadas. Mesmo não trabalhando com sistemas distribuídos (SOAP, RMI, CORBA) a separação lógica entre as camadas do seu sistema devem continuar a existir e não me parece uma boa prática enviar objetos Hibernate ou EJB3 para uma página JSP. Como também o contrário, e muito mais fácil de ser percebido como uma prática ruim, enviar para as camadas de négocio da aplicação, objetos Struts (como os objetos que estendem o ActionForm) ou objetos que lidam com o protocolo HTTP como os HttpServletRequest.
Me parece bastante claro os objetivos de uma aplicação cliente: coletar e exibir dados. Nada mais. O fato de enviar um Bean "parrudo", cheio de "regras de negócio" acredito que apenas dificulte o trabalho de quem implementa a aplicação cliente. Na grande maioria das vezes você precisa
contextualizar as suas regras de negócio ao escopo de uma transação, fora dela você está sujeito à inconsistências. A lógica de cada caso de uso faz parte da solução do sistema e deve ser descrita na aplicação servidora. Muitas das vezes apenas com os dados "inputados" pelo cliente o estado do objeto ainda se encontra "incompleto", e que só vai ser "terminado" durante o decorrer da transação na aplicação servidora. Não adianta portanto que os "sets" ou os "validates" sejam executados pela aplicação cliente. É uma função dos componentes de sistema e dos componentes de domínio (vide UML Components - Cheesman).
Quanto a grande dificuldade de criar e manter DTOs, não vejo dessa forma. Exite uma classe (como a maioria das fornecidas pela Apache) que é a BeanUtils, que tem um método muito útil chamado copyProperties(). Com ele é possível facilmente popular os Domain Beans a partir dos Forms e/ou HashMaps e vice-versa. Quanto a gerar e regerar os Assemblers e os próprios DTOS, a maioria das IDEs já faz isso pra você.
Outra coisa, Beans simples normalmente são usados para telas de cadastro. Em grande parte dos casos de uso os objetos que chegam a aplicação cliente são mais complexos. Vide telas de consulta onde normalmente lidamos com "resultsets", ou grafos de objetos.
Bom, acho que to escrevendo demais .... STOP.
Abração.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 01/02/2007 12:10:04
|
pcalcado
Moderador
![[Avatar]](/images/avatar/110eec23201d80e40d0c4a48954e2ff5.jpg)
Membro desde: 08/03/2004 17:19:35
Mensagens: 5169
Localização: Sydney - Australia
Offline
|
Oi, Renato,
Renatov wrote:
1. As aplicações se tornaram dependentes da solução de persistência. A biblioteca do Hibernate passou a ser necessária na implantação das aplicações clientes. Ou seja, se eu uso um TomCat para implementar minhas aplicações WEB preciso anexar o jar do Hibernate a um container que é somente WEB.
Isso indica que você não está utilizando separação de Camadas. A Camada de Persistência é a única que deve (pode, na verdade) depender do Hibernate, se seu Tomat não é responsável pela persistência provavelmente você tem um problema de arquitetura.
Renatov wrote:
2. Os Domain Bean Hibernate (pois eles passam a ser objetos Hibernate)
Novamente vejo um problema de arqutietura aqui. Seus objetos persistidos pelo Hibernate deveriam ser POJOs, eles não podem depender do Hibernate. Essa dependência é um erro de projeto.
Renatov wrote:
quando enviados ao cliente são passíveis de lançarem exceções Hibernate. Por exemplo, um objeto A que possua uma coleção de objetos B ( tipo Funcionário com Dependentes) e cuja a associação está marcada com LAZY. Neste caso, se o programador da aplicação cliente tentar acessar a coleção de Dependentes recebe uma exceção Hibernate avisando que não é possível "carregar" os objetos pois estão fora do "contexto" do Hibernate.
Este é um problema de Lazy-Loading, você tem opções para gerenciar este problema na Camada de Persistência ou simplesmente não utilizar este recurso.
Renatov wrote:
Esses problemas sempre me remetem a questão do isolamento entre as camadas. Mesmo não trabalhando com sistemas distribuídos (SOAP, RMI, CORBA) a separação lógica entre as camadas do seu sistema devem continuar a existir e não me parece uma boa prática enviar objetos Hibernate ou EJB3 para uma página JSP.
Como falei antes este é o problema desta arqutietura: não existe separação de Camadas. Você está deixando lógica de persistência escorrer para a Camada de Negócios e isso não é culpa do framework
Renatov wrote:
Como também o contrário, e muito mais fácil de ser percebido como uma prática ruim, enviar para as camadas de négocio da aplicação, objetos Struts (como os objetos que estendem o ActionForm) ou objetos que lidam com o protocolo HTTP como os HttpServletRequest.
Exato e não há porque você fazer isso com Hibernate.
Renatov wrote:
Me parece bastante claro os objetivos de uma aplicação cliente: coletar e exibir dados. Nada mais. O fato de enviar um Bean "parrudo", cheio de "regras de negócio" acredito que apenas dificulte o trabalho de quem implementa a aplicação cliente.
Para isso existem DTOs, que sao um conceito diferente de TO(antigo VO) ou até de objetos burros.
Renatov wrote:
Na grande maioria das vezes você precisa
contextualizar as suas regras de negócio ao escopo de uma transação, fora dela você está sujeito à inconsistências. A lógica de cada caso de uso faz parte da solução do sistema e deve ser descrita na aplicação servidora. Muitas das vezes apenas com os dados "inputados" pelo cliente o estado do objeto ainda se encontra "incompleto", e que só vai ser "terminado" durante o decorrer da transação na aplicação servidora. Não adianta portanto que os "sets" ou os "validates" sejam executados pela aplicação cliente. É uma função dos componentes de sistema e dos componentes de domínio (vide UML Components - Cheesman).
Não entendi o que isso tem a ver com TO/VO.
Hmm... Cheesman? Deixa eu adivinhar: CCE da PUC-Rio?
Renatov wrote:
Quanto a grande dificuldade de criar e manter DTOs, não vejo dessa forma. Exite uma classe (como a maioria das fornecidas pela Apache) que é a BeanUtils, que tem um método muito útil chamado copyProperties(). Com ele é possível facilmente popular os Domain Beans a partir dos Forms e/ou HashMaps e vice-versa. Quanto a gerar e regerar os Assemblers e os próprios DTOS, a maioria das IDEs já faz isso pra você.
Uma biblioteca extra só para criar objetos burros? Acho que não condiz muito com OOP.
De qualquer forma o problema não é copiar dados apenas, é manter hierarquias paralelas artificiais de objetos.
Renatov wrote:
Outra coisa, Beans simples normalmente são usados para telas de cadastro. Em grande parte dos casos de uso os objetos que chegam a aplicação cliente são mais complexos. Vide telas de consulta onde normalmente lidamos com "resultsets", ou grafos de objetos.
Existem dezenas de maneira de lidar com isso num domínio rico, não vejo qual o problema.
|
Phillip Calçado "Shoes"
http://fragmental.tw/
http://blog.fragmental.com.br/
"It is unfortunate that much of what is called 'object-oriented programming today is simply old style programming with fancier constructs." - Alan Kay |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 01/02/2007 13:58:17
|
Renatov
What is classpath?
Membro desde: 29/01/2007 13:50:25
Mensagens: 7
Offline
|
Olá PCalcado,
A arquitetura de camadas que usamos é a seguinte:
VISÃO _
<=> |
CONTROLE | --- > WAR
<=> |
DELEGAÇÃO _|
<=>
SISTEMA _
<=> | ----> EJB JAR
DOMÍNIO _ |
Para vc entender a dependência que o "Hibernate Domain Bean" gera nas aplicações clientes, experimente criar um WAR que receba um POJO que foi utilizado pelo Hibernate em um archive EJB como retorno de um determinado método de negócio, implementado por um Session Bean. Para o exemplo ficar legal, procure implantar as aplicações de forma independente, de preferência em application servers distintos, no melhor exemplo um TomCat e um JBoss.
Você vai perceber que para "deployar" a sua aplicação Web no TomCat você vai ter que fornecer o jar do Hibernate. Isso acontece por que o POJO que representa uma entidade de negócio, que teoricamente é um objeto Java comum, é estendido pelo Hibernate. Ou seja, o objeto que chega como retorno para você na tua camada de delegação não é mais um "Plain Java" mas um objeto Hibernate. Daí a tal da dependência.
Quanto ao fato de criar estruturas paralelas, a primeira vista, realmente parece o fim do mundo. Concordo com você que "duplicar código" é sempre uma má idéia. Mas o fato de trabalhar por contratos e tentar isolar os clientes de componentes mais internos, eu considero crucial. O "Hibernate Domain Bean" acaba se tornando um "Mochileiro das Galáxias". Sai das camdas mais baixas do sistema (camada de persistência) e vai parar nas páginas JSP. Isso para mim é o que se chama de "ALTO ACOPLAMENTO". Ou seja, deixamos de ter trabalho criando estruturas paralelas mas ganhamos uma alta dependência dos clientes com pacotes e interfaces do tipo br.com.acme.xpto.entidades.Aluno. Realmente não acredito que se justifique.
Abração.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 01/02/2007 14:11:15
|
cv
Moderador
![[Avatar]](/images/avatar/210f760a89db30aa72ca258a3483cc7f.jpg)
Membro desde: 04/04/2003 00:32:12
Mensagens: 7817
Localização: São Paulo, SP
Offline
|
Algumas perguntas:
1) Camada de delegacao? Huh?
2)
Renatov wrote:Para vc entender a dependência que o "Hibernate Domain Bean" gera nas aplicações clientes, experimente criar um WAR que receba um POJO que foi utilizado pelo Hibernate em um archive EJB como retorno de um determinado método de negócio, implementado por um Session Bean. Para o exemplo ficar legal, procure implantar as aplicações de forma independente, de preferência em application servers distintos, no melhor exemplo um TomCat e um JBoss.
Pra que?
Lembre-se da primeira grande regra de sistemas distribuidos: nao construa sistemas distribuidos
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 01/02/2007 14:42:27
|
pcalcado
Moderador
![[Avatar]](/images/avatar/110eec23201d80e40d0c4a48954e2ff5.jpg)
Membro desde: 08/03/2004 17:19:35
Mensagens: 5169
Localização: Sydney - Australia
Offline
|
Renatov wrote:
Para vc entender a dependência que o "Hibernate Domain Bean" gera nas aplicações clientes, experimente criar um WAR que receba um POJO que foi utilizado pelo Hibernate em um archive EJB como retorno de um determinado método de negócio, implementado por um Session Bean. Para o exemplo ficar legal, procure implantar as aplicações de forma independente, de preferência em application servers distintos, no melhor exemplo um TomCat e um JBoss.
Você vai perceber que para "deployar" a sua aplicação Web no TomCat você vai ter que fornecer o jar do Hibernate. Isso acontece por que o POJO que representa uma entidade de negócio, que teoricamente é um objeto Java comum, é estendido pelo Hibernate. Ou seja, o objeto que chega como retorno para você na tua camada de delegação não é mais um "Plain Java" mas um objeto Hibernate. Daí a tal da dependência.
O sue problema é classloading: O classloader RMI não está disponível no seu contexto.
Como você resolve isso com EJBs se não colocar um jboss-client.jar da vida no classpath?
De qualquer modo este é o exemplo clássico do uso de DTOs: troca entre duas camadas físicas. Como falei o problema é arquitetrual.
Renatov wrote:
Quanto ao fato de criar estruturas paralelas, a primeira vista, realmente parece o fim do mundo. Concordo com você que "duplicar código" é sempre uma má idéia. Mas o fato de trabalhar por contratos e tentar isolar os clientes de componentes mais internos, eu considero crucial. O "Hibernate Domain Bean" acaba se tornando um "Mochileiro das Galáxias". Sai das camdas mais baixas do sistema (camada de persistência) e vai parar nas páginas JSP. Isso para mim é o que se chama de "ALTO ACOPLAMENTO". Ou seja, deixamos de ter trabalho criando estruturas paralelas mas ganhamos uma alta dependência dos clientes com pacotes e interfaces do tipo br.com.acme.xpto.entidades.Aluno. Realmente não acredito que se justifique.
Não senhor. Objetos de infra-estrutura gerados automaticamente como os do Hibernate não podem ser considerados mochileiros porque são transparentes apra o desenvolvedor/projetista.
Por seu argumento AOP é algo que provoca acoplamento e aumenta a dependência, já que se baseia em substituir classes por stubs e proxies.
Recomendada a leitura do Patterns of Enterprise Application Architecture.
|
Phillip Calçado "Shoes"
http://fragmental.tw/
http://blog.fragmental.com.br/
"It is unfortunate that much of what is called 'object-oriented programming today is simply old style programming with fancier constructs." - Alan Kay |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 09/02/2009 14:41:58
|
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
|
Regras de Négocio utilizam o padrão composto e aconselho que fiquem em uma classe separada.
Por exemplo: Se você tiver que implementar mais regras de négocio para cliente diferentes?
Classes de objetos do dominio, ou conceito do mundo real chamadas de Classe Conceitual.
Mas temos objetos chamados de Classe de Software - Classe que representa uma perspectiva de especificação ou implementação de um elemento de software, independente do processo ou método. Utilize o padrão Invensão Pura, sem obrigatoriamente utilizar um posfixo DTO, VO ect.
Uma classe anêmica só é anêmica se forçada.
Martin Fowler não expandiu tanto seu conceito assim.
|
Java until hell freezes over
1 ano de Java
Procurando Projeto |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 09/02/2009 14:48:30
|
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
|
"Mochileiro das Galáxias" KKK
|
Java until hell freezes over
1 ano de Java
Procurando Projeto |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 09/02/2009 15:26:33
|
fantomas
Forum Spammer
![[Avatar]](/images/avatar/a2bf57c3aee957f2aaf75aa84717b3be.jpg)
Membro desde: 24/04/2008 16:10:55
Mensagens: 1252
Localização: Terra (maior parte do tempo)
Offline
|
pcalcado wrote:Novamente vejo um problema de arqutietura aqui. Seus objetos persistidos pelo Hibernate deveriam ser POJOs, eles não podem depender do Hibernate. Essa dependência é um erro de projeto.
@pcalcado, o que o Renatov (espero não ter me enganado) está tentando dizer é que (se entendi bem): Se uma entidade possui uma collection o Hibernate "injeta" um objeto que possui caracteristicas bem diferente de uma collection da api Java e que pertence a api do Hibernate, se algum método que manipule essa collection for acionado em um local onde a infra do hibernate não estiver presente ocorre a exception. Isso geralmente ocorre em sistemas onde o modelo está sob o "dominio" de um web server e o cliente é um swing por exemplo. @todos, no livro pojo in action (indicado tambem pelo pcalcado, aliás obrigado por essa dica) o autor comenta sobre esse dilema. flws
This message was edited 1 time. Last update was at 10/02/2009 06:43:47
|
|
|
 |
|
|