Principais padrões J2EE para a construção de aplicações não distribuídas – Parte I

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (8)  (0)

Veja neste tutorial um resumo dos principais padrões de projeto, estratégias de projeto e conheça um pouco sobre Struts.

Neste tutorial mostraremos:

Ø       resumo dos principais padrões de projetos necessários à construção de aplicações J2EE profissionais não distribuídas,

Ø       algumas estratégias de projeto que devem ser consideradas e

Ø       como a framework Struts e seus derivados provêem suporte à maioria desses padrões e estratégias.

Introdução
A plataforma Java J2EE (Java 2 Enterprise Edition) surgiu com o objetivo de padronizar e simplificar a criação de aplicações empresariais. Para isso, propõe um modelo onde componentes J2EE (páginas JSP, Servlets, EJB's, etc) escritos pelos usuários da plataforma, podem fazer uso de serviços providos por esta, os quais simplificam sua implementação e possibilitam maior foco no negócio [SINGH02].

Um diferencial significativo na arquitetura proposta para a plataforma J2EE foi a iniciativa de enfatizar a utilização de padrões de projetos. Tais padrões trazem inúmeras vantagens na modelagem e implementação de um software:

·          possibilidade de projetar soluções mais rapidamente e com qualidade já que os padrões são soluções comprovadamente eficientes para problemas já conhecidos;

·          visam principalmente flexibilidade, organização e reaproveitamento de código, o que resulta em maior produtividade, qualidade e facilidade de manutenção das aplicações assim desenvolvidas.

Os principais serviços disponibilizados pela plataforma J2EE destinam-se a suprir as necessidades de aplicações empresariais distribuídas, isto é, aquelas que necessitam da flexibilidade de disponibilizar acesso à sua lógica de negócio e dados para diferentes tipos de dispositivos clientes (navegadores, dispositivos móveis, aplicações desktop, etc) e/ou para outras aplicações residentes na mesma empresa ou fora desta. A Figura 1.1 (extraída de [SINGH02]) ilustra um ambiente J2EE típico.

fig11padroes.JPG
Figura 1.1 : Ambiente J2EE.

Aplicações distribuídas são comumente compostas de uma camada cliente, que implementa a interface com o usuário, uma ou mais camadas intermediárias, que processam a lógica do negócio e provêem serviços à camada cliente, e outra, chamada de  Enterprise Information System ou EIS, formada por sistemas legados e bancos de dados. A infraestrutura oferecida pela J2EE possibilita que estas camadas,  possivelmente localizadas em máquinas diferentes, possam se comunicar remotamente e juntas comporem uma aplicação.

Um componente criado numa aplicação J2EE deve ser instalado no container apropriado. Um container é um ambiente de execução padronizado que provê serviços específicos a um componente. Assim, um componente pode esperar que em qualquer plataforma J2EE implementada por qualquer fornecedor estes serviços estejam disponíveis.

Um web container destina-se a processar componentes web como servlets, JSP's, HTML's e Java Beans. Estes são suficientes para criar aplicações completas que não necessitam ser acessadas por diferentes tipos de cliente nem tampouco tornar seus dados e lógica distribuídos. Já um EJB container destina-se a prover a infraestrutura necessária para a execução de componentes de negócio distribuídos. Um EJB (Enterprise Java Bean) é um componente de software que estende as funcionalidades de um servidor permitindo encapsular lógica de negócio e dados específicos de uma aplicação. Tal componente pode ser acessado de maneiras diferentes, por exemplo através de RMI, CORBA ou SOAP, o que possibilita que este seja utilizado por qualquer tecnologia que provê suporte a um destes padrões de comunicação e que seja localizado virtualmente a partir de qualquer rede TCP/IP.

A plataforma J2EE permite uma arquitetura flexível sendo que tanto o web container quanto o EJB container são opcionais. Alguns cenários possíveis podem ser observados na Figura 1.2.

fig12padroes.JPG
Figura 1.2: Cenários de aplicações J2EE.

O cenário que estaremos considerando neste trabalho é precisamente o ilustrado na Figura 1.3.

fig13padroes.JPG
Figura 1.3: Aplicação web J2EE em três camadas.

Como apresentado no livro [J2EETIP], uma aplicação web em três camadas é na maioria das vezes a escolha inicial para uma aplicação J2EE e é como implementar este tipo de aplicação que estaremos discutindo aqui. Nesta configuração, o container web encarrega-se de tratar tanto a lógica de  apresentação como a de negócios e veremos qual a melhor forma de organizarmos estas responsabilidades de forma a criarmos aplicações modulares, organizadas, com reaproveitamento de código e mais manuteníveis e extensíveis, ou seja, como criar aplicações profissionais neste cenário.

Neste artigo, discutiremos alguns padrões e estratégias de projeto que consideramos necessários à construção de aplicações J2EE profissionais não distribuídas. Basicamente, consiste num resumo de alguns dos padrões encontrados no livro [ALUR] acrescido de comentários baseados em nossa experiência prática no desenvolvimento destes tipos de aplicações. Muitas referências são feitas à framework Struts [STRUTS] e como esta implementa vários dos padrões e estratégias aqui apresentados.

 

 

Padrões de Projeto

A correta utilização de arquiteturas e padrões de projeto no desenvolvimento de softwares representa um importante ideal a ser alcançado por qualquer equipe que pretende produzir aplicações computacionais profissionais. Não basta aprender uma tecnologia, é necessário também conseguir projetar soluções com esta tecnologia. A definição de uma arquitetura, por exemplo, permite que tenhamos uma visão completa da aplicação, de quais são seus principais componentes, o objetivo de cada um deles e a maneira como se relacionam a fim de desempenharem suas funções. Quando utilizamos padrões, estamos levando em conta experiências de outros projetos de desenvolvimento, aumentando assim as chances de chegarmos em uma solução correta pois erros passados poderão ser evitados.

 

Em aplicações sob a plataforma J2EE não é diferente. Em geral estamos tão atolados no processo de compreensão dos serviços da plataforma, de suas APIs (Application Program Interface) e do negócio a ser resolvido que não dedicamos o tempo necessário para aprender a projetar soluções com a tecnologia. Segundo Booch [ALUR] “existe um buraco semântico entre as abstrações e serviços que a plataforma J2EE oferece e a aplicação final que será produzida com esta e os padrões de projeto representam soluções que aparecem repetidamente para preencher este buraco”.

 

Um padrão provê uma solução para um problema comum baseado em experiências anteriores comprovadamente eficazes. Dispor de um bom conjunto de padrões é como ter um time de especialistas sentado ao seu lado durante o desenvolvimento, aconselhando-lhe com o melhor do seu conhecimento. Boas práticas de projeto são descobertas pela experiência e levam tempo até se tornarem maduras e confiáveis. Um padrão captura essa experiência e serve para comunicar, de forma padronizada, o conhecimento que trazem. Dessa forma, os padrões, além de ajudarem os desenvolvedores e arquitetos a reutilizarem soluções tanto de projeto quanto de implementação, ajudam também a criar um vocabulário comum na equipe, diminuindo assim o esforço de comunicação.

 

Veremos agora um resumo dos mais relevantes padrões e estratégias de projeto para a construção de aplicações J2EE profissionais não distribuídas.

 

Arquitetura Dividida em Camadas

A plataforma J2EE provê uma clara divisão, tanto lógica quanto física, de uma aplicação em camadas. O particionamento de uma aplicação em camadas permite uma maior flexibilidade de escolha da tecnologia apropriada para uma determinada situação. Múltiplas tecnologias podem ser utilizadas para proverem o mesmo serviço possibilitando escolher a que melhor se adeqüa baseado nas características do problema em questão. Por exemplo, como pôde ser observado na Figura 1.1, é possível utilizar para a construção da camada cliente, quando um EJB container está sendo considerado, tanto páginas HTML e JSP como também um cliente desktop.

 

Como comentado anteriormente, existem situações onde a utilização de EJBs é desnecessária, a aplicação não necessita ser distribuída e apenas um subconjunto dos serviços disponíveis na plataforma atende aos seus requisitos. Dessa forma, nosso foco está na construção de aplicações web em três camadas, sendo a camada dos EJBs desconsiderada. Cada camada e suas responsabilidades são:

 

·          Camada cliente: é responsável por interagir e apresentar os dados aos usuários e por se comunicar com outras camadas da aplicação. Em geral é a única parte da aplicação com a qual o usuário tem contato. A camada cliente comunica-se com outras camadas através de interfaces bem definidas. Projetando desta forma, temos maior facilidade para adicionar novos clientes, contanto que estes estejam em conformidade com a interface para comunicação com as outras camadas. Em nossas aplicações o único cliente que consideraremos é o navegador web (browser). No caso da camada de Enterprise Java Beans estar presente, passa a ser possível, por exemplo, termos clientes como aplicações desktop escritas em Java e comunicando-se com esta camada via RMI (Remote Method Invocation) ou então aplicações escritas em outras linguagens e comunicando-se com esta via CORBA (Common Object Request Broker Architecture).

 

·          Camada web: é quem recebe e processa as requisições dos usuários através de um web container. É responsável por realizar todo processamento web, como hospedar páginas HTML, executar servlets e formatar páginas JSP a serem apresentadas pelos navegadores. Em nosso caso, é responsável também pelo controle do fluxo da aplicação e por processar toda a lógica do negócio, incluindo o gerenciamento de conexões com banco de dados e conectores para acesso a recursos legados.

 

·          Camada de banco de dados e sistemas de informação legados: tipicamente nesta camada estão incluídos sistemas gerenciadores de banco de dados, sistemas de planejamento de recursos (ou Enterprise Resource Planning (ERP)) e quaisquer sistemas legados. Com o apoio da API JCA (Java Connector Architecture) esta camada provê uma infraestrutura de software que mapeia dados e recursos de aplicações existentes dentro de projetos J2EE de forma padronizada.

 

A camada responsável pelo processamento dos EJBs é a Enterprise JavaBeans Tier. Esta fornece serviços,

implementados por um EJB container, para os EJBs. Alguns deles são: controle de transação, mecanismos de segurança, persistência, dentre outros. Estes serviços disponíveis facilitam a vida do programador, que fica livre da obrigação de ter que tratá-los, podendo se concentrar mais na implementação das funcionalidades inerentes ao seu negócio. Quando esta camada está presente, a lógica de negócio (toda ou parte desta) pode passar a ser implementada nos componentes de negócio distribuídos, ficando a camada web assim mais voltada à exibição dos dados.

 

Por fim, mantenha em mente que estas são divisões lógicas que servem principalmente para melhor estruturar uma aplicação. Com exceção talvez da camada cliente, não está implícito que cada camada esteja em localizações físicas diferentes. Nada impede por exemplo que o banco de dados esteja localizado no mesmo servidor que hospeda um web container numa arquitetura em três camadas, ou que tanto o web container e o EJB container estejam rodando na mesma máquina virtual Java. O importante é a divisão de responsabilidades que resulta das tecnologias separadas.

 

Model-View-Controller

Um dos principais padrões que utilizaremos para construção de nossas aplicações é o padrão MVC ou Modelo-Vista-Controlador (do inglês Model-View-Controller). Este padrão separa três formas distintas de funcionalidades em uma aplicação. O modelo representa a estrutura de dados e operações que atuam nestes dados. Em uma aplicação orientada a objetos, constitui as classes de objetos da aplicação que implementam o que quer que a aplicação tenha que fazer. Visões implementam exclusivamente a lógica de apresentação dos dados em um formato apropriado para os usuários. A mesma informação pode ser apresentada de maneiras diferentes para grupos de usuários com requisitos diferentes. Um controlador traduz ações de usuários (movimento e click de mouse, teclas de atalho, etc) juntamente com os valores de entrada de dados em chamadas à funções específicas no modelo. Além disso, seleciona, baseado nas

preferências do usuário e estado do modelo, a vista apropriada.  Essencialmente, estas três camadas abstraem: dados e funcionalidades, apresentação e comportamento de uma aplicação.

 

Os benefícios em usar o padrão MVC são:

 

·          Separação Modelo-Vista: separando o modelo da vista é mais fácil adicionar diferentes apresentações do mesmo dado, além de facilitar também a adição de novos tipos de visão a medida que a tecnologia evolui. Os componentes relativos ao modelo e visão podem ser projetados, desenvolvidos e modificados independentemente (com exceção das suas interfaces), melhorando a manutenibilidade, extensibilidade e testabilidade.

 

·          Separação Controlador-Vista: separar o controlador das visões permite maior flexibilidade para selecionar, em tempo de execução, visões apropriadas baseado no fluxo de trabalho, preferências do usuário ou estado interno do modelo, quando mais de uma estiver disponível. Por exemplo, se o nível de acesso, linguagem ou localização de um usuário determinar uma apresentação diferente, esta decisão é feita na camada de controle que retornará para este usuário a visão correta.

 

·          Separação Controlador-Modelo: separando o controlador do modelo temos como criar mapeamentos configuráveis de ações capturadas pelo controlador para funções no modelo. Estas configurações possibilitam, por exemplo, que uma mesma ação seja executada, para usuários diferentes, por funções diferentes.

 

Mais uma vez, a divisão de responsabilidades que resulta deste particionamento lógico possibilita uma melhor compreensão e organização dos requisitos da aplicação e facilita a implementação, manutenção e extensão dos mesmos. Nossas aplicações obedecerão a divisão dessas três camadas lógicas da seguinte forma:

 

·          A camada modelo será composta por um conjunto de classes de objetos com toda a implementação da lógica de negócio da aplicação. Os desenvolvedores Java responsáveis por criar estas classes o farão com ferramentas propícias a esta tarefa e pouco ou nenhum contato com os membros responsáveis pelo desenvolvimento das visões.

 

·          A camada de visão será composta por arquivos HTML, JSP, arquivos de imagens, arquivos multimídia, enfim, tudo que englobe o desenvolvimento de páginas web a serem apresentadas aos usuários. Como o objetivo de uma visão é tão somente apresentar os dados que vêm do modelo, teremos como premissa remover o máximo possível de código Java, isto é scriptlets, das páginas JSP.

 

·          A camada de controle determina o fluxo da apresentação, servindo como uma camada intermediária entre a apresentação e lógica da aplicação. Qualquer solicitação de um usuário é interceptada primeiro pelo controlador que pode, neste momento, realizar qualquer tipo de controle, como verificação de restrições de segurança, gravação de logs, etc. Depois disso dá-se início ao processamento da solicitação, provavelmente com o controle designando para classes auxiliares a execução do comando. Quando a execução termina o controlador escolhe, baseado no resultado e outras configurações, qual página retornar ao usuário. O controle centralizado deste fluxo traz inúmeras vantagens e veremos mais detalhes sobre este no padrão Front Controller.

 

Front Controller

Em geral qualquer aplicação, independente de plataforma, é projetada com um determinado fluxo de  operação em mente. Esperamos que os usuários interajam com a aplicação seguindo este fluxo, pois  cada etapa de uma operação tem um propósito a ser cumprido para que toda ela complete com sucesso. Não podemos, por exemplo, exibir detalhes do perfil de um usuário sem antes este ter sido selecionado.

 

Diferentemente das aplicações desktop, os programas baseados na web estão sujeitos a interrupções que podem ocorrer no fluxo esperado de operação. O usuário pode pressionar o botão de “Voltar” ou “Recarregar” do navegador, abortar prematuramente uma solicitação em andamento, abrir novas janelas a qualquer momento, resubmeter uma operação, etc. Nada disso ocorre numa aplicação tradicional desktop, onde o programador tem controle muito maior sobre o fluxo de operacionalização do programa. É de responsabilidade da aplicação web tratar estes inconvenientes e garantir que o fluxo e estado adequado da aplicação sejam mantidos.

 

Uma das maneiras de fazer isso é inserir o código necessário para efetuar esse controle em cada uma das páginas JSP. Esta abordagem tem dois sérios problemas. Primeiro, o código referente à lógica de  controle é misturado com o código da lógica de apresentação, dificultando a manutenção destas páginas. Outro problema está relacionado ao fato de que a disseminação da lógica de controle em múltiplas páginas JSP requer também manutenção em cada uma das páginas. Numa aplicação com dezenas ou centenas de páginas, sempre que essa lógica for alterada ter-se-á um grande trabalho para executar uma simples manutenção, já que o código de controle foi reaproveitado numa abordagem copia-cola.

 

Uma solução mais adequada para implementação da lógica de controle é a utilização de um ponto centralizado para receber e tratar as solicitações dos usuários. Isto é feito adicionando-se um controller ao projeto das aplicações. Um controlador, além de prover os benefícios comentados no  contexto do padrão MVC, possibilita a centralização do código referente ao controle do fluxo de  execução de uma aplicação reduzindo a quantidade de código Java (scriptlets) embutido nas páginas  JSP. Isto promove a reutilização de código e melhora o desenvolvimento e manutenção das páginas JSP, que passam a conter apenas código relativo a apresentação de dados.

 

Além destes benefícios, a centralização do acesso provida por um  controlador ajuda na implementação dos seguintes ítens:

 

·          controle de transações,

·          serviços de sistema comuns como acesso a banco de dados e serviços de autenticação e autorização,

·          acompanhamento das ações de um usuário através do site,

·          etc.

 

Cabe neste momento comentarmos sobre a framework Struts [STRUTS]. Esta é uma implementação  bastante completa e flexível de um front controller e MVC, além de disponibilizar recursos que ajudam   na construção da camada de visão e aplicar vários dos padrões e estratégias que discutiremos a seguir.

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?