Clique aqui para ler esse artigo em PDF.imagem_pdf.jpg

capaSQL12.JPG


Clique aqui para ler todos os artigos desta edição

Desenvolvimento de aplicações Orientadas a Objeto apoiado por tecnologias Java Parte I

 

O aumento da complexidade dos softwares, de sua aplicação em diversos setores da sociedade e também da grande concorrência entre empresas de desenvolvimento criou uma preocupação crescente com aspectos do desenvolvimento de sistemas. Assim, questões relativas ao tempo e custo de desenvolvimento, tecnologias utilizadas e ferramentas de apoio são decisivas.

A aplicação de boas práticas pregadas pela Engenharia de Software pode auxiliar a atingir esses objetivos, possibilitando a construção de sistemas com um menor custo, mais confiáveis e com boa qualidade. Atualmente, a principal prática adotada pelas empresas de desenvolvimento de software para obter melhorias em seus produtos é o paradigma de orientação a objeto. O uso de objetos permite a utilização de abstrações mais naturais e próximas dos problemas reais, facilitando o mapeamento das soluções idealizadas pelos engenheiros de software em modelos e em implementações computacionais. Entretanto, percebemos que em grande parte desses produtos somente a modelagem de alto nível é feita seguindo este paradigma e apenas em alguns casos esses conceitos são respeitados também durante a codificação.

Devido à escassez de ferramentas e soluções que apóiem a orientação a objeto nas diversas etapas de desenvolvimento, é observado que freqüentes mapeamentos são necessários para possibilitar o desenvolvimento completo de um sistema. Isto aumenta o risco de inserção de defeitos no software. Como principal exemplo temos a questão do armazenamento de dados, onde é comum se realizar um mapeamento dos diagramas de classe para o modelo de entidades e relacionamento. Essa abordagem é utilizada pelo fato de banco de dados relacionais ser uma tecnologia já madura. Para este caso, seria interessante o uso de uma plataforma de desenvolvimento que evite essa abordagem de mapeamento, permitindo que o mesmo tipo de abstração possa ser aplicado em todas as etapas do ciclo de vida de desenvolvimento de um software.

Baseando-se neste cenário, será apresentada a partir desta edição uma série de artigos descrevendo uma forma de desenvolvermos software utilizando o paradigma da Orientação a Objeto durante todo o seu ciclo de vida, desde a análise de seus requisitos até a realização de testes. Nesta primeira parte introduziremos conceitos e tecnologias que serão aplicadas durante a execução das etapas que compõem o ciclo de vida de desenvolvimento de um software. Nos próximos artigos serão apresentadas ferramentas de apoio às tecnologias discutidas nesta primeira parte e um exemplo de desenvolvimento de software, guiado por um modelo de ciclo de vida incremental composto pelas etapas de análise, projeto, codificação e teste, onde serão aplicados na prática os conceitos e tecnologias discutidos ao longo da série.

Tecnologias utilizadas para o desenvolvimento orientado a objeto

Para a apresentação de uma abordagem de desenvolvimento de software utilizando o paradigma de orientação a objeto durante todo o seu ciclo de vida, alguns conceitos e tecnologias devem ser selecionados.

 

Modelagem: para a modelagem de alto e baixo nível do sistema será utilizada a modelagem orientada a objeto através da linguagem UML (Unified Modeling Language) que consiste em um padrão para elaboração da estrutura de projetos de software.

Desenvolvimento: Devido às facilidades oferecidas, sua evolução e amadurecimento, Java foi escolhido como plataforma de desenvolvimento. Essa plataforma é fortemente fundamentada nos conceitos de Orientação a Objeto (OO), característica que dificulta o seu aprendizado por desenvolvedores iniciantes que não conhecem a teoria da OO. No entanto, após vencer a sua curva de aprendizado, as facilidades apresentadas por esta plataforma permitem o desenvolvimento de forma mais simplificada e rápida de diversos tipos de software.

 

Armazenamento: Serão aplicados os conceitos de persistência de objetos visando mostrar ao leitor uma solução de armazenamento que evite a criação de complexas sentenças SQL e que permita atender as necessidades de acesso e armazenamento dos dados do sistema.

 

Novas tecnologias estão sendo incluídas na plataforma Java, permitindo que a abstração de objetos seja utilizada em todas as tarefas do desenvolvimento de um software, incluindo persistência e realização de testes de unidade. Entre essas tecnologias, serão discutidas:

·         Java Data Object (JDO) que consiste em uma solução para a persistência de objetos;

·         JUnit que consiste em um framework para a realização de testes de unidade;

JDO

Para implementar uma aplicação em Java, freqüentemente é necessário o acesso e a persistência de dados tradicionalmente armazenados em banco de dados. Atualmente, o método mais comum de acesso requer o uso da  JDBC dentro do código da aplicação, por onde sentenças SQL são representadas e enviadas ao banco. Com essa abordagem os dados retornam no formato de Strings e números que devem ser mapeados em atributos de objetos.

Para desenvolver aplicações de forma mais produtiva, sem a necessidade de realizar mapeamentos entre diferentes tipos de modelos (modelo de classes « modelo relacional), a tarefa de persistência deveria ser transparente ao desenvolvedor. Este se preocuparia principalmente com a modelagem dos objetos de negócio e de sua codificação, enquanto que os dados seriam gerenciados através de uma camada de persistência de objetos.

Tendo em mente as facilidades que tal abordagem poderia oferecer aos desenvolvedores, a Sun integrou na plataforma Java uma API para realizar tal tarefa, denominada de JDO (Java Data Object).

O principal objetivo da JDO é prover uma API padrão que permita a utilização de um gerenciador de persistência de objetos, realizando assim o mapeamento automático entre o modelo relacional e o modelo de classes da aplicação. Tendo como base essa API padrão, vários fornecedores podem implementar sua própria camada de persistência, chamada de implementação JDO (ver Figura 1),  permitindo assim embutir as características por ele desejada, como por exemplo, alto desempenho, baixo custo de aquisição, etc.

 

image001.gif 

Figura 1 - Arquitetura de uma aplicação que utiliza a API JDO

 

Com a tecnologia JDO, o desenvolvedor não precisa manipular as interfaces nativas de acesso a diferentes tipos de repositório. Essa camada de persistência é responsável também por transformar os dados recebidos pelo banco em uma instância do objeto ao qual os dados se referem. Com essa abordagem, os principais benefícios a serem obtidos são:

o    Portabilidade: aplicações escritas com a API JDO podem ser executadas em múltiplas implementações sem necessitar nova compilação ou alteração no código fonte. Essa característica permite que a aplicação não fique dependente de nenhuma solução JDO e possibilita alterá-la de acordo com as facilidades e características presentes em cada implementação;

o    Independência de Banco de dados: devido à camada criada entre a aplicação e o banco, o acoplamento entre esses dois componentes passa a ser mínimo, o que deixa o sistema totalmente independente do banco de dados.

o    Facilidade de uso: o desenvolvedor pode dar mais atenção à modelagem do sistema deixando assim os detalhes de persistência para o framework que estiver implementado a API JDO. Desta forma, não é mais necessária a inserção de código SQL no código fonte da aplicação;

o    Maior performance: por ser responsável pelo gerenciamento da persistência, o JDO pode otimizar os padrões de acesso a fim de encontrar um desempenho ótimo para o acesso a base de dados;

 

PersistenceManager pm = pmf.getPersistenceManager();

try

  {

    Habitante hab = new Habitante(“Michele Santos”, “Feminino”, 21);

    hab.setEndereco(new Endereco("Cidade", "Rua", 6900000, "Brasil"));

    ...

    pm.makePersistent(hab);

   }

...

pm.close();

Listagem 1 – Exemplo de código Java-JDO para a criação de um novo objeto e inserção no banco

Como exemplo de implementação temos o código apresentado na Listagem 1, onde uma instância do PersistenceManager é criada. O PersistenceManager é o principal ponto de acesso às informações contidas no banco de dados, esse objeto é responsável por realizar as operações (exclusão, inserção, alteração) responsáveis por alterar o estado do banco de dados. Nesse exemplo, uma instância de Habitante é criada e depois ela é persistida no banco através do PersistenceManager (pm.makePersistent(hab)).

JUnit

 

A maioria dos desenvolvedores concorda com a necessidade de testar seus códigos antes de disponibilizá-lo. Para reduzir a quantidade de defeitos inseridos no software é necessária a realização de atividades de teste. Estas envolvem várias fases como teste de unidade, teste de integração e teste de sistema. Neste artigo trataremos somente de teste de unidade que tem como objetivo explorar a menor unidade do projeto (no caso de projeto orientado a objeto a menor unidade é o método de uma classe) procurando erros em cada módulo.

A definição e execução de casos de teste para cada método de uma classe é uma atividade fundamental na sua avaliação, no entanto, pode envolver muito tempo e custo na sua realização. Com isso, uma das soluções disponibilizadas aos desenvolvedores Java é o framework JUnit que se baseia nos conceitos de testes de unidade onde a abstrações de objetos é utilizada.

Através desse mecanismo, em um primeiro momento, casos de teste para cada classe são especificados e, em uma segunda fase, são executados com o auxílio de uma ferramenta, responsável pela criação de relatórios compostos pela descrição dos problemas detectados.

Assim, esse framework permite a especificação de casos em que a execução dos métodos de um objeto poderia falhar, além de automatizar a execução desses testes. Caso a equipe possua o hábito de executar testes diariamente, a execução permite apontar problemas assim que aconteçam, reduzindo bastante o custo de manutenção.

O JUnit é bastante simples e está sendo integrado às principais ferramentas de desenvolvimento Java. Ele é composto basicamente por:

o        Uma classe base (TestClasse) que deve ser estendida pelas classes que realizarão o teste (SuaClasseTeste) (Figura 2);

o        Um conjunto de métodos auxiliares (Assert) para a verificação de asserções que verificam a validade das comparações (Figura 2);

o        Ferramenta para execução do teste (Figura 3);

                              image002.jpg

Figura 2 - Criando classes de teste

image004.jpg 

Figura 3 - Ferramenta para execução do teste

Descrição das etapas de desenvolvimento

Iremos introduzir a seguir um modelo de ciclo de vida que pode ser utilizado para guiar o desenvolvimento do software. Para cada etapa do ciclo de vida será abordada então uma estratégia para executá-la através do paradigma de orientação a objeto e possíveis ferramentas (de preferência gratuitas) que apoiarão essas etapas.

O uso de ferramentas ao longo do desenvolvimento resulta em uma maior produtividade da equipe e fornece também um conhecimento sobre as atividades a serem realizadas. No entanto, as licenças dessas ferramentas resultam em um custo significativo para as empresas de desenvolvimento. Desta forma, a utilização de ferramentas gratuitas pode diminuir o custo e conseqüentemente o preço do produto final.

O modelo de ciclo a ser seguido foi inspirado no modelo de ciclo de vida incremental (Figura 4). Esse modelo foi desenvolvido através da combinação entre os modelos “cascata” e prototipação. O desenvolvimento é dividido em etapas, denominadas “incrementos”, que produzirão gradativamente o sistema, até a sua versão final.

Em cada incremento, todas as etapas básicas do desenvolvimento de software são realizadas, do planejamento aos testes do sistema. Cada etapa produz um sistema totalmente funcional, apesar de ainda não cobrir todos os requisitos.

O modelo incremental apresenta diversas vantagens para o desenvolvimento de um software, especialmente se os requisitos não estão claros inicialmente:

·         O cliente esclarece seus requisitos e suas prioridades para os próximos incrementos;

·         O cliente pode contar com os serviços da versão já produzida

·         A construção de um sistema menor é sempre menos arriscada que a construção de um grande;

·         Se um grande erro é cometido, apenas o último incremento é descartado;

 

 

image006.gif

 

Figura 4 – Modelo de ciclo de vida incremental

Análise de requisitos

Os requisitos consistem em uma série de sentenças que descrevem de maneira clara, concisa, consistente e não-ambígua todos os aspectos significativos do sistema (objetivos, funções e limitações) a ser desenvolvido. Para a especificação dos requisitos, o desenvolvedor deve analisar a utilização específica do sistema a ser produzido. A especificação deve ser bem documentada, avaliada e deve conter requisitos funcionais e não-funcionais (requisitos de qualidade) do sistema, além das restrições funcionais e de projeto.

Ao final dessa atividade o desenvolvedor deve produzir o documento (especificação) de requisitos que guiará o restante do processo de desenvolvimento. Essa especificação deve estabelecer o comportamento visível do sistema, independente da implementação a ser desenvolvida.

Nesta série de artigos será utilizada a técnica de casos de uso para representar os atores e suas ações no sistema. O modelo de casos de uso a ser produzido nesta etapa deve ser acompanhado por um documento com a descrição detalhada das funcionalidades apresentadas neste modelo. Para a definição deste modelo será utilizada a linguagem de modelagem orientada a objeto UML apoiada através de uma versão gratuita da ferramenta de modelagem Poseidon.

Projeto de sistema

Nessa etapa, os componentes individuais de software são refinados até o nível de interfaces, classes e componentes. Detalhes são adicionados, em termos de estrutura de dados e algoritmos, de modo a permitir que os componentes individuais do software sejam futuramente implementados. Para tal, devem ser tomadas decisões de projeto, como por exemplo, a definição da base de dados, da linguagem de programação, do padrão de integração e do estilo de interface. Ao final desta etapa, o desenvolvedor deve produzir o documento (especificação) do projeto do sistema.

Para a definição das classes do sistema, que será mostrado na continuação desse artigo, será utilizado o diagrama de classes definido pela linguagem UML que será apoiada através da ferramenta Poseidon. Em seguida, será realizado o mapeamento deste diagrama para a.estrutura da camada de persistência de objetos.  Essa camada segue o padrão definido pela API JDO e a implementação JDO Genie foi escolhida para controlar o acesso aos dados no SGBD MySQL.

Codificação

O desenvolvedor deve codificar e documentar cada unidade de software usando técnica de implementação que produzam um código eficiente e livre de erros. Se o projeto elaborado na fase anterior possuir um nível de detalhe elevado, a etapa de codificação terá seu esforço minimizado, pois muita coisa poderá ser gerada automaticamente. Para a execução desta etapa será utilizada a linguagem Java apoiada por uma versão gratuita do ambiente de desenvolvimento NetBeans.

 Teste

O processo de teste centraliza-se em dois pontos principais: as lógicas internas do software e as funcionalidades externas. Esta fase concentra-se na descoberta de erros “comportamentais” do software e tem como objetivo assegurar que as entradas definidas produzam resultados reais que coincidam com os requisitos especificados. Para a execução desta etapa será utilizado o framework JUnit para a realização de testes nas unidades que compõem o sistema.

Considerações

O este artigo não tem como objetivo introduzir formas de desenvolvimento de software, mas instigar os desenvolvedores a buscarem novas tecnologias para solucionar os problemas no desenvolvimento orientado a objeto. Nesta primeira parte foi descrita uma visão geral sobre os conceitos e tecnologias que apóiam o desenvolvimento de sistemas orientados a objeto. Nos próximos artigos da série iremos apresentar como as tecnologias analisadas podem ser aplicadas na prática, além de mostrarmos possíveis ferramentas de apoio através do desenvolvimento de um sistema real.

 

Links interessantes

 

www.java.sun.com – Página do desenvolvedor Java

www.java.sun.com/products/jdo – Página principal da tecnologia JDO

www.junit.org – Página oficial do JUnit

www.uml.org – Página oficial da UML