Transporte em grande aplicação distribuida

Saudações :smiley:

Perdoem-me pela extensão do post, mas gostaria de expor algumas idéias à crítica pública:

Suponham o seguinte cenário:

  • Uma grande aplicação industrial, com um domínio de objetos de aproximadamente 300 classes diferentes persistida em qualquer BD relacional.
  • Previsão de carga de 10 a 500 usuários simultâneos.
  • Muitos objetos de várias classes são associados entre si formando grandes grafos que uma vez completos contém importantes e detalhadas especificações industriais.
  • É exigida uma interface gráfica Swing muito ágil para entrada de informações, que permita o “cadastramento” de dados para cerca de 80% dos objetos do domínio.
  • Ainda na interface Swing tais objetos serão associados a outros e persistidos formando grafos de várias proporções (desde pequenos com cerca de 5 objetos associados, até grandes como árvores de 10 níveis de profundidade e um total de 100 objetos) .
  • Não existem operações muito complexas envolvendo os objetos do domínio. A maioria delas são referentes a persistência ou atualizações de estados de objetos (exemplo: OrdemProducao: aberta, parada, encerrada, etc…), ou então duplicação dos grafos para que o usuário possa apenas alterar algumas informações, ao invés de entrar com todas elas novamente na interface (exemplo: duplicação de um objeto OrdemProducao, com todas as suas especificações industriais em que o usuário possa alterar apenas um detalhe como a Cor do produto, ou alterar totalmente todas as especificações).
  • O único complicador, é que tais operações são sempre atômicas. Por exemplo: ao persistir um objeto OrdemProducao, todos os objetos associados devem ser persistidos em grandes cascatas em uma única transação de BD.
  • A aplicação deve disponibilizar muitas consultas e relatórios que buscam e cruzam informações de objetos de todo o domínio.

Então …

  • Devido as necessidades de carga, optaria-se por J2EE e pelo app server JBoss que é freeware.
  • EJBs de sessão ofereceriam os serviços para persistência, consultas e demais processos de negócios.
  • Hibernate seria adotado como mecanismo de persistência, e seu HQL combinado com JXPath resolve as necessidades das consultas.

E finalmente os pontos mais importantes para discussão:

  • Devido as necessidades de “edição” dos objetos na interface Swing seria necessário transporta-los até o lado cliente, tornando o domínio de objetos distribuído e criando vários complicadores.
  • O primeiro problema seria que não poderíamos simplesmente serializar os objetos e despacha-los para o lado cliente, porque o tráfego na rede seria muito grande, já que a maioria dos objetos faz parte dos complexos grafos citados acima.
  • Uma possível solução seria implementar um mecanismo no lado servidor para “recortar” dos grafos somente os objetos que realmente precisam ser transportados. Isso seria feito com a incorporação de “proxies” ao domínio de objetos, ou seja, para cada entidade do domínio teríamos uma interface que seria implementada por uma classe e também por um proxy. Por exemplo: para representação de um “produto” no sistema, teríamos uma interface chamada Produto + uma classe chamada ProdutoImpl e + um proxy chamado ProdutoProxy. Assim, se tivéssemos que enviar um objeto OrdemProducao para o lado cliente e esse objeto tivesse associado a si um objeto Produto, poderíamos trocar a instância de ProdutoImpl por uma instância de ProdutoProxy, desacoplando o objeto do restante do grafo (que segue adiante a partir do produto).
  • Acredito que a primeira crítica a essa abordagem, seria a perda de tempo na implementação de tal mecanismo… Ainda porque, quando um objeto viajasse do lado cliente para o lado servidor, o processo inverso teria que ser feito para reintegrar o objeto ao domínio e persiti-lo quando for o caso.
  • Outra alternativa seria criar um domínio de objetos paralelo, composto apenas por Value Objects criados a imagem e semelhança do modelo real que serviriam apenas para transportar valores de um lado para o outro. Porém essa, parece ainda mais ineficiente, já que haveria a necessidade de passar via código os valores do objeto do domínio real para o VO e vice versa.
  • Seguindo a mesma linha, poderíamos pensar também em usar outros tipos de objetos para transportar os dados de maneira mais light. Como HashMaps e ArrayLists ou uma combinação deles, mas ainda haveria a necessidade de passar os valore dos objetos domínio “de” e “para” eles. Me parece inclusive, que uma técnica semelhante é usada em alguns frameworks para Web. Porém nesse caso, a auxência dos objetos inteiros pode complicar a implementação de um MVC…

Enfim, são muitos e sinuosos os caminhos possíveis…

Qual será o caminho das estrelas :?: E qual será a estrada para a perdição :?:

Anseio por críticas e sugestões…

Bem, não sou a pessoa mais indicada para te auxiliar em algo tão grande. Contudo, posso te aconselhar uma coisa: use xul, não swing :smiley:

www.xulplanet.com

Talvez esse seja um bom caso para uso de Naked Objects … deve facilitar a sua vida para escrever seus objetos de negócio completos sem se preocupar com as relações em um primeiro momento.

Realmente, estive lendo a documentação e o ObjectServer do NakedObjects parece resolver os problemas de transporte dos objetos, porém ainda seria necessário avaliar o consumo de banda dessas operações.

Porém, adotar algo assim me parece um pouco “radical demais” para o caso…

Obrigado pela dica.

Use proxies para todos objetos de forma ao transporte inicial deles ser rápido. Coloque os clientes funcionando como 1 cache pro servidor, ai é só algum algoritmo para caches distribuidos e pronto.
Outra dica importante é dividir o transporte dos teu objetos mais pesados de acordo com os use cases deles de forma a enviar apenas um estado parcial na maioria dos casos.

Você tem alguma idéia para uma implentação de tais proxies diferente da idéia que eu havia descrito no meu post inicial? Pergunto porque eu acho que seria muito improdutivo ter que escrever uma classe de proxy para cada classe do domínio.

:shock: Puxa, a primeira vista isso parece complexo! Você conhece alguma implementação disso na qual eu possa me basear? Ou talvez alguns artigos que discutam o assunto mais a fundo?

Estou tentando imaginar o que você quis dizer com “estado parcial”, mas nada me ocorreu até então…

Muito obrigado pelas contribuições,
Gabriel.

Voce pode usar Dynamic Proxies ou um framework de AOP, recomendo o segundo.

Procupe por implementações de caching distribuido como jcs, jbosscache, coherence, spirit cache, etc…
Procupe por algoritmos em http://citeseer.ist.psu.edu/cs.

[quote=“gcobr”]
Estou tentando imaginar o que você quis dizer com “estado parcial”, mas nada me ocorreu até então…[/quote]

Simples, voce tem 1 objeto com 4 atributos: A,B,C e D; no primeiro use case somene A e B são necessarios, nos demais C e D são usados. Logo somente A e B são enviados quando um dos dois for solicitado, evitando o envio inutil de C e D. Isso é muito util no casos de objetos enormes.

Para mais detalhes voce pode entrar em contato comigo (via private message inicialmente) que posso te prestar serviços de consultoria neste assunto.