En esta directriz se describen los pasos implicados en la ingeniería inversa de una base de datos y en la correlación
de las tablas de modelo de datos resultantes con clases
de diseño en el modelo
de diseño. El diseñador
de base de datos puede utilizar este proceso para generar el desarrollo de modificaciones para la base de datos
como parte de un ciclo de desarrollo de evolución. El diseñador de base de datos debe gestionar el proceso de
ingeniería inversa a lo largo del ciclo de vida de desarrollo del proyecto. En muchos casos, el proceso de
ingeniería inversa se lleva a cabo en una fase temprana del ciclo de vida del proyecto y, a continuación, los cambios
en el diseño de datos se gestionan de forma incremental, sin necesidad de realizar ingeniería inversa posterior de la
base de datos.
Los pasos más importantes del proceso para ingeniería inversa de una base datos y la transformación de los elementos
del modelo de datos resultantes en elementos del modelo de diseño son los siguientes:
-
Crear un modelo de datos físico que contenga tablas para representar el diseño físico de datos persistentes en la
base de datos. Este paso se puede llevar a cabo automáticamente utilizando las herramientas que se
proporcionan con RDBMS (sistema de gestión de bases de datos relacionales), o bien, a través de las herramientas de
modelado visual más modernas.
-
Transformar las tablas del modelo de datos físico en clases de diseño del modelo de datos. Este paso se puede
llevar a cabo por medio de la combinación del soporte de herramientas automatizadas para la transformación inicial
y, a continuación, realizando ajustes manuales.
-
Definir asociaciones entre las clases en el modelo de diseño.
-
Definir operaciones adecuadas en las clases del modelo de diseño basadas en las acciones llevadas a cabo en los
elementos del modelo de datos correspondiente.
-
Agrupar las clases del modelo de diseño en subsistemas y paquetes, según proceda.
Normalmente, el proceso de ingeniería inversa de script DDL (lenguaje de definición de datos) o de bases de datos
produce un conjunto de elementos de modelo (por ejemplo, tablas, vistas o procedimientos almacenados). Dependiendo de
la complejidad de la base de datos, es posible que el diseñador de bases de datos deba particionar los elementos de
modelo de ingeniería inversa en paquetes de área temática que contengan conjuntos de tablas relacionados de forma
lógica.
Se puede seguir el procedimiento siguiente para producir clases de diseño a partir de elementos de modelo en el modelo
de datos. La creación de réplicas de la estructura de la base de datos en un modelo de clase es relativamente sencilla.
En el proceso que se indica más abajo se describe el algoritmo para transformar elementos del modelo de datos en
elementos del modelo de diseño.
En la tabla siguiente se muestra un resumen de la correlación general entre elementos del modelo de diseño y elementos
del modelo de datos.
Elemento del modelo de datos
|
Elemento del modelo de diseño correspondiente
|
Tabla
|
Clase
|
Columna
|
Atributo
|
Relación de no identificación
|
Asociación
|
Tabla de intersección
|
Clase de asociación
Asociación varios a varios
Asociación calificada
|
Relación de identificación
|
Agregación
|
Cardinalidad
|
Multiplicidad
|
Comprobar restricción con una cláusula enumerada
|
Clase <<ENUM>>
|
Esquema
|
Paquete
|
Algunos elementos de modelo del modelo de datos no tienen correlación directa en el modelo de diseño. Estos elementos
incluyen los espacios de tablas y la base de datos en sí misma, que modelan las características de almacenamiento
físico de la base de datos y se representan como componentes. Otro elemento son las vistas de la base de datos, que son
tablas "virtuales" sin significado en el modelo de diseño. Por último, los índices de las claves principales de
las tablas y las funciones de desencadenamiento de la base de datos, que se utilizan para optimizar el funcionamiento
de las bases de datos, y sólo tienen significado en el contexto de la base de datos y el modelo de datos.
Para cada tabla que desee transformar, cree una clase que la represente. Para cada columna, cree un atributo en la
clase con el tipo de datos adecuado. Intente que el tipo de datos del atributo y el tipo datos de la columna asociada
coincidan lo máximo posible.
Ejemplo
Considere la tabla de base de datos Cliente, con la estructura siguiente de la figura que se muestra más abajo:
Nombre de columna
|
Tipo de datos
|
ID_Cliente
|
Número
|
Nombre
|
Varchar
|
Calle
|
Varchar
|
Ciudad
|
Varchar
|
Estado/Provincia
|
Char(2)
|
Código postal
|
Varchar
|
País
|
Varchar
|
Definición de tabla para la tabla Cliente
Empezando a partir de este punto, se crea una clase, Cliente, con la estructura que se muestra en la figura
siguiente:
Clase Cliente inicial
En esta clase Cliente inicial, en la tabla Cliente existe un atributo para cada columna. Cada atributo
tiene visibilidad public, puesto que se puede consultar cualquiera de las columnas de la tabla de origen.
Observe que el icono "+" listado a la izquierda del atributo indica que el atributo es 'public'; por omisión, todos los
atributos derivados de las tablas RDBMS deben ser públicos puesto que, por lo general, RDBMS permite consultar
cualquier columna sin restricciones.
Con frecuencia, la clase que es resultado de la correlación de tabla-clase directa contiene atributos que se pueden
separar en una clase separada, especialmente, en aquellos casos en los que los atributos aparecen en varias clases
transformadas. Estos "atributos repetidos" pueden ser resultado de la desnormalización de tablas por motivos de
rendimiento, o bien, de un modelo de datos simplificado en exceso. En estos casos, divida la clase correspondiente en
dos o más clases que representen una vista normalizadas de las tablas.
Ejemplo
Después de definir la clase Cliente, más arriba, se puede definir una clase Dirección que contenga toda
la información relacionada con la dirección (dando por supuesto que hay otros elementos con direcciones en el sistema),
lo que dejaría las clases siguientes:
clase Cliente revisada, con la clase Dirección extraída
La asociación que se dibuja entre ambas es una agregación, puesto que la dirección del cliente se puede
considerar como parte del cliente.
Para cada relación de clave externa de la tabla, cree una asociación entre las clases asociadas, eliminando el atributo
de la clase que se ha correlacionado con la columna de claves externas. Si la columna de claves externas se ha
representado, inicialmente, como un atributo, elimínelo de la clase.
Ejemplo
Suponga la estructura de la tabla Pedido listada más abajo:
Nombre de columna
|
Tipo de datos
|
Número
|
Número
|
ID_Cliente
|
Varchar
|
Estructura de la tabla Pedido
En la tabla Pedido listada más abajo, la columna ID_Cliente es una referencia de clave externa;
esta columna contiene el valor de clave principal del cliente asociado al pedido, tal como se representa en el modelo
de diseño que se muestra más abajo:
Representación de las relaciones de claves externas en el modelo de diseño
La clave externa se representa como una asociación entre las clases Pedido y Elemento.
Los modelos de datos RDBMS representan relaciones de varios a varios con lo que ha dado en llamar una tabla de
unión, o bien, una tabla de asociación. Estas tablas permiten representar relaciones de varios a varios por
medio de una tabla intermedia que contiene las claves principales de dos tablas diferentes que se pueden unir entre sí.
El motivo por el que se necesitan tablas de unión es que una referencia de clave externa sólo puede contener una
referencia a un solo valor de clave externa; una sola fila se puede relacionar con otras filas de otra tabla, pero se
necesita una tabla de unión para asociarlas.
Ejemplo
Considere el caso de Productos, que puede proporcionar uno de varios Proveedores, y cualquier
Proveedor puede ofrecer cualquier número de Productos. Las tablas Productos y Proveedores
tienen la estructura que se ha definido más abajo:
Tabla Productos
Nombre de columna
|
Tipo de datos
|
ID_Producto
|
Número
|
Nombre
|
Varchar
|
Descripción
|
Varchar
|
Precio
|
Número
|
|
Tabla Proveedores
Nombre de columna
|
Tipo de datos
|
ID_Proveedor
|
Número
|
Nombre
|
Varchar
|
Calle
|
Varchar
|
Ciudad
|
Varchar
|
Estado/Provincia
|
Char(2)
|
Código postal
|
Varchar
|
País
|
Varchar
|
|
Definiciones de las tablas Productos y Proveedores
Con el objeto de enlazar ambas tablas entre sí para buscar los productos que ofrece un proveedor determinado, se
necesita una tabla Productos-Proveedor, que se definen en la tabla siguiente:
Tabla Producto-Proveedor
|
Nombre de columna
|
Tipo de datos
|
ID_Producto
|
Número
|
ID_Proveedor
|
Número
|
Definición de la tabla Producto-Proveedor
Esta tabla de unión contiene las claves principales de los productos y los proveedores, enlazándolos entre sí.
Una fila de la tabla indica que un proveedor determinado ofrece un producto concreto. Todas las filas cuyo ID_Proveedor
coincide con un ID de proveedor específico proporcionan un listado de todos los productos que ofrece dicho proveedor.
En el modelo de diseño, esta tabla intermedia es redundante, puesto que un modelo de objeto puede representar
asociaciones de varios a varios de forma directa. En la figura siguiente se muestran las clases Proveedor y
Producto y sus relaciones, junto con la clase Dirección, que se extrae del Proveedor, tal como se
ha explicado más arriba.
Representación de las clases Producto y Proveedor
A menudo, se encuentran tablas cuya estructura es similar. En el modelo de
datos no hay ningún concepto de generalización, por lo que no existe ningún procedimiento para representar que dos
o más tablas tienen una estructura en común. A veces, la estructura común es resultado de la desnormalización para el
rendimiento, como sucedía en el caso anterior con la tabla Dirección "implícita" que se ha extraído a una clase
separada. En otros casos, las tablas comparten características más esenciales que se pueden extraer a una clase padre
generalizada con dos o más subclases. Para buscar oportunidades de generalización, observe las columnas repetidas en
varias tablas, donde las tablas presentan más similitudes que diferencias.
Ejemplo
Considere las tablas siguientes, SoftwareProduct y HardwareProduct, tal como se muestran más abajo:
Tabla Productos de software
Nombre de columna
|
Tipo de datos
|
ID_Producto
|
Número
|
Nombre
|
Varchar
|
Descripción
|
Varchar
|
Precio
|
Número
|
Versión
|
Número
|
|
Tabla Productos de hardware
Nombre de columna
|
Tipo de datos
|
ID_Producto
|
Número
|
Nombre
|
Varchar
|
Descripción
|
Varchar
|
Precio
|
Número
|
Versión
|
Número
|
|
Tablas SoftwareProduct y HardwareProduct
Observe que las columnas resaltadas en azul son idénticas; ambas tablas comparten gran parte de la definición, y
presentan ligeras diferencias. Se puede representar extrayendo una clase Producto, con SoftwareProduct y
HardwareProduct como subclases del Producto, tal como se muestra en la figura siguiente:
Clases SoftwareProduct y HardwareProduct, mostrando la generalización de la clase Producto.
Al unir todas las definiciones de clases entre sí, la figura siguiente muestra un diagrama de clase consolidado para el
sistema de Entrada de pedido (sólo las clases principales).
Diagrama de clase consolidado para el sistema de entrada de pedido
La creación de réplicas es más difícil puesto que, normalmente, las bases de datos relacionales no están orientadas a
objetos y parecen no tener nada análogo con las operaciones realizadas en una clase del modelo de objeto. Los pasos
siguientes le pueden ayudar a volver a construir el comportamiento de las clases identificadas más arriba:
-
Crear operaciones para obtener un establecer cada atributo. Debe haber un modo de establecer, cambiar y
consultar los valores de los atributos de los objetos. Puesto que el único procedimiento para acceder a los
atributos de un objeto es por medio de las operaciones que proporciona la clase, se deben definir dichas
operaciones en la clase. Al crear las operaciones que establecen el valor de un atributo, asegúrese de que
incorpora todas las restricciones de validación que pueden operar en la columna asociada. Si no existen
restricciones de validación, elija sólo que se represente el hecho de que los atributos se pueden obtener y
establecer al hacer que tengan visibilidad pública, tal como se ha realizado en los diagramas anteriores
(con el icono a la izquierda del nombre del atributo).
-
Crear una operación en la clase para cada procedimiento almacenado que opere en la tabla asociada. Los
procedimientos almacenados son rubrutinas ejecutables que se ejecutan en el propio DBMS. Esta lógica se debe
convertir al modelo de diseño. Si el procedimiento almacenado sólo opera en una clase, cree una operación en la
clase con los mismos parámetros y el mismo tipo de retorno que el procedimiento almacenado. Documente el
comportamiento del procedimiento almacenado en la operación, asegurándose de que anota en la descripción del
método que el procedimiento almacenado implementa la operación.
-
Crear operaciones para gestionar asociaciones entre clases. Cuando existe una asociación entre dos clases,
debe haber un modo de crear, gestionar y eliminar asociaciones. Las asociaciones entre objetos se gestionan a
través de referencias a objetos, así, para crear una asociación entre Order y LineItem (es decir,
para añadir LineItem a Order), se invoca una operación en Order, pasando LineItem como
un argumento (es decir, Order.add(aLineItem)). También debe haber procedimientos para eliminar y actualizar
la asociación (es decir, Order.remove(aLineItem) y Order.change(aLineItem,aNewLineItem)).
-
Manejar supresión de objetos. Si el lenguaje de destino ofrece soporte para la supresión explícita, añada
comportamiento al destructor de la clase que implementa la comprobación de la integridad referencial. En aquellos
casos en los que existen restricciones de integridad referencial en la base de datos, por ejemplo cascade
delete, se deben crear réplicas del comportamiento en las clases adecuadas. Por ejemplo, la base de datos puede
definir una restricción que indique que cada vez que se suprima un Order, también se eliminen todos los
LineItems asociados. Si el lenguaje de destino admite la recopilación de basura, cree un mecanismo por el
que se eliminen las filas de las tablas cuando se elimine el objeto asociado por medio de la recopilación de
basura. Tenga en cuenta que parece más difícil de lo que parece (y parece difícil), puesto que debe implementar un
mecanismo que garantice que ningún cliente de la base de datos tenga referencias al objeto que va a recopilar la
basura; no es suficiente para depender de las posibilidades de la recopilación de basura de la máquina
virtual/entorno de ejecución, puesto que es, simplemente, una vista del cliente.
-
Manejar el comportamiento que implican las consultas. Examine las sentencias Seleccionar que acceden a la
tabla para ver cómo se recupera y manipula la información. Para cada columna que devuelve una sentencia Seleccionar
directamente, establezca la propiedad public del atributo asociado en true; todos los demás atributos
deben ser private. Para cada columna calculada en una sentencia Seleccionar, cree una operación en la clase
asociada para calcular y devolver el valor. Cuando considere las sentencias Seleccionar, incluya también las
sentencias Seleccionar incorporadas en definiciones de Ver.
Las clases de diseño que se crean a partir de las transformaciones de tabla en clase se deben organizar en paquetes de diseño o subsistemas de diseño adecuados en el modelo de diseño, según
proceda, en base a la estructura arquitectónica global de la aplicación. Consulte los apartados Concepto: Capas y Concepto:
Arquitectura de software, donde se proporciona una visión general de la arquitectura de la aplicación.
|