estratégias de persistência em software orientado a ...re.granbery.edu.br/artigos/mjm3.pdf · a...

21
Estratégias de Persistência em Software Orientado a Objetos: Definição e Implementação de um Framework para Mapeamento Objeto-Relacional João Carlos da Silva, Marcelo Santos Daibert, Valdete Maria Gonçalves de Almeida, Alessandreia Marta de Oliveira Julio, Marco Antônio Pereira Araújo [email protected], [email protected], [email protected], {amojulio, maraujo}@granbery.edu.br Faculdade Metodista Granbery Bacharelado em Sistemas de Informação Rua Batista de Oliveira, 1145 – CEP 36010-530 – Juiz de Fora/MG Resumo A orientação a objetos, com o passar dos anos, vem se tornando o padrão de desenvolvimento de sistemas de software. Entretanto, os desenvolvedores enfrentam problemas quando necessitam persistir objetos, uma vez que os bancos de dados puramente orientados a objetos não são maduros o suficiente e normalmente com desempenho inferior aos bancos de dados relacionais. Vislumbrando este problema, este trabalho se propõe a realizar um estudo exploratório e comparativo das tecnologias de persistência de objetos disponíveis no mercado, incluindo as de banco de dados orientado a objetos e objeto-relacionais, além de técnicas de mapeamento objeto-relacional em banco de dados relacionais. Através destes estudos, foi definida e implementada uma ferramenta de persistência de objetos compatível com o Borland Delphi: o framework de persistência objeto-relacional DPL (Delphi Persistent Layer). Palavras Chave: Camada de Persistência, Orientação a Objetos, Mapeamento Objeto- Relacional, Delphi, DPL Abstract Object-Oriented has become, throughout the years, the development pattern for software systems. However, developers have faced problems whenever they need to persist objects, once purely OO database are not mature enough and normally with inferior yielding to relational database. In respect to this problem, it has been proposed to carry out an explanatory and comparative study of technologies of persistence of objects available in the market, including the OO database and the relational-object ones, besides the object-relational mapping techniques in relational database. By means of these studies, it has been defined and implemented a tool of persistence of objects compatible with Borland Delphi: the object-relational persistence framework DPL (Delphi Persistence Layer). Keywords: Persistence Layer, Object-oriented, Object-relational mapping , Delphi, DPL.

Upload: hoanganh

Post on 10-Nov-2018

214 views

Category:

Documents


0 download

TRANSCRIPT

Estratégias de Persistência em Software Orientado a Objetos:

Definição e Implementação de um Framework para

Mapeamento Objeto-Relacional

João Carlos da Silva, Marcelo Santos Daibert, Valdete Maria Gonçalves de Almeida, Alessandreia Marta de Oliveira Julio, Marco Antônio Pereira Araújo

[email protected], [email protected],

[email protected], {amojulio, maraujo}@granbery.edu.br

Faculdade Metodista Granbery Bacharelado em Sistemas de Informação

Rua Batista de Oliveira, 1145 – CEP 36010-530 – Juiz de Fora/MG

Resumo

A orientação a objetos, com o passar dos anos, vem se tornando o padrão de desenvolvimento de sistemas de software. Entretanto, os desenvolvedores enfrentam problemas quando necessitam persistir objetos, uma vez que os bancos de dados puramente orientados a objetos não são maduros o suficiente e normalmente com desempenho inferior aos bancos de dados relacionais. Vislumbrando este problema, este trabalho se propõe a realizar um estudo exploratório e comparativo das tecnologias de persistência de objetos disponíveis no mercado, incluindo as de banco de dados orientado a objetos e objeto-relacionais, além de técnicas de mapeamento objeto-relacional em banco de dados relacionais. Através destes estudos, foi definida e implementada uma ferramenta de persistência de objetos compatível com o Borland Delphi: o framework de persistência objeto-relacional DPL (Delphi Persistent Layer). Palavras Chave: Camada de Persistência, Orientação a Objetos, Mapeamento Objeto-Relacional, Delphi, DPL

Abstract

Object-Oriented has become, throughout the years, the development pattern for software systems. However, developers have faced problems whenever they need to persist objects, once purely OO database are not mature enough and normally with inferior yielding to relational database. In respect to this problem, it has been proposed to carry out an explanatory and comparative study of technologies of persistence of objects available in the market, including the OO database and the relational-object ones, besides the object-relational mapping techniques in relational database. By means of these studies, it has been defined and implemented a tool of persistence of objects compatible with Borland Delphi: the object-relational persistence framework DPL (Delphi Persistence Layer). Keywords: Persistence Layer, Object-oriented, Object-relational mapping , Delphi, DPL.

1. Introdução

O paradigma de desenvolvimento orientado a objetos tem sido extensivamente

utilizado na construção de sistemas de software e se tornando, de fato, o padrão para o

desenvolvimento de aplicações.

Os bancos de dados orientados a objeto são mais adequados para a persistência

de objetos manipulados por aplicações orientadas a objeto, devido à utilização do

mesmo paradigma. Porém a indisponibilidade atual destes bancos de dados, seja devido

ao custo, diversidade ou amadurecimento do mercado, faz com que seja necessária a

busca de alternativas para a realização da persistência.

O modelo de armazenamento relacional é largamente utilizado e difundido no

mercado, contando com diversos produtos e tecnologias maduras e eficientes. Sendo

assim, existe uma forte tendência de utilização de bancos de dados relacionais para

armazenamento dos objetos de aplicações orientadas a objetos. Porém, existem

diferenças significativas do paradigma orientado a objetos para o modelo relacional.

Para que seja possível obter os benefícios de ambos, é necessária uma compatibilidade

entre esses modelos.

Vislumbrando este problema, este trabalho se propôs a realizar um estudo

exploratório e comparativo das tecnologias de persistência de objetos disponíveis no

mercado, incluindo tecnologias de bancos de dados orientado a objetos, objeto-

relacionais, além de técnicas de mapeamento objeto-relacional em banco de dados

relacionais.

Foi realizado um levantamento de soluções de gerenciamento de banco de dados

e de frameworks de mapeamento objeto-relacional para avaliação de viabilidade na

utilização prática no desenvolvimento de projetos. Visando testar as soluções

encontradas, foi implementado um sistema para estudo de caso compatível com as

várias estratégias de persistência. Este estudo de caso surgiu de um processo de

reengenharia de um sistema existente de controle acadêmico construído através de uma

abordagem estruturada.

Inicialmente foram analisados o banco de dados pós-relacional Caché [1, 2, 3, 4,

5], desenvolvido pela Intersystems e alguns frameworks de mapeamento objeto-

relacional do mercado [6, 7, 8]. Os estudados foram o DePO (Delphi Persistent Object)

[9], o IO (Instant Objects) [10] e o TiOPF (TechInside Object Persistence Framework).

Todos compatíveis com o ambiente Borland Delphi de Desenvolvimento.

Com os dados obtidos a partir deste estudo realizado foi definida e

implementada uma nova ferramenta de persistência de objetos compatível com o

Borland Delphi: o framework de persistência objeto-relacional DPL (Delphi Persistent

Layer) [11].

Diante disso, este trabalho está dividido em cinco seções além desta introdução.

A seção 2 define mapeamento objeto-relacional. Na seção 3 são apresentados os

conceitos de camadas de persistência. A seção 4 apresenta a camada desenvolvida no

escopo deste trabalho, a DPL. Já na seção 5 é apresentado um estudo de caso e, na seção

6, as considerações finais.

2. Mapeamento Objeto-Relacional

O mapeamento objeto-relacional é uma abordagem que permite a construção de

sistemas utilizando o paradigma orientado a objetos com a persistência destes objetos

em bancos de dados relacionais. Utilizando-se de técnicas e estratégias específicas, é

possível mapear classes com seus atributos e associações para o modelo relacional

(Figura 1).

Classes

Tabelas

Figura 1. Mapeamento Objeto-Relacional

Utiliza-se uma abstração bastante intuitiva no sentido de que uma classe pode

ser mapeada para uma tabela no banco de dados relacional e atributos da classe para

campos da tabela. Porém, algumas diferenças entre os dois modelos, como OID (Object

Identifiers - identificador de objetos), tipos de dados, herança e associações, demandam

um estudo mais detalhado das estratégias de mapeamento.

2.1 OIDs (Object Identifiers)

Existem várias estratégias para atribuir OIDs para objetos, inclusive pode-se

criar uma ou mais classes cuja responsabilidade específica é a de atribuir OIDs para

objetos, sendo estas estratégias separadas das classes que implementam as regras de

negócio.

É considerada uma boa prática de desenvolvimento separar a estratégia de

atribuição de OIDs das classes de negócio, evitando utilizar um atributo qualquer da

classe para ser o identificador. Identificadores que possuem um significado de negócio,

certamente mudam em algum momento [12], pois as regras de negócio mudam

freqüentemente, e o esforço necessário para realizar esta modificação pode ser

imensurável.

Dentre as várias formas de gerar OIDs, pode-se por exemplo utilizar recursos do

próprio sistema gerenciador de bancos de dados para gerar números seqüenciais

automaticamente e utilizá-los como OIDs. Pode-se utilizar conjuntos de números

inteiros, criar algoritmos sofisticados ou utilizar algoritmos já existentes como GUID’s

(Globally Unique IDentifier) ou UUID’s (Universal Unique Identifier) disponibilizados

pela Microsoft e Digital Equipment respectivamente [12].

Uma importante questão em relação aos OIDs está na escolha da estratégia

utilizada para gerá-los. A utilização de estratégias proprietárias pode limitar a utilização

e portabilidade da aplicação, pois nem todas as estratégias são possíveis em todas as

plataformas de hardware e software. Porém, implementar uma estratégia própria que

garanta a unicidade dos OIDs em diversos ambientes, principalmente em ambientes

cliente-servidor e de objetos distribuídos não é uma tarefa trivial, devido ao volume de

transações concorrentes ou distribuição do gerador de OIDs.

2.2 Mapeamento de Classes em Tabelas

O mapeamento de classes pode ser feito mediante a paridade entre classe e

tabela, ou seja, uma classe é mapeada para uma tabela [12]. Este mapeamento direto de

classes para tabelas representa a forma mais simples de mapeamento, tornando mais

fácil o entendimento e a manutenção de uma aplicação. Com um modelo de classes

bastante simples isto poderia ser feito.

Porém, nem sempre é simples assim. No caso de uma estrutura hierárquica,

várias classes podem ser mapeadas para uma tabela, como também uma classe pode ser

mapeada para várias tabelas. Ainda, classes com atributos multivalorados ou compostos

podem ser mapeadas para mais de uma tabela.

2.3 Mapeamento de Atributos em Colunas

Ao tratar do mapeamento de atributos de uma classe para colunas em tabelas de

um banco de dados relacional, deve-se levar em conta que os atributos podem ser de

tipos de dados simples como inteiros, ponto flutuante, caracteres, boleanos e binários,

mas também podem ser de tipos de dados complexos como tipos baseados em outras

classes. Os atributos podem ser ainda multivalorados, o que viola as regras de

normalização do modelo relacional. Além disso, podem existir atributos de controle ou

utilizados em cálculos, que geralmente não necessitam ser mapeados [12].

Desta forma, os atributos simples podem ser mapeados diretamente para colunas

em uma tabela, já os atributos complexos e multivalorados podem necessitar de tabelas

adicionais para seu armazenamento. Estes atributos complexos geralmente possuem

características recursivas, ou seja, são classes que possuem outros atributos e assim

sucessivamente.

2.4 Mapeamento de Herança

Existem fundamentalmente três estratégias para mapear herança em um banco

de dados relacional [13], exemplificado pela Figura 2:

� uma tabela por hierarquia: mapear toda a hierarquia de classes para uma

tabela, onde todos os atributos das classes da hierarquia são armazenados

nesta única tabela. A desvantagem desta estratégia é que toda vez que um

objeto da hierarquia for persistido no banco, é necessário persistir também

os valores das demais classes vazios, causando uma grande quantidade de

campos inutilizados. Entretanto o acesso ao banco para a manipulação dos

dados é mais rápido, uma vez que todos os dados estão em somente uma

tabela. É adicionada uma coluna na tabela que referencia qual o tipo do

objeto, ou seja, de qual classe aqueles dados pertencem;

� uma tabela por classe concreta: cada classe concreta mapeada vira uma

tabela com todos os atributos herdados das super classes abstratas. A

vantagem desta estratégia é a facilidade de manipulação de dados, uma vez

que todos os dados de cada classe estão em apenas uma única tabela. Como

desvantagem, destaca-se que quando se modifica uma classe abstrata, é

necessário modificar todas as tabelas geradas pelas classes filhas no modelo

relacional;

� uma tabela por classe: cada classe é mapeada para uma tabela.

Uma tabela por

hierarquiaUma Tabela porClasse Concreta

Uma Tabela porClasse

Figura 2. Estratégias de Mapeamento para Herança

2.5 Mapeamento de Associações

As associações entre classes no modelo orientado a objetos é conceitualmente

bastante similar ao relacionamento entre tabelas no modelo relacional. Este fato permite

que tais associações sejam mapeadas para relacionamentos, podendo utilizar chaves

estrangeiras ou tabelas auxiliares [13].

2.5.1. Associações do Tipo 1:1

A associação do tipo 1:1 entre classes é mapeada colocando o atributo

identificador da classe referenciada na classe que o referencia, criando então o conceito

de uma chave estrangeira no modelo relacional [13], como demonstrado na Figura 3.

Figura 3. Mapeamento de Associação do Tipo 1:1

2.5.2. Associações do Tipo 1:n

Da mesma forma que a associação do tipo 1:1, o relacionamento 1:n também é

mapeado colocando o atributo identificador da classe referenciada na classe que o

referencia, criando então o conceito de uma chave estrangeira no modelo relacional

[14], como demonstrado na Figura 4.

Figura 4. Mapeamento de Associação do Tipo 1:n

2.5.3. Associações do Tipo n:n

Para mapear uma associação do tipo n:n, é necessário utilizar o conceito de

tabela associativa, cujo propósito é manter o relacionamento entre duas ou mais tabelas

do modelo relacional [13].

Cria-se então uma tabela associativa com os OID’s das classes que se

referenciam, garantindo a navegabilidade do relacionamento, como exemplificado na

Figura 5.

Figura 5. Mapeamento de Associação do Tipo n:n

2.6 Mapeamento de Associações Todo/Parte

As associações todo/parte geralmente são representadas como agregações ou

composições. As agregações são associações que representam uma relação

grupo/membro, ou seja, onde o objeto agregado pode existir independente dos objetos

que o constituem. Já a composição representa um tipo de associação onde o todo não

existe sem sua(s) parte(s). Neste caso, tanto agregações quanto composições são

mapeadas para tabelas de duas formas: utilizando uma única tabela com todos os

atributos da classe que representa o todo e das classes que representam suas partes, ou

mais de uma tabela, uma para cada classe envolvida no modelo [14].

3. Camadas de Persistência

O termo camada é muito é utilizado por desenvolvedores de sistemas que

desejam construir aplicações com maior grau de manutenibilidade, encapsulando

funcionalidades e diminuindo assim o acoplamento dentro da aplicação. Na utilização

do paradigma orientado a objetos, alguns padrões de projeto auxiliam na construção de

aplicações em camadas, como por exemplo, o padrão Layer e o MVC (Model-View-

Controller), dentre outros [13].

Existem vários arranjos possíveis destas camadas, e a quantidade delas não é

pré-determinada, dependendo do tamanho da aplicação e da arquitetura desejada.

Porém, certamente, quanto menor o número de camadas, melhor é o desempenho da

aplicação [13]. Desta forma o equilíbrio entre o número de camadas e sua arquitetura

traz benefícios à manutenibilidade do sistema com um mínimo de impacto no seu

desempenho.

Já persistência é a habilidade de um objeto sobreviver ao ciclo de vida do

processo no qual ele reside [15]. Objetos que morrem com o fim de um processo são

chamados transientes.

A Figura 6 apresenta uma arquitetura em camadas de uma aplicação utilizando o

modelo MVC, que separa em camadas a aplicação, para diminuir a dependência entre as

classes de interface e de negócio.

Figura 6. Arquitetura de um Aplicativo em Camadas

A camada de persistência encontra-se entre a camada de negócio (onde estão as

classes de domínio da aplicação, ou seja, classes que definem as regras de negócio) e o

banco de dados, permitindo que o impacto das modificações em uma delas seja

atenuado em relação à outra. Isto diminui o grau de dependência do banco de dados,

aumentando o grau de manutenibilidade. Toda responsabilidade por persistir objetos

fica a cargo da camada de persistência, liberando a aplicação destas tarefas, aumentando

a produtividade no desenvolvimento [16].

Na camada de persistência está a definição das estratégias de mapeamento do

modelo orientado a objetos para o modelo relacional, discutidas anteriormente. As

estratégias de mapeamento podem estar implícitas nas classes que compõem a camada,

porém neste caso, a escolha de determinada estratégia em detrimento de outra, traz uma

inflexibilidade na própria camada, pois para mudar de estratégia é necessário modificar

a camada. Porém, é possível isolar da camada de persistência as definições das

estratégias de mapeamento, de forma que as estratégias possam ser modificadas ao

longo do tempo, de acordo com as necessidades. A utilização de documentos XML

(Extensible Markup Language) é uma das possíveis formas de armazenamento das

definições das estratégias de mapeamento. Pode-se também utilizar arquivos texto ou

até mesmo tabelas do próprio banco de dados como estratégia de mapeamento.

Classes de Interface com usuário (View)

Classes de Controle (Controller)

Classes de Negócio (Model)

Classes de

sistema

Banco de Dados

Camada de Persistência

Modelo MVC

4. A Ferramenta DPL (Delphi Persistent Layer)

Para este trabalho, o Delphi foi adotado como linguagem de desenvolvimento da

DPL devido a sua adequação ao paradigma da orientação a objetos. Além disto, para

este ambiente não existem tantas opções de persistência como para outros ambientes

como Java. Isto dificulta a adoção efetiva do paradigma orientado a objetos no

desenvolvimento de aplicações de Delphi.

A construção da DPL seguiu uma abordagem de desenvolvimento através do

ciclo de vida espiral, permitindo separar o processo de construção em etapas e de

maneira evolutiva. Desta forma, funcionalidades são implementadas a cada iteração.

Para divisão das fases foi considerado o modelo proposto por Scott Ambler para

construção de camadas de persistência [13]. Baseado neste modelo, o desenvolvimento

da DPL encontra-se concluído até a segunda etapa (milestone), o que permite a

realização das operações básicas de persistência como: criar, recuperar, atualizar e

excluir objetos (CRUD), além de tratar as associações de classes, como demonstrado na

Figura 7.

Legenda: 1. Operações CRUD 2. Suporte para associações 3. Busca por critérios 4. Suporte para cursores, proxies, registros e cache 5. Aplicação de administração 6. Suporte a transações

DPLFinal

Fases de Evoluçãoda Camada

1

2

3

4

5

6

Figura 7. Fases de evolução da DPL

A Figura 7 ilustra a evolução da DPL segundo um ciclo de vida em espiral,

dividido em seis fases. Na primeira fase a DPL oferece as operações básicas de

persistência (Create, Read, Update e Delete) que permite persistir e recuperar objetos

individualmente. Na segunda fase é possível tratar associações dos objetos, podendo

então persistir e recuperar de maneira simples objetos associados. Na terceira fase é

possível determinar critérios para recuperação e processamento de conjuntos de objetos.

Na quarta fase pode-se utilizar cursores, proxies, cache e registros para otimizar o

desempenho da camada. Na quinta fase é implementada uma aplicação de administração

da DPL que permita uma interação amigável ao desenvolvedor na configuração da DPL,

definição das estratégias de mapeamento, construção automática de classes de domínio

e tabelas do banco de dados relacional, entre outras. A sexta e última fase trata de

implementação do controle de transações bem como concorrência.

A lista de requisitos a seguir encontra-se implementada, onde alguns destes itens

foram implementados parcialmente, porém de maneira completamente funcional, de

forma que a DPL pode ser utilizada para a construção de aplicações simples orientadas a

objetos [13]:

� suportar a arquitetura de aplicação em n-camadas;

� implementar o uso da tecnologia DBExpress para acesso aos bancos de

dados relacionais;

� gerenciar conexões com o banco de dados relacional;

� realizar automaticamente o mapeamento de classes e atributos para tabelas e

campos respectivamente no banco de dados relacional, sendo gerada uma

tabela por classe existente na aplicação;

� mapear agregações, associações (um-para-um, um-para-n e n-para-n) e

composições de classes para relacionamento entre tabelas no banco de dados

relacional;

� mapear herança de classes para tabelas no banco de dados relacional;

� gerar automaticamente identificadores de objetos;

� implementar as operações básicas para os objetos persistentes, seguindo o

padrão CRUD;

� recuperar todos os objetos persistentes automaticamente de uma classe;

� retornar coleções de registros como resultado de requisições de recuperações

visando evitar overhead de conversão de registros de bancos de dados em

objetos e depois em registros novamente.

Para aplicações mais complexas é necessária a evolução da DPL, podendo seguir

as demais fases propostas por Scott Ambler, com incorporação de outros requisitos

descritos no projeto.

Atualmente, aplicações que utilizam classes com ou sem herança, associações

um-para-um e um-para-n são ideais para avaliação da DPL.

A DPL foi projetada para atender à necessidade de troca do banco de dados

relacional utilizado para armazenamento dos objetos, desde que este atenda ao padrão

SQL ANSI. Desta forma, foi utilizado o componente DBExpress que permite, de

maneira simples, a troca do driver utilizado na comunicação com o banco de dados.

Embora o DBExpress dê uma certa flexibilidade à DPL, este exige por sua vez a

utilização de drivers compatíveis com a sua tecnologia, o que é uma certa limitação.

Devido ainda, à implementação de alguns requisitos estarem definidos em fases

de desenvolvimento mais adiantadas, é necessária a criação e manutenção manual tanto

do banco de dados e suas tabelas, bem como do arquivo XML que guarda informações

do mapeamento objeto-relacional.

O tratamento de tipos de dados não primitivos, assim como requisitos

relacionados a desempenho, concorrência e transações, estão alocados para

implementação em fases mais adiantadas na construção da DPL.

4.1 Armazenamento das Estratégias de Mapeamento Objeto-Relacional em XML

As estratégias de mapeamento objeto-relacional definem o funcionamento

essencial da DPL. De forma a tornar flexível a manutenção destas estratégias, encontra-

se fora do código da DPL, ou seja, estão armazenadas em um arquivo externo do tipo

XML, utilizado pela DPL.

Este arquivo XML contém basicamente metadados das classes da aplicação, bem

como suas associações, e principalmente a correspondência para estruturas do banco de

dados relacionais (tabelas e campos).

A Listagem 1 demonstra que o arquivo XML está centrado nas informações das

classes, seus atributos e associações. E ainda onde estes elementos da orientação a

objetos estão mapeados no banco de dados relacional. A estrutura do arquivo XML

facilita a leitura das informações por parte da DPL através de um conjunto de tags pré-

definidas. A validação desta estrutura pode ainda ser feita com uso de XML Schema,

permitindo maior integridade das informações.

Listagem 1. Mapeamento XML para a DPL

01: <?xml version="1.0" encoding="iso-8859-1"?>02: <mapeamento>03: <classes>04: <classe>05: <nomeclasse>Curso</nomeclasse>06: <heranca></heranca>07: <tabela>Curso</tabela>08: <tipo>Concreta</tipo>09: <atributos>10: <atributo>11: <nome>ID</nome>12: <OID>TRUE</OID>13: <campo>OID</campo>14: <tipodado>STRING</tipodado>15: <tamanho>38</tamanho>16: </atributo>17: <atributo>18: <nome>codigocurso</nome>19: <OID>FALSE</OID>20: <campo>cod_curso</campo>21: <tipodado>INTEGER</tipodado>22: <tamanho></tamanho>23: </atributo>24: </atributos>25: <associacoes>26: <classeassociada>27: <nomeclasse>Disciplina</nomeclasse>28: <tipoassociacao>agregation</tipoassociacao>29: <cardinalidade>one</cardinalidade>30: <atributoinverso>curso</atributoinverso>31: </classeassociada>32: <classeassociada>33: <nomeclasse>Professor</nomeclasse>34: <tipoassociacao>one-to-one</tipoassociacao>35: <cardinalidade>one</cardinalidade>36: <atributoinverso>curso</atributoinverso>37: </classeassociada>38: </associacoes>39: </classe>40: </classes>41: </mapeamento>

A DPL realiza na fase inicial da aplicação o carregamento das informações

do arquivo XML de mapeamento. As informações obtidas são armazenadas em um

conjunto de classes que facilitam ainda mais a leitura e navegação pelo mapa de classes

da aplicação, além de evitar o acesso constante ao disco rígido, o que afetaria o

desempenho da DPL. Este conjunto de classes, por sua vez, faz parte de uma arquitetura

implementada pela DPL para facilitar a interação com as aplicações.

4.2 Arquitetura da DPL

Existem diversas classes que formam a arquitetura básica da DPL, sendo: OID,

TDPLPersistentObject, TDPLPersistenceBroker, TDPLPersistenceMapXML,

TDPLRelationalDatabase e TDPLSQLStatement. O diagrama de classes da DPL pode

ser visto na Figura 8, onde os atributos e serviços foram suprimidos para facilitar a

visualização do modelo.

Figura 8. O diagrama de classes da DPL

A classe OID é responsável por gerar identificadores únicos para os objetos

instanciados. Como tais identificadores podem ser criados a partir de diversas

abordagens, a utilização desta classe permite que futuramente a forma de gerar os OIDs

possa ser modificada independente do funcionamento da DPL. Atualmente o algoritmo

utilizado para criação do OID é baseado no GUID (Globally Unique Identifier). O

GUID é representado por um conjunto de caracteres hexadecimais, cuja formação

garante a unicidade do identificador gerado [13].

A classe TDPLPersistentObject é uma das classes principais na arquitetura da

DPL. Através dela, e somente dela, a aplicação orientada a objetos recebe por herança

toda a capacidade de persistência. Esta classe associa-se na arquitetura às outras classes

de maneira a permitir que as informações dos objetos sejam persistidas em bancos de

dados relacionais, através da geração de expressões SQL, comunicação e envio destas

expressões ao banco de dados relacional, dentre outras atividades.

A classe TDPLPersistenceBroker é responsável pela interação com o banco de

dados relacional bem como tarefas de inicialização da DPL. Desta forma implementa

operações que coordenam a carga do mapa XML, a inicialização do banco de dados e

envio de expressões SQL ao banco.

A classe TDPLPersistenceMapXML é responsável por carregar em memória as

informações do arquivo de mapeamento XML, permitindo assim o acesso mais rápido

às informações de mapeamento objeto-relacional, além da flexibilidade de mudança no

arquivo, que pode ser recarregado novamente caso necessário.

A classe TDPLSQLStatement é responsável pela geração de expressões SQL

para realização das operações de persistência junto ao banco de dados relacional. Podem

ser geradas várias expressões SQL para uma única operação de persistência, de acordo

com as definições realizadas no arquivo XML. Ou seja, a persistência de um único

objeto pode gerar várias expressões SQL para manutenção em diversas tabelas no

modelo relacional.

A classe TDPLRelationalDatabase tem como responsabilidade o

encapsulamento das funcionalidades do componente DBExpress. Desta forma, esta

classe controla a conexão ao banco de dados, bem como os parâmetros inerentes ao

driver apropriado do banco, a execução das expressões SQL e desconexão do banco.

O funcionamento coordenado das classes acima mencionadas, cada qual com

responsabilidades bem definidas, permitindo abstrair da aplicação as tarefas

relacionadas à persistência de objetos.

5. Estudo de Caso

Como estudo de caso foi adotado o Sistema de Controle Acadêmico (SCA) que é

utilizado em algumas disciplinas do curso de Sistemas de Informação da Faculdade

Metodista Granbery, sendo um dos motivos pelo qual foi escolhido. O pré-

conhecimento das características do SCA foi um facilitador para a equipe, para poder

então se concentrar nos aspectos relativos à construção e implementação da DPL.

Porém, para a adequação do Sistema de Controle Acadêmico, visto que o mesmo

originalmente foi construído de forma estruturada, foi necessária a realização de uma

reengenharia do sistema para torná-lo aderente ao paradigma orientado a objetos, o que

permitiu a elaboração de uma documentação completa deste sistema seguindo o padrão

IEEE std 830-1998 para especificação de requisitos.

5.1 Desenvolvimento do Sistema de Controle Acadêmico

O SCA seguiu algumas fases de desenvolvimento de forma que pudesse estar

preparado para utilização com a DPL. Como citado anteriormente, na fase inicial sofreu

uma reengenharia com objetivo de torná-lo orientado a objetos e ao mesmo tempo

produzir uma documentação padronizada e completa, consistindo da elaboração dos

diagramas de casos de uso, de classes e de seqüência, utilizando a simbologia da UML

(Unified Modeling Language).

O Sistema de Controle Acadêmico foi então desenvolvido em uma única versão

capaz de utilizar as diversas estratégias de persistência envolvidas neste trabalho. Por

isso, sua implementação contém códigos padronizados e genéricos compatíveis a todas

as estratégias abordadas (DPL, frameworks de persistência e banco de dados objeto-

relacional Caché). Desta forma, e obedecendo ao padrão MVC, foram implementadas as

camadas View (formulários e relatórios) e Controller (denominada gerente). Estas duas

camadas são únicas para todas as abordagens. Apenas a camada Model foi

implementada de acordo com cada abordagem, não interferindo nas demais.

A camada Controller implementa gerentes para cada caso de uso, tendo como

responsabilidade intermediar as solicitações e envios de objetos entre as camadas Model

e View, de forma genérica o bastante para permitir a troca da implementação feita na

camada Model, sem necessidade de modificações na camada View. A camada

Controller transfere objetos do tipo ClientDataset, criados dinamicamente, em resposta

a solicitações e envios de dados dos objetos, permitindo maior independência entre as

camadas.

Na camada Model foram implementadas as classes da aplicação. No caso da

implementação com a DPL foram criadas as classes que herdam de uma superclasse

comum chamada TDPLPersistentObject. Esta característica define a camada como

sendo intrusiva, pois exige a realização da herança. Porém, o SCA foi preparado não

somente para esta abordagem como também para a não intrusiva, como no caso da

utilização do banco de dados Caché.

A abordagem de uso do padrão MVC não é uma obrigatoriedade para

implementação com a DPL, nem mesmo com as demais estratégias. Porém, o desafio de

construção deste tipo de aplicação foi um motivador a mais durante o projeto de

pesquisa.

Sendo assim, o Sistema de Controle Acadêmico foi desenvolvido em camadas

separadamente até a implementação dos gerentes para cada caso de uso. Posteriormente,

foram implementadas as camadas de modelo para cada abordagem. Sendo então a única

diferença entre cada abordagem, a camada Model.

5.2 Implementação do Sistema de Controle Acadêmico com a DPL

Como uma das fases iniciais da implementação da DPL no Sistema de Controle

Acadêmico, destaca-se a construção do arquivo XML de mapeamento objeto-relacional.

De posse da documentação do SCA, em especial do diagrama de classes, foi possível

construir o arquivo de mapeamento.

Como o banco de dados sofreu alterações mínimas (basicamente inclusão de

campos para OIDs) da versão original construída através do paradigma estruturado para

a versão orientada a objetos, os diagramas como DER (Diagrama de Entidade e

Relacionamentos) e DTR (Diagrama de Tabelas Relacionais) serviram também como

base para elaboração do arquivo XML de mapeamento objeto-relacional.

O estudo de caso relacionado à implementação com a DPL descrito neste

trabalho concentra-se em apenas um fragmento do SCA, tendo sido escolhido o caso de

uso Cadastrar Curso, pois possui classes e associações cujas características são

apropriadas para o teste das funcionalidades implementadas na DPL.

Como o próprio nome já indica, o caso de uso Cadastrar Curso permite a

manutenção (pesquisa, inclusão, alteração, exclusão e consulta) de cursos no Sistema de

Controle Acadêmico. Na documentação completa do SCA, este caso de uso faz parte

dos cenários da Secretaria, que trata de funcionalidades realizadas pela secretaria de

uma instituição de ensino. A Figura 9 mostra um fragmento do diagrama de classes do

Sistema Acadêmico, considerando apenas as classes relacionadas a este caso de uso. Os

atributos foram retirados para facilitar a leitura do modelo.

Pessoa

Criar()Pers is tir()Excluir()RecuperaObjeto()RecuperaObjetos ()

Curso

Criar()Pers is tir()Excluir()RecuperaObjeto()RecuperaObjetos ()

Profes s or

1

1

1

1

Coordena0..*

0..*

0..*

0..*Aloca

Figura 9. Fragmento do diagrama de classes do Sistema Acadêmico

A classe Pessoa é uma classe abstrata e possui atributos que são comuns às

classes Professor e Aluno. Esta classe, bem como a classe Curso, herda diretamente da

classe TDPLPersistentObject recebendo assim a capacidade de persistência oferecida

pela DPL. A classe Professor por sua vez recebe esta capacidade de persistência de

maneira indireta, ou seja, pela herança de Pessoa.

As classes implementam propriedades para cada atributo, sendo esta uma

obrigatoriedade para implementação com a DPL. As propriedades substituem os

métodos get e set, necessários para modificar dados dos objetos sem desrespeitar o

princípio do encapsulamento. Embora não seja necessário, podem-se criar propriedades

que acionam métodos get e set caso queira-se respeitar à risca o padrão de uso destes

tipos de métodos. As propriedades devem ter o mesmo nome utilizado internamente no

arquivo XML de mapeamento para referenciar os campos das tabelas.

As classes Professor e Curso implementam os serviços Criar, Excluir, Persistir,

RecuperaObjeto e RecuperaObjetos, que acionam serviços correspondentes nos gerentes

permitindo a realização das respectivas operações, sendo o serviço RecuperaObjetos

responsável pela recuperação de todos os objetos da classe.

A classe Curso implementa a associação do tipo um-para-um com Professor,

adicionando um atributo cujo tipo refere-se a este último, da mesma forma como

especificado no arquivo XML. Ao identificar o tipo de dado do atributo como sendo

uma classe, a DPL verifica se esta faz parte da hierarquia de TDPLPersistentObject.

Caso isto seja verdadeiro, o objeto relacionado ao atributo é instanciado

automaticamente e recebe o OID correspondente. Observa-se que somente o OID é

recuperado, pois é o suficiente para identificar o objeto e posteriormente pode ser

recuperado por completo.

Um único gerente é instanciado no momento da execução de cada operação e

este instância um objeto da classe Curso obtendo ou transferindo a ele os dados para

persistência. Tal transferência acontece de maneira transparente ao desenvolvedor da

aplicação. Os dados da interface são alocados em um ClientDataSet o qual é entregue ao

gerente e solicitado à persistência. Ou, é solicitado ao gerente a recuperação dos dados,

que são recebidos em um ClientDataSet. Desta forma a programação da interface é

simplificada de forma que o desenvolvedor não necessite conhecer como e onde os

dados são persistidos.

O caso de uso Cadastrar Curso, bem como todos os demais, foi especificado em

termos de seu Fluxo Principal, Alternativos e de Exceções, além de sub-fluxos

representando as operações básicas de inclusão, alteração, exclusão e consulta. A

interface principal deste caso de uso considerando o sub-fluxo de inclusão pode ser vista

na Figura 10.

Figura 10. Interface Principal do Caso de Uso Cadastrar Curso

6. Considerações Finais

A persistência de objetos é um tema importante quando se fala em

desenvolvimento de sistemas orientados a objetos. As dificuldades atuais inerentes à

utilização de bancos de dados orientados a objetos levam a busca de alternativas para a

realização da persistência. Devido à grande inserção no mercado, os bancos de dados

relacionais são uma possível alternativa.

Ao determinar a utilização do modelo relacional para persistência de objetos,

deve-se levar em consideração a diferença existente entre estes dois paradigmas,

orientado a objetos e relacional.

O mapeamento objeto-relacional apresenta diversas estratégias para reduzir a

diferença entre os dois paradigmas, a partir do mapeamento de classes, atributos e

associações em tabelas, campos e relacionamentos. As estratégias não apresentam

solução única para cada caso, mas devem levar em consideração características do

modelo de classes, questões como manutenibilidade e desempenho.

A construção de camadas de persistência, embora não seja trivial, mostra-se

possível, através da DPL, e podem ser obtidos resultados visíveis com a sua

implementação. O domínio de temas como engenharia de software, padrões de projeto e

orientação a objetos, entre outros, mostra-se extremamente necessário para acomodar o

processo de desenvolvimento de um framework de persistência.

Agradecimentos

À Faculdade Metodista Granbery pelo apoio dado ao projeto de iniciação

científica Estratégias de Persistência em Software Orientado a Objetos, no qual este

trabalho está inserido.

Referencias Bibliográficas

[1] ALMEIDA, V. M. G. Persistência de Objetos no Banco de Dados Caché. Trabalho de Conclusão de Curso, Bacharelado em Sistemas de Informação – Faculdade Metodista Granbery, Juiz de Fora, 2005.

[2] ALMEIDA, V. M. G.; JULIO, A. M. O.; ARAÚJO, M. A. P. Persistência de Objetos no Caché. SQL Magazine, Rio de Janeiro, v. 22, p. 16-21, 2005.

[3] ALMEIDA, V. M. G.; JULIO, A. M. O.; ARAÚJO, M. A. P. Implementando um Projeto no Caché. SQL Magazine, Rio de Janeiro, v. 25, p. 8-14, 2005.

[4] ALMEIDA, V. M. G.; JULIO, A. M. O.; ARAÚJO, M. A. P. Desenvolvendo Aplicações Web no Caché. SQL Magazine, Rio de Janeiro, v. 29, p. 60-62, 2005.

[5] SILVA, J. C.; ARAÚJO, M. A. P.; JULIO, A. M. O. Delphi X Caché - Persistindo Objetos no Banco de Dados Caché. Active Delphi, v. 28, p. 10-16, junho, 2006.

[6] DAIBERT, M. S. Persistência em Software Orientado a Objetos: Soluções de Mapeamento Objeto-Relacional. Trabalho de Conclusão de Curso,

Bacharelado em Sistemas de Informação – Faculdade Metodista Granbery, Juiz de Fora, 2005.

[7] DAIBERT, M. S.; JULIO, A. M. O.; ARAÚJO, M. A. P. Persistência em Software Orientado a Objetos: Abordagens Utilizando Frameworks Opensource. In: II FESTSOL - Festival de Software Livre, Juiz de Fora, 2005.

[8] DAIBERT, M. S.; JULIO, A. M. O.; ARAÚJO, M. A. P. Persistência em Software Orientado a Objetos: Abordagens Utilizando Frameworks Opensource. In: III Encontro de Software Livre do Amazonas (ESLAM), Manaus, 2005.

[9] DAIBERT, M. S.; JULIO, A. M. O.; ARAÚJO, M. A. P. Persistência de Objetos no Delphi: Introdução ao Framework DePO (Delphi Persistent Objects). Active Delphi, v. 24, p. 16 - 21, fevereiro, 2006.

[10] DAIBERT, M. S.; JULIO, A. M. O.; ARAÚJO, M. A. P. Persistência de Objetos no Delphi: Introdução ao Framework IO (Instant Objects). Active Delphi, v. 25, p. 30 - 34, março, 2006.

[11] SILVA, J. C. Camada de Persistência Objeto-Relacional para Delphi. 2005, Trabalho de Conclusão de Curso, Bacharelado em Sistemas de Informação – Faculdade Metodista Granbery, Juiz de Fora, 2005

[12] AMBLER, S. W. Mapping Object to Relational Databases. 1999. Disponível em: <http://www.ambysoft.com/mappingObjects.pdf>. Acesso em: 08 jul. 2006

[13] AMBLER, S. W. The Design of a Robust Persistence Layer for Relational Databases. Nov. 2000. Disponível em: < http://www.ambysoft.com/essays/persistenceLayer.html >. Acesso em: 01 jul. 2006.

[14] KELLER, W. Mapping Objects to Tables - A Pattern Language. 1997, 2004. Disponível em: <http://www.objectarchitects.de>. Acesso em: 08. jul. 2006.

[15] KELLER, W. Persistence Options for Object-Oriented Programs. 2004. Disponível em: <http://www.objectarchitects.de>. Acesso em: 08. jul. 2006.

[16] YODER, J. W., JOHNSON, R. E., WILSON, Q. D. Connecting Business Objects to Relational Databases. In Proceedings of the 5th Conference on the Pattern Languages of Programs, Monticello, 1998. Disponível em: <http://www.joeyoder.com/Research/objectmappings/Persista.pdf>. Acesso em: 08. jul. 2006.