[ Parte II - Experiência Pessoal ]  
Parte I - Especificação Técnica do Projeto

Aluno: Stefan Neusatz Guilhen
Orientador: Prof. Dr. Fábio Kon

Introdução

 O Jefras é um sistema que visa facilitar o processo de compra de livros para a biblioteca do IME. Atualmente, esse processo é um tanto quanto burocrático. Os professores responsáveis pela lista de compras de livros se vêem envoltos por uma papelada que em nada facilita o processo de decisão sobre quais livros devem ou não ser comprados. São tantos papéis, que não é possível ter controle sobre qual livro foi pedido há muitos anos e qual foi pedido recentemente. Pior, muitas vezes, aquele livro pedido há mais tempo nem é mais de interesse e, ainda assim, está na lista de livros a serem comprados.

O processo de compras de livros atualmente
 Atualmente, existe um professor responsável pela lista de compras de cada departamento, que é encarregado de enviar uma lista dos livros que foram pedidos pelos professores daquele departamento. Na biblioteca, os livros são selecionados dessa lista manualmente e a bibliotecária inicia a compra propriamente dita. É feita uma pesquisa de preços de livros nas livrarias e, depois, é enviado o pedido de compras. Após alguns dias, os livros chegam até a biblioteca. Pode acontecer de não chegar algum livro pedido, por estar esgotado, ou por alguma outra razão. Essa é uma descrição resumida de como é o processo de compras de livros atualmente.

O sistema Jefras
 O Jefras é um sistema cujo desenvolvimento teve início em 2002, no curso de MAC445 – Laboratório de Programação XP.
Infelizmente, ao fim da disciplina, o sistema não estava pronto para produção. O trabalho de formatura foi, então, dar continuidade a esse projeto, implementando funcionalidades que faltavam e adicionando outras novas.


Objetivos (Escopo)

 O objetivo do sistema Jefras é facilitar o processo de compras de livros atualmente. Ele será responsável por registrar os pedidos de livros de cada professor, registrar votos de alunos em livros e gerar uma lista de livros automaticamente, baseado em alguns critérios:

 - a importância (prioridade) do livro para o professor que fez a sugestão;
 - o número de votos não docentes;
 - o preço do livro.

 Utilizando esses critérios e o valor da verba disponível para a compra, a lista de compras será gerada automaticamente. A importância de cada um dos critérios na geração da lista é configurada por um administrador do sistema.

 A lista de compras gerada pode ser alterada pelo administrador, que adiciona e remove livros. O sistema controla quando a lista entrou em compras, quando os livros chegaram à biblioteca, e, se por algum motivo, como indisponibilidade, quais livros não foram entregues.

 Os usuários são notificados por e-mail a respeito das várias etapas do processo. Por exemplo, um usuário que votou em um livro é notificado quando ele foi enviado para compra, sabe a data de previsão de chegada, é notificado caso ele esteja esgotado e etc.

 O sistema faz também a busca automática de preços dos livros no site da Livraria Cultura.

Funcionalidades

 Por ser um projeto do curso de XP, o Jefras teve as suas funcionalidades escritas em story cards. Para quem não está familiarizado com XP (eXtremme Programming), story cards são cartões de papelão nos quais os usuários escrevem “histórias”, descrevendo como vão utilizar o sistema. Cada “história” representa uma funcionalidade a ser adicionada ao sistema. Para visualizar os cartões que descrevem as funcionalidades do Jefras, visite a página de XP de 2002.

  Também é possível dividir as funcionalidades do Jefras em categorias de usuário. Para cada tipo de usuário, existe um conjunto de funcionalidades disponíveis. Seguem, nos próximos tópicos, as funcionalidades do sistema classificadas dessa forma.

Convidado
 O convidado é um usuário que não tem senha nem login. Ele pode:
 - votar em um livro;
 - visualizar a lista de livros cadastrados no sistema;
 - visualizar as listas de compras do sistema.

Professor
 O professor possui senha e login. As funcionalidades que o sistema provê para essa categoria de usuário são:
 - registro de sugestão de um livro com uma prioridade;
 - alteração da prioridade dada a uma sugestão;
 - cancelar sugestões;
 - editar os seus dados pessoais cadastrados no sistema, bem como a senha;
 - visualizar a lista de livros cadastrados no sistema;
 - visualizar as listas de compras do sistema.

Administrador
 O administrador é o usuário que controla as funções vitais do sistema. As funcionalidades disponíveis para o administrador são:
 - cadastro de usuários no sistema;
 - alterar o preço de um livro;
 - configurar a importância de cada critério utilizado para a geração de listas de compras;
 - geração automática de listas de compras, através da verba disponível e dos pesos dos critérios;
 - editar listas de compras;
 - remover listas de compras;
 - notificar o sistema de que foi enviado um pedido de compra para aquela lista;
 - notificar o sistema de que foi entregue o pedido de uma lista;
 - notificar o sistema de que um livro não chegou e explicar a razão disso;
 - visualizar a lista de livros cadastrados;
 - visualizar as listas de compra;
 - fazer pesquisas de preços de livros no site da Livraria Cultura.


O Sistema Jefras no Início

 Para detalharmos mais facilmente o que fizemos, vamos primeiramente descrever como era o sistema Jefras no começo do ano.

 O Jefras originalmente utilizava o arcabouço Prevayler[1] para fazer persistência de dados. Essa ferramenta realiza a persistência dos objetos Java de forma "transparente" para o programador, sem o uso de um banco de dados, registrando seriação desses objetos em arquivos no disco. Para utilizar o Prevayler, você deve implementar uma classe (PrevalentSystem), que será o seu banco. Ela deve conter referências para todos os objetos que devem ser persistidos, de modo que, quando ela for seriada em um arquivo, todas as referências também o serão. Sempre que for necessário alterar os dados persistidos, é preciso implementar uma interface Command:

public interface Command {
  public Serializable execute(PrevalentSystem system) throws Exception;
}

 No método execute, é recebida uma referência para PrevalentSystem, e é nesse método que deve ser alterado o banco. Essa forma de encapsular um código qualquer em um objeto é uma implementação do Padrão Command (233)[2]. O Prevayler grava os dados do PrevalentSystem em um certo intervalo de tempo. E, sempre que um comando tiver que ser executado, ele é seriado em um arquivo de log do Prevayler. Desse modo, caso o sistema saia do ar por algum motivo, o Prevayler restaura o PrevalentSystem que foi seriado em um arquivo, e executa cada comando que foi gravado no log desde a última vez que o objeto banco foi salvo. Um comando no Prevayler é uma transação. Caso se deseje colocar vários comandos dentro de uma transação, não seria possível. A única solução seria criar um comando que executasse o mesmo que esses comandos executam.

 No Jefras, dados do banco são manipulados e alterados o tempo todo. Praticamente qualquer coisa que o usuário fizer na tela resulta em alterações no banco. Isso significa que quase toda a lógica do Jefras teria que ser implementada em comandos.

 E era assim que estava a arquitetura de classes do Jefras: uma arquitetura monolítica, composta de mais de 20 classes comandos, além de uma classe que seria o PrevalentSystem. Essa classe (que persistia todos os livros registrados no sistema, todos os professores, e etc) era um tanto extensa. Além de métodos relacionados à persistência de objetos, existiam métodos para ordenação de livros, que nada tinham a ver com a função da classe: referenciar objetos a serem persistidos.

 Além dessas classes relativas à persistência, havia as classes das entidades que tinham que ser persistidas no sistema: Book, Professor, Guest, Admin, Classification e etc. Cada uma delas possuía um conjunto de exceções internas. Havia uma exceção para cada campo que fosse inválido dessa classe. Por exemplo, para Book, tínhamos: Book.InvalidISSNException, Book.InvalidTitleException, Book.InvalidPublisherException, Book.InvalidEditionException, e assim por diante. Os construtores faziam a validação de cada atributo, e lançavam mais de cinco exceções. Algumas classes possuíam métodos estáticos que validavam outras classes. Por exemplo, Book tinha um método validateProfessor, que o construtor de Professor invoca para fazer validação.

 Os comandos eram invocados diretamente das páginas jsp. Nessas páginas, exceções como as de validação eram tratadas. Em alguns pontos, o catch era vazio, em outros, a exceção era impressa na tela.

  Existia também um pacote de testes, que possuía testes apenas para verificar se o construtor de cada entidade lançava cada uma daquelas exceções corretamente. Havia também uma servlet (e algumas classes auxiliares), denominada JefrasServlet, que direcionava o browser do usuário para a página correta, de acordo com o endereço pedido. Essa servlet era também responsável por inicializar o Prevayler. Além disso tudo, existiam classes que geravam a lista de compras.

O que foi feito

 No início do ano, tomamos familiaridade com a regra do negócio que o sistema se propõe a resolver. Estudamos como o sistema tinha sido desenvolvido até então, e tomamos conhecimento de quais ferramentas tinham sido utilizadas para isso.

Primeira Refatoração
 Como o sistema apresentava uma arquitetura de classes bastante desorganizada, o primeiro passo seria, sem dúvida, refatorá-lo. Desse modo, seria muito mais fácil implementar as funcionalidades restantes. Essa foi a etapa mais longa do processo.

 Fizemos uma classe para ser persistida (PrevalentSystem) que era independente do tipo de objeto a ser persistido, que, por sua vez, tinha que implementar somente uma interface que desse acesso a sua chave primária. Era possível criar “tabelas”, persistir objetos, fazer buscas (através de uma linguagem definida em objetos muito próxima de SQL), e até alterar os objetos persistidos. Essa classe apresentava uma coleção de comandos internos, que alteravam os objetos, de modo que pudemos remover todos os comandos do sistema. Era possível fazer atualizações de qualquer atributo de qualquer objeto retornado por uma expressão de busca. Isso nos ajudou a diminuir o número de classes pela metade. Essa classe também era responsável por fazer a sua própria inicialização, que tínhamos removido de JefrasServlet.

 À medida que novas alterações eram feitas, testes eram escritos para verificar se funcionavam corretamente.

 Havia um outro problema: toda a lógica de negócios estava nas páginas jsp. Criamos um pacote para colocar classes que implementavam as regras de negócio. Após remover as regras de negócio nas páginas jsp, já tínhamos uma primeira versão do sistema funcionando.

Transição para J2EE
 Depois de ser feita a primeira grande refatoração do sistema, começamos a implementar os story cards que faltavam. Durante isso, mais refatorações foram feitas ao sistema.
 No decorrer do processo, começamos a ter problema com o Prevayler. A primeira coisa que notamos era o problema com relacionamento entre classes. Suponha que um professor P é gravado no sistema através de um comando C1. Como C1 contém uma referência a P, quando C1 é gravado em um arquivo, é gravada uma cópia de P. Depois disso, o professor P vota no livro B. Para isso, o sistema verifica se B não está cadastrado no sistema. Suponha que B não está cadastrado. Então, é executado um comando C2, que registra o livro B no sistema. Após isso, é necessário registrar o voto do professor P no livro B. Isso é feito através de um comando C3, que persiste um voto. Esse comando tem uma referência para o professor P e uma para o livro B. Desse modo, o log do Prevayler ficaria dessa forma:

 C1: persiste P na tabela “professor”.
 C2: persiste B na tabela “book”.
 C3: persiste o voto V, que têm uma referência a B e uma a P, na tabela “vote”.

 Se desligarmos o sistema após essas operações, no momento de colocarmos o sistema no ar existirão duas cópias do professor P e duas do livro B. Veja por quê: cada registro de um comando seriado é uma “foto” daquele comando e dos objetos para os quais referencia. Primeiramente, o comando C1 é desseriado. É criada, então, uma instância do comando C1 na memória, que contém uma referência para um objeto professor P’, que também foi carregada na memória utilizando a versão seriada do professor P. Esse comando é executado, o que adiciona o professor P’ na tabela “professor”. O mesmo é feito com C2. É criada uma instância de C2 na memória, baseada na “foto” tirada de C2 anteriormente, que está registrada no log. Isso leva à criação de um livro B’, com os mesmos atributos e dados que tinha o livro B, antes de o sistema ser desligado. Em seguida, é criada uma instância do comando C3 na memória, apontando para uma instância de um voto V’ que também é criado, contendo os dados do voto V original. Esse, por sua vez, tem uma referência ao professor P e ao livro B, que também são instanciados na memória, criando um professor P’’ e um livro B’’ na memória, com os mesmos dados que havia no professor P e no livro B.

Desse modo, existem duas cópias do livro B e do professor P quando o sistema é carregado na memória. Se você perguntar ao livro B’ se ele foi sugerido por alguém, o resultado será não, já que é o livro B’’ que contém o registro do voto feito pelo professor. Apesar de B’ e B’’ conterem o mesmo ISSN, o mesmo título e, assim por diante, são instâncias diferentes na memória. É B’ quem está registrado na tabela “book”, e não B’’.

 Resolver isso parecia fácil. Ao invés de gravar uma referência a B e uma a P no comando C3, poderíamos gravar as chaves primárias desses objetos. Mas o que parecia uma solução simples tornou-se muito difícil de ser implementado. Os comandos da classe persistida poderiam gravar qualquer objeto, e como saber se esse objeto referencia um objeto que já está persistido no banco de dados, para evitar a criação de uma cópia do mesmo no sistema? Tentamos muitas soluções, mas vimos que estava ficando complicado e difícil, e nenhuma solução parecia realmente boa.

 Outro problema com o qual teríamos que lidar era a mudança de classes. Em Java, se é feita a seriação de um objeto em um arquivo, e a sua classe é alterada, não será possível restaurar a instância que foi gravada no arquivo. Isso significa que, se em algum momento tivéssemos que alterar a classe Book, por exemplo, para gravar mais algum dado, não seria possível obter os dados que estavam no banco antes dessa alteração. O Prof. Dr. Fábio Kon sugeriu que fizéssemos uma rotina que convertesse os objetos seriados para a nova versão da classe sempre que fosse necessário, mas isso parecia muito difícil. Não conseguimos encontrar um modo de fazer isso, e o tempo estava começando a ficar curto.

 Além disso, havia momentos em que queríamos que um conjunto de comandos fosse tratado como uma transação. Por exemplo, não queríamos que o comando C2 acima seja efetuado se o comando C3 for cancelado. Afinal, qual o sentido de existir um livro cadastrado que nunca foi sugerido por ninguém? Mas, com o Prevayler, como já foi dito, isso não é possível. Um comando é uma transação. Teríamos que agrupar nossos comandos em um único comando para fazer transações, de acordo com a necessidade da lógica de negócio que estivéssemos implementando.

 Perdemos muito tempo tentando suprir as deficiências do Prevayler, até que chegou um ponto em que se tornava claro: não daria para continuar utilizando essa ferramenta. Ela não se adequava à complexidade do sistema que estávamos desenvolvendo. Fizemos a transição do sistema para J2EE, que provê uma camada de persistência transparente, com suporte a relacionamentos entre objetos e a transações. Com isso, diminuímos o número de classes do sistema consideravelmente.

 Após fazermos a transição das entidades, fizemos a transição das nossas classes eram responsáveis pelas regras de negócio para session beans.

  As principais funcionalidades que não tinham sido implementadas foram adicionadas ao sistema e, atualmente, estão em fase de teste. Existem 127 métodos de teste, todos executando, mas esses testes ainda não cobrem todas as regras de negócio.

Validação de Dados
 A forma como era feita a validação dos dados digitados pelo usuário também foi substituída. Como citamos anteriormente, existia uma exceção para cada campo de cada entidade. Isso era ruim. Eliminamos essa exceção, e implantamos um sistema de validação muito mais limpo, baseado em um padrão apresentado no PLoP[3] 2002, denominado ValidationStrategy[3]. A nossa solução para validação será detalhada na seção Arquitetura: Padrões Utilizados: ValidationStrategy.

A camada Web
 O próximo passo foi a camada web. A interface com o usuário, feita em jsp, estava muito simples. Além disso, faltavam telas cruciais para o sistema, como por exemplo, uma tela para edição de listas de compras. Mas sabíamos que páginas feitas puramente em jsp não eram a melhor solução. Precisávamos de algo que provesse um modo mais sistemático e modularizado de desenvolver páginas web. Para isso, utilizamos o Struts[4], uma ferramenta do projeto Jakarta que modulariza a interface gráfica em M-V-C (Model - View - Controller).

 Essa arquitetura de interfaces gráficas com o usuário é bastante conhecida, e muito útil. A interface com o usuário é dividida em três camadas:
 - Model: esse é o modelo do sistema. É a parte funcional do sistema que manipula os dados de acordo com as regras de negócio. Como já foi dito, essa parte do sistema foi feita em J2EE.
 - View: essa é só a janela do usuário. É somente o que ele vê. Essa parte do sistema não possui lógica alguma. No Struts, as Views são páginas escritas em jsp e o Form (uma classe que armazena todos os dados digitados nos formulários das páginas).
 - Controller: o controller deve ser acoplado à view, e é ele que pede para o modelo executar algum processo sempre que o usuário clicar em um botão, ou executar qualquer outra ação na interface gráfica. É o controller que sabe a função de cada elemento mostrado na view. Ele sabe para que serve cada botão, campo de texto e outros elementos exibidos na view. No Struts, o Controller é a Action.

  Como o Struts utiliza essa arquitetura, é muito mais fácil editar uma tela sem alterar a sua lógica. A lógica da interface fica desacoplada da própria interface com a qual o usuário tem contato. Para ganhar maior flexibilidade, implementamos uma arquitetura reflexiva para trabalhar com o Struts. A Classe JefrasActionRoot é superclasse de todas as demais actions do sistema e invoca os métodos de suas subclasses usando reflexão. Dessa forma, quando o usuário executa alguma ação em uma página como, por exemplo, pressionar um botão, um javascript coloca na requisição, que está sendo enviada, o nome do método a ser invocado para tratar a interação com o usuário.

 Como cada página está vinculada a uma Action e a um Form, o próprio framework se encarrega de encontrar a Action que será responsável por tratar a requisição. Assim, a classe JefrasActionRoot obtém, a partir da requisição, o nome do método a ser invocado e realiza a invocação do método, usando o mecanismo de reflexão. Essa superclasse também recebe as exceções que forem lançadas pelo sistema, extrai suas mensagens e as formata para exibição na tela.

 Todas as páginas do sistema foram refeitas para utilizar as tags do Struts e tirar o código Java que estava impregnado. Os menus de navegação também foram refeitos com o objetivo de melhorar a navegação dos usuários. Antes, a tela inicial do sistema exibia todos os links possíveis na barra de navegação e quando o usuário clicava sobre um link que exigia autenticação, a tela de login era exibida. Isso foi modificado. Hoje, a tela inicial exibe somente os links comuns a todos os usuários e um campo de login. Depois que um usuário se autentica, sua barra de navegação é modificada para exibir os links aos quais ele tem acesso.

 Todas as mensagens e textos exibidos pela parte web da aplicação utilizam um catálogo de mensagens (arquivo de propriedades, que mapeia uma chave em um texto descritivo). O objetivo é facilitar a internacionalização do sistema. Por exemplo, para exibir os textos em inglês, basta copiar o arquivo de propriedades para um arquivo com o mesmo nome seguido de _en (isto é, JefrasWebResources_en.properties) e traduzir os textos associados com as chaves para o inglês. O Struts identifica o locale do usuário e seleciona o arquivo properties, de acordo com a extensão do locale.

Conclusão
 Foi dada continuidade ao projeto Jefras. Quase todos os cartões restantes foram implementados (faltaram alguns que dependem do banco que está sendo desenvolvido pela turma de laboratório de banco de dados deste ano), e outras funcionalidades foram adicionadas ao sistema.
 Desse modo, podemos concluir que o sistema original foi totalmente refatorado, e foram utilizadas outras tecnologias, que acreditamos se adequarem melhor ao sistema.


Metodologia

 O modo em que desenvolvemos o Jefras foi um pouco caótico. Fazendo estágio e faculdade, não tínhamos tanto tempo quanto gostaríamos. Tínhamos que improvisar. Trabalhamos separadamente em casa, à noite nos dias de semana. E, quando tínhamos alguma janela no horário da faculdade, programávamos em dupla, como é feito em XP. Mesmo quando desenvolvíamos o sistema em separado, sempre tomamos juntos as decisões, expondo abertamente as nossas idéias.
 Utilizamos testes durante o desenvolvimento inteiro, porque achamos que é muito importante validar a correção do sistema.
 No decorrer do processo, foram feitas algumas reuniões com o Prof. Dr. Fábio Kon e os clientes da biblioteca. Mas, infelizmente foram poucas as reuniões, devido à baixa disponibilidade do nosso horário.

Arquitetura

 A arquitetura principal do Jefras é uma típica arquitetura baseada na plataforma J2EE:

Arquitetura do sistema

• O cliente interage com o sistema utilizando o browser. Tipicamente, não haverá processamento no lado cliente, a menos que a aplicação seja composta por applets. Como no Jefras não existem applets, a máquina cliente não executa nenhum processamento.

• As requisições dos clientes são transportadas via http até o servidor web que irá tratá-las. Como estamos utilizando a plataforma J2EE, nosso servidor web tem que saber como lidar com servlets e páginas JSP, para construir a página de resposta que será enviada ao cliente. Escolhemos o servidor Apache Tomcat, um software de código aberto que implementa a especificação de servlets e JSP.

• As actions do framework struts se comunicam com os componentes que são responsáveis pela lógica de negócios (SessionBeans) usando o protocolo RMI/JRMP. As sessions são localizadas através do serviço de nomes JNDI (Java Naming and Directory Interface).

• As session beans implementam a lógica de negócio e invocam os entity beans para realizar a persistência dos dados. O ambiente de execução desses componentes é fornecido por um servidor de aplicações J2EE. Os entity beans realizam a persistência transparente dos dados em uma base de dados. O servidor escolhido foi o JBoss, uma implementação gratuita e de código aberto da especificação J2EE.

Padrões utilizados

 Seguem os principais padrões que utilizamos para desenvolver o Jefras.

EJBHomeFactory[5]
 Esse padrão provê uma maneira simples e eficiente de abstrair a complexidade de se fazer a busca de interfaces Home utilizando o JNDI. Uma única classe do sistema conhece em qual máquina e em qual porta está rodando o serviço de nomes. Dessa forma, se o serviço de nomes for movido para outra máquina ou para outra porta, apenas uma classe terá que ser modificada.
 Além disso, esse padrão permite um ganho de eficiência se um pool das interfaces Home que foram obtidas for construído dentro do EJBHomeFactory. Através desse pool são obtidas as interfaces Home para o sistema, sem que seja necessário utilizar o JNDI, ou seja, sem ter que fazer uma nova chamada remota para obter as interfaces.

ValidationStrategy[3]
 
Esse padrão já foi citado anteriormente, e foi apresentado no PloP 2002. Ele prega que é melhor deixar a validação de um objeto encapsulada em uma única classe. Desse modo, a validação deve ser delegada para essa classe. Deve existir uma classe de validação para cada entidade do sistema.

 Esse padrão é compatível com qualquer tecnologia e facilita bastante o encapsulamento do código. Mas, infelizmente, o escopo do padrão não incluía como notificar aplicações clientes de que um objeto foi considerado inválido pelo sistema. Desse modo, decidimos adaptá-lo para satisfazer as nossas necessidades.

 Criamos uma exceção, InvalidFieldException, que era lançada quando um objeto fosse invalidado. Também achávamos que a lógica de validação de um campo deveria estar em um único objeto, que tivesse uma forma de se representar textualmente. Ou seja, um único objeto encapsula a expressão “x != null && x.length() > 3” e a sua representação textual: “O campo x deve ter pelo menos 4 dígitos”. Esse objeto foi denominado FieldValidation. Uma validação de um objeto seria, então, constituída de uma coleção de FieldValidations (um para cada campo do objeto a ser validado). Desse modo, existe um objeto Validation para cada entidade do sistema, e o seu método validate lança InvalidFieldException, caso um ou mais atributos do objeto passado como argumento sejam considerados inválidos. Essa exceção contém uma coleção dos FieldValidations que não validaram o objeto. Existem também objetos Validation especiais para criação de entidades no sistema. Esses, além de validarem coisas como “senha deve ter pelo menos 4 dígitos”, validam unicidade de objetos no sistema, impedindo que, por exemplo, sejam criados dois usuários com o mesmo login no sistema.

 Isso facilita bastante o desenvolvimento do código. Note que só existe uma única exceção a ser tratada: InvalidFieldException. Se iterarmos por cada FieldValidation que ela contém, poderemos obter a mensagem de erro a ser exibida para o usuário em uma interface gráfica. Como entendemos que a mensagem de erro a ser exibida para o usuário final não pode ser parte do modelo, pretendemos substituir a mensagem de InvalidFieldException por uma chave do tipo “String”. O valor equivalente a essa chave será colocado em um catálogo. Isso permitirá que o sistema seja utilizado em várias línguas diferentes. Podemos ter uma mensagem para aquela chave em um catálogo para a língua portuguesa, e uma mensagem para a mesma chave no catálogo da língua inglesa.

TransferObject[6]
 É considerada uma boa prática fazer com que as entidades de um sistema J2EE sejam interfaces locais, que não podem ser acessadas remotamente. Se uma entidade for acessível remotamente, os dados do sistema poderiam ser alterados por aplicações clientes, o que se configura como uma falha de segurança e péssima prática de programação.

 Apesar disso, deve haver um modo de transferir os dados contidos em uma entidade para aplicações clientes. Esse padrão sugere que, para cada entidade, seja criada uma classe que contenha os seus dados, e que seja seriável para ser transmitida remotamente.

  Assim, para que a camada web tivesse acesso aos dados do sistema, as sessions se comunicam com aplicações clientes através de TransferObjects, que contém os dados manipulados pelo sistema. Existe um TransferObject para cada entidade no sistema.
Isso facilita muito a interação com aplicações clientes. As sessions, apesar não poderem se comunicar com aplicações clientes utilizando entidades como abstração, não precisam manipular os dados diretamente. Os TransferObjects provêem esse nível abstração. Um exemplo que torna a utilidade desse padrão mais clara é: para cadastrar um livro, ao invés de uma session receber ISSN, título, autores, editora e assim por diante, basta receber um TransferObject com todos os dados necessários.

Model – View - Controller
 MVC é uma solução arquitetônica muito utilizada para interfaces gráficas, mas não é considerado um padrão. Apesar disso, colocamos MVC aqui, por ser uma solução que engloba um grande conjunto de padrões. Um dos mais importantes utilizados pelo MVC é o Strategy (315)[2], no qual podemos alterar a lógica de um sistema trocando apenas uma classe, que encapsula um algoritmo. No MVC, podemos pensar no Controller como uma estratégia. Se trocarmos o Controller de uma página, as respostas da página aos comandos do usuário podem ser alteradas.
Não vamos nos estender mais nesse tópico, já que o MVC foi detalhado em O que foi feito: A camada Web.


Ferramentas Utilizadas

 As principais tecnologias e ferramentas que utilizamos para desenvolver o sistema Jefras foram:

 - J2EE: Java 2 Platform, Enterprise Edition
 - JUnitEJB: extensão do JUnit, adiciona suporte a EJBs.
 - JBoss: servidor de aplicação para J2EE.
 - Struts: projeto do Jakarta, é um arcabouço que fornece suporte à arquitetura Model2 (uma variação da arquitetura Model-View-Controller), para páginas feitas em jsp.
 - Tomcat: servidor web de código aberto que implementa a especificação de servlets e JSP.
 - Eclipse IDE: ambiente para desenvolvimento de aplicações.


Trabalho Futuro

 Apesar de o ano estar acabando, pretendemos dar continuidade ao projeto. Muito foi feito e o sistema se apresenta pronto para ser colocado em produção. Contudo, faltam muitas coisas a fazer, como desenvolver uma documentação para o usuário.
 Recentemente, o Jefras foi adicionado ao projeto arca. Devido a isso, pretendemos mudar o nome do projeto para o nome de algum animal, seguindo o padrão de todos os projetos arca. Em breve, isso será feito e será lançada a primeira release do sistema.
 Esperamos que o Jefras seja realmente útil para a biblioteca do IME, o que será a maior recompensa do esforço empregado durante esse ano.


Bibliografia e Referências

 1 - Prevayler - www.prevayler.org
 2 - Design Patterns, de Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (Model/View/Controller, Strategy (315) e Command (233)).
 3 - PLoP 2002 - http://jerry.cs.uiuc.edu/~plop/plop2002/proceedings.html (Validation Strategy)
 4 - Struts: http://jakarta.apache.org/struts/
 5 - EJB Design Patters, de Floyd Marinescu (EJB Home Factory).
 6 - Core J2EE Patterns (Transfer Object e outros), de Deepak Alur, John Crupi, Dan Malks
 - JUnitEJB: http://sourceforge.net/projects/junitejb/
 - JBoss: http://www.jboss.org/

 
Valid HTML 4.01! Valid CSS!
[ voltar ]|[ topo ]