Esta diretriz descreve as etapas envolvidas em reverter a engenharia de um banco de dados e mapear as tabelas
resultantes do Modelo de Dados para as Classes
de Design no Modelo de Design. Esse processo pode ser utilizado pelo Designer de Banco de Dados para ocasionar o desenvolvimento de
modificações no banco de dados como parte de um ciclo de desenvolvimento evolutivo. O Designer de Banco de Dados
precisará gerenciar o processo de engenharia reversa em todo o ciclo de vida de desenvolvimento do projeto. Em
muitos casos, o processo de engenharia reversa é desempenhado logo no início do ciclo de vida do projeto e, depois, as
alterações no design de dados são gerenciadas de modo incremental, sem a necessidade de desempenhar a engenharia
reversa subseqüente do banco de dados.
As principais etapas no processo para reverter a engenharia de um banco de dados e transformar os elementos resultantes
do Modelo de Dados em elementos do Modelo de Design são mostradas a seguir:
-
Crie um Modelo de Dados físico que contenha tabelas para representar o layout físico de dados persistentes no banco
de dados. Esta etapa pode ser desempenhada automaticamente utilizando as ferramentas fornecidas com o RDBMS
(Relational Database Management) ou por meio das ferramentas mais modernas de modelagem visual.
-
Transforme as tabelas no Modelo de Dados físico em Classes de Design no Modelo de Design. Esta etapa pode ser
desempenhada por uma combinação de suporte a ferramentas automatizadas para a transformação inicial, seguida por
ajustes manuais.
-
Defina associações entre as classes no Modelo de Design.
-
Defina operações apropriadas nas classes do Modelo de Design com base nas ações executadas nos elementos
correspondentes do Modelo de Dados.
-
Agrupe as classes do Modelo de Design em subsistemas e pacotes, conforme necessário.
O processo de engenharia reversa do banco de dados ou do script DDL (Data Definition Language) geralmente apresenta um
conjunto de elementos de modelo (tabelas, visualizações, procedimentos armazenados, etc.) . Dependendo da complexidade
do banco de dados, o designer de banco de dados pode precisar particionar os elementos do modelo da engenharia reversa
em pacotes de áreas de assunto que contêm conjuntos logicamente relacionados de tabelas.
O procedimento a seguir pode ser utilizado para produzir Classes de Design a partir dos elementos de modelo no Modelo
de Dados. A replicação da estrutura do banco de dados em um modelo de classe é um procedimento relativamente simples. O
processo listado a seguir descreve o algoritmo para transformar os elementos do Modelo de Dados em elementos do Modelo
de Design.
A tabela a seguir mostra um resumo do mapeamento geral entre os elementos do Modelo de Design e os elementos do Modelo
de Dados.
Elemento do Modelo de Dados
|
Elemento do Modelo de Design Correspondente
|
Tabela
|
Classe
|
Coluna
|
Atributo
|
Relacionamento sem Identificação
|
Associação
|
Tabela de Interseção
|
Classe de Associação
Associação de Muitos-para-Muitos
Associação Qualificada
|
Relacionamento de Identificação
|
Agregação
|
Cardinalidade
|
Multiplicidade
|
Restrição de Verificação com uma cláusula enumerada
|
Classe <<ENUM>>
|
Esquema
|
Pacote
|
Há alguns elementos de modelo no Modelo de Dados que não possuem correlação direta no Modelo de Design. Esses elementos
incluem os Espaços de Tabelas e o próprio Banco de Dados, que modelam as características de armazenamento físico do
banco de dados e são representados como componentes. Um outro item é a visualização do banco de dados, que é uma tabela
"virtual" e não tem significado no Modelo de Design. Por último, índices em chaves principais de tabelas e
funções do acionador do banco de dados, que são utilizados para otimizar a operação do banco de dados, têm significado
apenas no contexto do banco de dados e do Modelo de Dados.
Para cada tabela que você deseja transformar, crie uma classe para representar a tabela. Para cada coluna, crie um
atributo na classe com o tipo de dado apropriado. Tente fazer a correspondência mais aproximada possível entre o tipo
de dado do atributo e o tipo de dado da coluna associada.
Exemplo
Considere a tabela de banco de dados Cliente, com a estrutura mostrada na figura a seguir:
Nome da Coluna
|
Tipo de Dados
|
ID_do_Cliente
|
Número
|
Nome
|
Varchar
|
Rua
|
Varchar
|
Cidade
|
Varchar
|
Estado/Província
|
Char(2)
|
CEP
|
Varchar
|
País
|
Varchar
|
Definição da tabela Cliente
A partir deste ponto, criamos uma classe, Cliente, com a estrutura mostrada na figura a seguir:
Classe Cliente inicial
Nesta classe Cliente inicial, há um atributo para cada coluna na tabela Cliente. Cada atributo possui
visibilidade pública, já que qualquer coluna da tabela de origem pode ser consultada.
Observe que o ícone "+" listado à esquerda do atributo indica que o atributo é 'público'; por padrão, todos os
atributos derivados das tabelas RDBMS devem ser públicos, pois o RDBMS geralmente permite que qualquer coluna seja
consultada sem restrição.
Geralmente, a classe que resulta do mapeamento direto das classes de tabela contém atributos que podem ser separados em
uma outra classe, principalmente nos casos em que os atributos aparecerem em várias classes convertidas. Esses
'atributos repetidos' podem resultar de uma desnormalização das tabelas, por razões de desempenho, ou de um Modelo de
Dados muito simplificado. Nesses casos, divida a classe correspondente em duas ou mais classes para representar uma
visão normalizada das tabelas.
Exemplo
Depois de definir a classe Cliente anterior, é possível definir uma classe Endereço que contenha todas as
informações de endereço (considerando que haverá outros endereços no sistema), resultando nas classes a seguir:
Classe Cliente revisada, com classe Endereço extraída
A associação dessas duas classes resulta em uma agregação, já que o endereço do cliente pode ser considerado
como parte do cliente.
Para cada relacionamento de chave estrangeira da tabela, crie uma associação entre as classes associadas, removendo o
atributo da classe mapeada para a coluna de chave estrangeira. Se a coluna de chave estrangeira tiver sido representada
inicialmente como um atributo, remova-a da classe.
Exemplo
Considere a estrutura da tabela Pedido listada a seguir:
Nome da Coluna
|
Tipo de Dados
|
Número
|
Número
|
ID_do_Cliente
|
Varchar
|
Estrutura da tabela Pedido
Na tabela Pedido listada anteriormente, a coluna ID_do_Cliente é uma referência de chave
estrangeira; esta coluna contém o valor da chave principal do Cliente associado ao Pedido. Essa representação é
mostrada a seguir no Modelo de Design:
Representação dos relacionamentos de chave estrangeira no modelo de design
A chave estrangeira é representada como uma associação entre as classes Pedido e Item.
Os modelos de dados RDBMS representam relacionamentos de muitos-para-muitos que foram chamados de tabela de
junção ou tabela de associação. Essas tabelas permitem que esses relacionamentos sejam representados através
de uma tabela intermediária, contendo as chaves primárias de duas tabelas diferentes que podem ser associadas. As
tabelas de junção são necessárias porque uma referência de chave estrangeira pode conter apenas uma referência a um
único valor de chave estrangeira. Quando uma única linha puder ser relacionada a várias outras linhas de uma tabela
diferente, a tabela de junção será necessária para associá-las.
Exemplo
Considere o caso de Produtos, que podem ser fornecidos por qualquer um dos diversos Fornecedores, e de
qualquer Fornecedor que possa fornecer fornecer qualquer número de Produtos. As tabelas Produto e
Fornecedor possuem a estrutura definida a seguir:
Tabela de Produtos
Nome da Coluna
|
Tipo de Dados
|
ID_do_Produto
|
Número
|
Nome
|
Varchar
|
Descrição
|
Varchar
|
Preço
|
Número
|
|
Tabela de Fornecedores
Nome da Coluna
|
Tipo de Dados
|
ID_do_Fornecedor
|
Número
|
Nome
|
Varchar
|
Rua
|
Varchar
|
Cidade
|
Varchar
|
Estado/Província
|
Char(2)
|
CEP
|
Varchar
|
País
|
Varchar
|
|
Definições das Tabelas Produtos e Fornecedores
Para vincular essas duas tabelas e localizar os produtos oferecidos por um determinado fornecedor, é necessária uma
tabela Produto-Fornecedor, definida na tabela a seguir.
Tabela de Produto-Fornecedor
|
Nome da Coluna
|
Tipo de Dados
|
ID_do_Produto
|
Número
|
ID_do_Fornecedor
|
Número
|
Definição da Tabela Produtos-Fornecedores
Esta tabela de junção contém as chaves primárias de produtos e fornecedores, vinculando-os. Uma linha na tabela
indicaria que um fornecedor específico oferece um determinado produto. Todas as linhas cuja coluna ID_do_Fornecedor
correspondesse a uma identificação específica de fornecedor forneceriam uma listagem de todos os produtos oferecidos
por esse fornecedor.
No Modelo de Design, essa tabela intermediária é redundante pois um modelo de objeto pode representar diretamente as
associações muitos-para-muitos. As classes Fornecedor e Produto e seus relacionamentos são mostrados na
figura a seguir, juntamente com a classe Endereço, que é extraída do Fornecedor, de acordo com a
discussão anterior.
Representação das Classes Produtos e Fornecedores
Geralmente, algumas tabelas terão uma estrutura semelhante. No Modelo de
Dados, não há conceito de generalização, portanto não há como representar duas ou mais tabelas com alguma estrutura
em comum. Algumas vezes, uma estrutura comum resulta de uma desnormalização de desempenho, como o caso anterior em que
a tabela Endereço, extraída em uma classe separada, está 'implícita'. Nos outros casos, as tabelas compartilham
características mais fundamentais que podem ser extraídas em uma classe pai generalizada com duas ou mais subclasses.
Para localizar oportunidades de generalização, procure por colunas repetidas em várias tabelas, em que as tabelas têm
mais semelhanças do que diferenças.
Exemplo
Considere as tabelas, SoftwareProduct e HardwareProduct, mostradas a seguir:
Tabela de Produtos de Software
Nome da Coluna
|
Tipo de Dados
|
ID_do_Produto
|
Número
|
Nome
|
Varchar
|
Descrição
|
Varchar
|
Preço
|
Número
|
Versão
|
Número
|
|
Tabela de Produtos de Hardware
Nome da Coluna
|
Tipo de Dados
|
ID_do_Produto
|
Número
|
Nome
|
Varchar
|
Descrição
|
Varchar
|
Preço
|
Número
|
Versão
|
Número
|
|
Tabelas SoftwareProduct e HardwareProduct
Observe que as colunas destacadas em azul são idênticas; essas duas tabelas compartilham a maior parte de suas
definições em comum e diferem somente um pouco. Podemos representar isso extraindo uma classe Produto comum, com
SoftwareProduct e HardwareProduct como subclasses do Produto, conforme mostrado na figura a
seguir:
Classes SoftwareProduct e HardwareProduct, mostrando uma generalização da classe Produtos
A figura a seguir, que reúne todas as definições de classe, mostra um diagrama de classes consolidado para o sistema
Entrada de Pedidos (somente as classes principais).
Diagrama de Classes Consolidado para o Sistema Entrada de Pedidos
Replicar um comportamento é um procedimento mais difícil, pois geralmente os bancos de dados relacionais não são
orientados a objetos e não parecem ter nada semelhante às operações em uma classe no modelo de objeto. Os passos a
seguir podem ajudar a reconstruir o comportamento das classes identificadas acima:
-
Criar operações para obter e configurar cada atributo. É necessário encontrar uma maneira de configurar,
alterar e consultar os valores dos atributos de objetos. Como a única maneira de acessar os atributos de um objeto
é através de operações fornecidas pela classe, essas operações devem ser definidas na classe. Ao criar as operações
que definirão o valor de um atributo, verifique se incorporou todas as restrições de validação que possam ser
operadas na coluna associada. Se não houver restrições de validação, você poderá optar por simplesmente representar
o fato de que os atributos podem ser obtidos e configurados, marcando-os como tendo visibilidade
"pública", como isso foi feito nos diagramas anteriores (com o ícone à esquerda do nome do atributo).
-
Criar uma operação na classe para cada procedimento armazenado que opera na tabela associada Os
procedimentos armazenados são sub-rotinas executáveis que são executadas no próprio DBMS. Essa lógica precisa ser
convertida no Modelo de Design. Se um procedimento armazenado operar apenas em uma classe, crie uma operação na
classe com os mesmos parâmetros e o mesmo tipo de retorno do procedimento armazenado. Documente o comportamento do
procedimento armazenado na operação, certificando-se de anotar na descrição do método que a operação é
implementada pelo procedimento armazenado.
-
Criar operações para gerenciar associações entre classes. Quando há uma associação entre duas classes, é
necessário que haja uma maneira de criar, gerenciar e remover associações. As associações entre os objetos são
gerenciadas por meio de referências dos objetos. Portanto, para criar uma associação entre um Pedido e um
LineItem (isto é, incluir o LineItem no Pedido), uma operação seria chamada em Pedido,
transmitindo o LineItem como um argumento (isto é, Order.add(aLineItem)). É necessário que também
haja maneiras de remover e atualizar a associação (isto é, Order.remove(aLineItem) e
Order.change(aLineItem,aNewLineItem)).
-
Manipular a Exclusão de Objetos. Se o idioma de destino suportar a exclusão explícita, inclua o
comportamento no destrutor da classe que implementará a verificação de integridade referencial. Nos casos em que
houver restrições de integridade referencial no banco de dados, como exclusão em cascata, o comportamento
precisará ser replicado nas classes apropriadas. Por exemplo, o banco de dados pode definir uma restrição que
determine que sempre que um Pedido é excluído, todos os LineItems associados também devem ser
excluídos. Se o idioma de destino suportar coleta de lixo, crie um mecanismo que permita remover linhas de tabelas
quando o objeto associado for coletado para a lixeira. Observe que isso é mais difícil do que parece (e mesmo assim
parece difícil), pois será necessário implementar um mecanismo que assegure que nenhum cliente de banco de dados
tenha qualquer referência ao objeto que será coletado para a lixeira. Não basta depender dos recursos de coleta de
lixo do ambiente de execução/máquina virtual; essa é uma visão simplista do cliente de perceber o mundo.
-
Manipular o Comportamento Imposto por Consultas. Examine as instruções Select que acessam a tabela para
verificar como as informações são recuperadas e manipuladas. Para cada coluna diretamente retornada por uma
instrução Select, configure a propriedade public do atributo associado como true; todos os outros
atributos devem ser private. Para cada coluna calculada em uma instrução Select, crie uma operação na classe
associada para calcular e retornar o valor. Ao considerar as instruções Select, inclua também as instruções Select
incorporadas nas definições View.
As Classes de Design criadas a partir das transformações de tabela em classe devem ser organizadas em pacotes de design e/ou subsistemas de design apropriados no Modelo de Design, conforme
necessário, com base na estrutura arquitetural geral do aplicativo. Consulte Conceito: Divisão em
Camadas e Conceito:
Arquitetura de Software para uma visão geral da arquitetura do aplicativo.
|