No ultimo post o meu objetivo era discutir a melhor tecnologia de view e concluir que não ha a melhor e que o ideal – o esperado em uma implementação robusta – seria views tira-põe de modo a não amarrar o resto das camadas com a view.

Hoje existem algumas poucas tentativas para isto. A mais conhecida é o uso de REST. A ideia é ter um web server/container que provê respostas as URL. Então, um aplicativo independente pode ser criado para utilizar essas interações HTTP para produzir funcionalidade agregada e “bonita” naquilo que se está chamando de rich cliente (“cliente rico”). Ok. Só tem um detalhe. Se a aplicação quiser otimizar ou prover uma funcionalidade nova não é possível sem modificação da contraparte REST. Podemos argumentar que a otimização é um problema que pode ser deixado para ultimo e/ou não levado em consideração numa primeira analise. Afinal os browsers são otimizados paras as mesmas respostas HTTP sem saber bem o que vem do outro lado. Coisas como zipar o conteúdo ou controlar o cache de respostas dadas pelo servidor podem ser controlados pelo servidor e desabilitadas pelo browser. Funciona. Mas sempre tem aquele cookie que vc precisa aceitar. Ou seja, estado. O browser precisa armazenar estado para otimizar a comunicação.

Mas REST vai contra isto de estado. Ok. Neste cenário poderíamos implementar um UI em javascript e uma em Swing e tudo estaria correto do ponto de vista da independência parcial. O servidor é livre de prover mais funcionalidades a qualquer momento e o cliente de as usar. O cliente é livre de deixar o usuário brincar com o dados e janelas como quiser. Claro que o cliente não pode criar funcionalidade do zero, mas pode- por exemplo – fazer o mashup de vários servidores para chegar em um cliente interessante. Por exemplo, integrar o google maps com o REST de cadastro de lojas. O detalhe é que nestes mashups o cliente vira a aplicação, o servidor de dados REST é apenas um Banco de Dados virtualizado num URL. Esta é exatamente a arquitetura que o Android usa, com a diferença que os dados podem ficar no próprio aparelho. Mas vc é livre de usar os dados de um aplicativo em outro (dadas as permissões, etc…) Ou seja, as camadas do “DAO para baixo” são expostas como REST e as camadas para cima como uma aplicação diferente. O Business fica em algum lugar no meio. Podemos ter REST que salvam, validam, dão update, etc.. mas podemos deixar todas as regras de validação na aplicação e usar o REST como um dao burro. “Podemos” – não quer dizer que é a melhor forma ou a mais usada. Depende muito se os dados são read-only ou write-almost-never ou se é um serviço transacional pesado como são telas de cadastro.

Bom, isto é uma solução possível nos nosso dias. Passa por alguns pontos interessantes, mas não é bem o que eu estava pensando quando falei do padrão Bridge (Mediator). O padrão Mediator seria mais no nível do código/ bibliotecas/ camadas, à semelhança do JDBC por exemplo.  Pense assim, o JDBC está para o banco de dados como este mediador de UI está para  a ui. O “driver” seria a implementação da API do mediador para a tecnologia de view em causa. O “driver” deveria permitir três coisas básicas : dirigir o fluxo ,  coletar/apresentar dados, responder a eventos. Note-se que estes eventos, dados e diretor de fluxo são levantados pela UI verdadeira ( struts, jsf, etc… ) mas tudo é canalizado para este “driver” invertido” de forma que o mediator possa entender os dados e comunicar com o outro lado dos business.

Se você entendeu o que falei , vc deve estar pensando “mas isso é o que a action do struts faz”. Sim. É o que ela faz. Assim como o managed bean do jsf e outros objetos que cumpre este papel em outro frameworks. Estes objetos são um pouco business delegate ( porque contêm algumas regras de negocio) e um pouco view controler porque dirigem o fluxo.

As peças são mais ou menos obvias e se virmos com atenção estão presentes em todos estes frameworks “compativeis”. Para começar temos o Dispatcher. Este é o cara que trata a navegação. Começa com o próprio dispatecher da Servlet API pura até ao próprio struts em si mesmo. E todos os frameworks web usam isto, afinal tem que ser possível pular de um URL para outro dentro do servidor (forward) ou instruir o browser a pular para outro URL (redirect). Basta termos um objeto POJO -like que não use construtos muitocomplexos (apenas, por exemplo, simples strings ou enums de algum tipo ) para pular para outro “cena”. Este conceito de “cena” em vez de janela ou página ajuda a pensar que o usuário irá ver outra coisa, sem sabermos onde a irá ver.  Para pegar dados o velho padrão View Object é simples de usar e com os recursos de atuais é  o que já usamos. Se bem que adoramos usar as entidades de banco de dados para este fim, mas nada mais se trata do que capturar todos os parâmetros em um POJO e deixar o framework implementar os detalhes da copia, conversão, etc.. Para responder a eventos temos aquilo que definimos como “actions” que podemos entender como métodos em que o nome do método corresponde com a ação. Obviamente este mapeamento acontece na real implementação da view, mas os métodos do mediador são sempre os mesmos.

Quase todos os objetos que identificamos como “actions” se comportam assim e têm estes acessos a API semelhantes. Se enxergarmos do ponto de vista do mediador para fora em direção ao browser iremos enxergar que um conjunto de padrões de uso se repetem, da mesma forma que enxergamos do business em direção do DB que muitos padrões de uso se repetem. Quando estamos na camada de business e olhamos o banco de dados que fica na camada de recursos e nada mais é que o um arquivo glorificado, pensamos na camada de integração onde ficam coisas como o JDBC, JPA e companhia. Quando olhamos da  camada de business em direção ao usuário que está usando a camada cliente pensamos na camada de apresentação no meio.  Normalmente pensamos no cliente como o browser e na camada de apresentação como o struts/spring MVC/ JSF. Contudo sabemos bem que devido a coisas como Ajax, REST, javascript estas partes ( browser – framework web) não são separáveis. Não com um corte limpo.  Mas se pensarmos que na realidade “browser+framework web” são o cliente ficamos com um camada inteira para desacoplar e manter desacoplada. O que significa muito espaço de manobra. Afinal a camada de apresentação não deve depender do cliente (camadas são independentes e se B sucede a A , B não pode depender de A.)

Dito de outra forma. Ou todo o mundo está violando a separação de camadas por fazer a camada de apresentação conhecer o cliente ( o que é sacrilégio já que ninguém aceitaria fazer depender o DAO do business) ou ninguém está usando a camada de apresentação de fato.  Claro que sabemos que a primeira é verdade já que todos assumimos usar duas camadas e todos assumimos que a nossa implementação web depende do browser, mas podemos pensar que afinal não estamos violando nada e usando a segunda.

Para os mais atentos deve ficar o gosto de que estamos repetindo as mesmas “ações” nesta camada de apresentação que repetimos nos frameworks web. Bom, no estado que é hoje sim. Afinal as responsabilidades são semelhantes. Mas se pensarmos na implementação da camada de apresentação como a verdadeira implementação destes padrões ( view object, dispatecher, observer) e as tecnologias web como meras canalizações – meros “drivers”- , então tanto faz à camada de apresentação se o usuário apertou um botão no browser ou uma imagem no swing (ou vice-versa) : o que interessa é a intenção chamada “salvar”  ou “calcular” etc…Afinal são estas intenções que o sistema entende (como no caso do REST ele só entender update, post, get, put, delete) e tanto faz , quem, como ou quanto foram chamadas.

Este design ainda não responde a todas as questões como “como populo um table a partir de uma tabela” e como mudar o struts pelo ZK, por exemplo, mas acho que abre uma porta sem realmente inventar nada e apenas vendo o que temos com outros olhos. E com essa porta começar a pensar como seria a implementação de algo assim.

Aguardo as vossas opiniões sobre o conceito e comentários.

 

 

Comente

Scroll to Top