Realmente, clientes desconexos são bem mais complexos. Não adianta pensar em lazy-loading, você precisa saber exatamente o que mandar para o cliente remoto, pois o uso da rede/banda tem que ser otimizado.
Difícil decidir por essa complexidade toda só porque "um dia seu sistema pode ser acessado por uma interface desktop desconexa".
Muitas vezes é bem ruim adicionar muita complexidade tentando prever o futuro!
[quote=Fabio Kung]Realmente, clientes desconexos são bem mais complexos. Não adianta pensar em lazy-loading, você precisa saber exatamente o que mandar para o cliente remoto, pois o uso da rede/banda tem que ser otimizado.
Difícil decidir por essa complexidade toda só porque "um dia seu sistema pode ser acessado por uma interface desktop desconexa".
Muitas vezes é bem ruim adicionar muita complexidade tentando prever o futuro!
Fala Fabio, atualmente, não tenho me preocupado em “saber exatamente o que tem que mandar”. No EJB 3 tenho mandando os próprios entities para a camada de apresentação remota sem usar DTO. Aí sim o LazyLoad passa a ser uma preocupação… Mas prefiro essa preocupação do que a preocupação de ficar montando e desmontando DTO.
Rede/Banda otimizado? Não creio que vai ser 10K numa requisição RMI que vai deixar as coisas pesadas…
Outra coisa, a discussão não é sobre prever o futuro, só coloquei a questão do projeto desconectado para comparar, pois nesses projetos não dá para usar OpenSessionInView de jeito nenhum. OK?
Realmente é besteira querer deixar a sua camada de aplicação pronta para todo e qualquer cliente que queira se comunicar com o Domain Model…
[quote=rodrigoy]…mas acho que tu não entendeu o que o pattern OpenSessionInView prega. Não estou falando para colocar comandos SQL nos JSPs, estou falando para colocar a ABERTURA e FECHAMENTO da transação na VIEW de forma a encapsular tudo o que acontece na requisição web numa unit of work…
[/quote]
Rodrigo,
So um detalhe.
Se nao estou enganado o que o Open In View prega é a abertura e fechamento de uma Session do Hibernate na View.
Em sistemas web classicos isso normalmente é feito atraves de um filtro.
Mas isso nao me diz que eu preciso manter uma transacao aberta, eu posso ja ter feito commit ou rollback de tudo que eu precisava, mas mantendo a Session aberta isso ja basta para o Open In View.
Pra mim uma coisa é diferente da outra, manter uma Session aberta até na View para poder fazer Lazy Loading é muito mais simples do que colocar o controle transacional no controller.
Luca, as coisas estão tão estranhas que você está postando que creio que não estamos falando a mesma coisa!!! :?
Vamos por partes:
Sistema Web rodando servlets e JSPs (ou Frameworks Web a escolher) no Tomcat dentro do Jboss tudo numa mesma máquina virtual. Melhor escolha para um controle de abertura e fechamento de transação: OpenSessionInView. Se não concorda poste uma opção melhor…
Sistema Desktop rodando Swing + servidor de aplicações, nesse caso, uma máquina virtual no cliente Swing e outra no AppServer. Nesse cenário, não dá para usar OpenSessionInView, pois a UnitOfWork não consegue migrar do client para o server. Você sabe uma maneira transparente da transação ocorrer na camada de apresentação de um sistema remoto?
[quote=Luca]Olá
Sua frase sobre uma única máquina virtual que me refiro é esta e este pattern se chama JavaClipperTabajareitor
Repito, se você se satisfaz com um sistema isolado que exige levar seu computador junto consigo, então use Clipper, VB ou Delphi.
Mas para mim nem agenda pessoal eu admito sem acesso à Internet pois quero acessá-la de onde eu estiver no mundo.
[/quote]
Não tem muita relação o número de máquinas virtuais de uma aplicação e o fato dela viver ou não em isolamento. E muito menos com a escolha de Java, Clipper, VB ou Delphi…
[quote=Luca] Separar a camada de apresentação do acesso ao banco de dados não é introduzir complexidade. É apenas fazer um sistema que sirva para alguma coisa.
[/quote]
Em algum momento a transação tem que ser aberta, fechada ou deu uma exceção que precisa de rollback. O ponto é aonde isso deve ser feito…
[quote=Luca]Cliente desconectado apenas significa que você não tem os demais componentes do sistema instalados e replicados em sua máquina.
[/quote]
Cara, não significa só isso não… acredite em mim, estou desenvolvendo aplicações Swing a mais de 5 anos e a questão do controle transacional ainda é muito precário. É uma luta contra a complexidade e um exemplo é esse post que fiz:
Rodrigo, eu me ative a sua frase: tudo em uma única JVM.
Quanto a dificuldade de controle transacional com Swing eu não vejo nenhuma porque desde 2000 todos os sistema Swing em que eu participei do desenvolvimento NENHUM acessava a base de dados pela camada de apresentação Swing.
Rodrigo, eu me ative a sua frase: tudo em uma única JVM.
Quanto a dificuldade de controle transacional com Swing eu não vejo nenhuma porque desde 2000 todos os sistema Swing em que eu participei do desenvolvimento NENHUM acessava a base de dados pela camada de apresentação Swing.
[]s
Luca[/quote]
Luca, meus sistemas Swing também não acessam a base pela View! O resumo da arquitetura que estou usando agora é:
Panel -> Facade -> Domain Model
Nesse modelo, a transação inicia e termina no Facade…
[quote=rodrigoy]Panel -> Facade -> Domain Model
Nesse modelo, a transação inicia e termina no Facade…
[/quote]
No modelo que uso entre o Swing e o resto, há troca de mensagens usando arquitetura de mensagens HTTP e deixando a camada de apresentação o mais desacoplada possível.
Fiz sempre assim mesmo que o sistema rode todo no mesmo micro. O negócio é fazer uma vez para perceber que é fácil.
Só não me convidem para elogiar projeto que acessa EJBs no Swing a menos que me provem tim tim por tim o porque desta escolha. Até hoje vi poucos que justificassem corrretamente esta opção.
[quote=Luca]A partir desta lembrança repito: não é complexo. Mas é claro que não basta ser certificado Java para saber como.
[/quote]
Tem certas coisas que o que limita é a tecnologia atual. Quando o cliente é desconectado você precisa tomar alguns cuidados a mais. Seria ótimo se você conseguisse obter as instâncias de entities no cliente Swing e as usasse livremente sem se importar com a transação, mas infelizmente isso ainda não é a realidade.
Algumas vezes você precisa usar um Stateful para driblar um LazyLoad, ou fazer uma interface remota que limite o que o cliente pode fazer no Swing, ou forçar um FetchType.EAGER. Resumo: Essa abstração de um objeto remoto ainda é falha, principalmente no controle transacional de operações remotas.
Rodrigo, o que é preciso é se livrar deste ranço de RPC, RMI e sistemas síncronos. Habitue-se a desenvolver trocando mensagens entre o servidor e a camada de apresentação e deixe tudo isto que falou no servidor. Use arquitetura de mensagens para garantir ao cliente a atomicidade das transações.
E para falar em futuro, para mim ele será assíncrono. Todo o legado que for baseado em RPC (ou pior ainda, em RMI) ficará prejudicado. Já que você tem escola, porque não aprender e ensinar logo como fazer direito? Estamos usando Java que permite tudo isto com facilidade. É só questão de aprender a usar Java com todo seu potencial.
Camada de Apresentação “o mais desacoplada possível” é um custo alto. É bonito, mas também precisa justificar esse custo. Concorda? Outra coisa, concorda que trafegar XML com cópia dos dados dos objetos não seria a mesma coisa que usar DTOs?
Meu projeto acessa EJB direto no Swing de maneira simples, mas é EJB 3, onde os entities são livres para ir para o cliente, mas tem as limitações que já postei aqui… Agora, a produtividade é muito alta. Fazemos telinhas em minutos…
Nem vou me ater a nomenclatura DTO que geralmente é usada em outro contexto. Todos os sistemas Swing que tenho participado, de uma forma ou de outra, enviam mensagens XML para o servidor. O uso de XML é apenas para facilitar a depuração da mensagens. Nem sempre elas representam objetos serializados.
Uma opção bem rápida de desenvolver um sistema assim é usar XML-RPC. Mas aí cai naquele tal de RPC que eu estou tentando me livrar. O ideal é usar mensagens assíncronas e se valer de técnicas de mensagens para garantir a atomicidade.
Depois que se sabe como fazer, o resto é tão simples ou mais do que o modo como faz. Em um dos sistemas em que eu trabalhei, que atendia a transações de cartão de crédito, o servidor era minúsculo pois TODAS as transações eram tratadas da mesma forma através do uso de reflection. A gente quando precisava criar uma nova transação o servidor já estava pronto. Neste caso, quando falo em servidor é apenas o carinha que recebe o HTTP dos clientes e repassa para o back end de acordo como este entende.
Depois que a gente se acostuma a trabalhar deste jeito, já tem tudo pronto para reusar em outros projetos.
Depois que a gente se acostuma a trabalhar deste jeito, já tem tudo pronto para reusar em outros projetos.
[]s
Luca[/quote]
Estou fazendo mais um Pet Project na ASPERCOM nos moldes do Hotmotors. É parte do meu próximo artigo. Estou fazendo em Swing e EJB 3, se você quiser podemos fazer também na sua abordagem para podermos ver as diferenças…
De qualquer forma, ainda acredito que seria melhor que no futuro pudéssemos manusear os entities na camada de apresentação sem limitações, navegando livremente nas associações, chamando operações de negócio e com uma performance excelente…
Outro ponto: acho um pouco “utopia” uma camada de apresentação totalmente desacoplada. Mudanças no domínio quase sempre forçam uma mudança na camada de apresentação, sempre tem um campo novo que entrou, ou uma associação que teve multiplicidade alterada. Por mais que a apresentação esteja desacoplada, ela vai ter alterações motivadas pelo domínio…
Concordo plemamente. As vezes, basta trocar o servidor para quebrar o acoplamento. Este é o motivo porque eu sempre digo: acoplamento mais fraco possível ao invés de fraco acoplamento ou desacoplamento total.
São 2 as frases chaves que todo desenvolvedor tem que ter na cabeça sempre:
“Coesão mais forte possível” e “acoplamento mais fraco possível”
O problema do uso dos EJBs no cliente é que quebra o acoplamento cedo demais. É claro que tem vantagens na velocidade de desenvolvimento. No dia em que o genesis rodar com EJB3 vai ficar moleza desenvolver um sistema assim. Mas eu ainda acho que seria sacrificar a qualidade da arquitetura em benefício da facilidade do desenvolvimento. Isto só poderia ser considerado bom se o cliente só pagasse pela arquitetura mais acoplada.
Acho que também fui mal entendido em algum momento aí para trás.
Não discordei do que vocês estão debatendo.
Rodrigo, não critiquei o OpenSessionInView. Pelo contrário, eu acho que é a melhor opção para um sistema web sobre http. E eu acho que se aplica bem ao seu sistema desacoplado baseado na troca de mensagens também Luca.
A discussão inicial era se o melhor é abrir uma sessão com o bd na hora que chega a requisição a ser tratada e deixa ela aberta até o momento em que a requisição acabou de ser tratada; ou se é melhor ter uma Fachada de métodos de negócio e controlar o ciclo de vida da sessão dentro da camada de negócios.
O grande problema de deixar a sessão restrita dentro da camada de negócios (eu nem gosto de fachadas procedurais, mas isso é outro assunto) é que a camada de negócios tem que retornar exatamente/somente aquilo que o sistema precisa para montar a resposta da requisição. O que inclui saber quais relacionamentos vão ser navegados para iniciá-los antes e não tomar LazyInitializationException, ou ainda mandar só o que vai ser usado através de uma estrutura-pseudo-orientada-a-objetos (DTO/VO). Saber o que você vai precisar usar mais para frente às vezes requer prever o futuro, e é disso que não gosto.
Mantendo a sessão aberta até o término do tratamento da requisição, não há a necessidade de se preocupar com isso. Eliminando grande parte da complexidade! A camada de negócio retorna algum(s) objeto(s) do seu domínio suficiente(s) para renderizar a view e você navega em relacionamentos a vontade.
E é aí que vem grande parte da confusão do tópico. Renderizar a view hoje, pode tanto ser criar um html para ser renderizado pelo browser, quanto montar um xml/json/texto para ser enviado como resposta ou mensagem assíncrona ao cliente remoto. O conceito de view que nós tinhamos até hoje já é @Deprecated. Eu estou hoje num projeto em que “renderizar a view” significa gerar um xml para ser digerido por Flash!
O que o Luca diz faz muito sentido. Não há motivos para não desacoplar a view nesse mundo da internet. Só que as views já são desacopladas, sejam elas um browser ou o seu eclipse.
ps.: é claro que eu só repeti tudo que estava escrito aí pra cima, do meu jeito!
É claro que se o cliente quiser lixo e só pagar por lixo, não há porque não lhe entregar lixo.
Mas se a gente puder fazer um tiquinho melhor também não é difícil. Já participei de um projeto com camada de apresentação feita em Swing em que havia uma outra interface via Struts :oops:
A equipe que desenvolveu o Struts não manjava nada de Swing e fizeram a parte deles como sabiam. Era uma coisa pequena a parte do Struts mas mostrou como foi bom fazer as coisas todas no servidor deixando o cliente Swing só como camada de apresentação e um mínimo de validação (repetida também no servidor por questões de segurança)
Aproveitando a discussão se eu tenho uma aplicação onde a seguinte estrutura é utilizada: view - bd - dao…
Porque eu não poderia controlar a transação no DAO, “já li aqui no forum que se eu controla-se no DAO iria ser complicado se eu fosse utilizar mais de um DAO, deram um exemplo aqui mesmo, salvar um pedido e depois os itens”.
porque ??? alguém poderia me explicar por favor ?
porque se você controla a transação no DAO, você salva um pedido, e depois dá erro ao salvar um item, você não tem como dar o rollback no pedido
Assim você não garante a atomicidade