patronesparapersiste.. - Escuela Superior de Informática

Transcripción

patronesparapersiste.. - Escuela Superior de Informática
Patrones para persistencia (I)
Ingeniería del Software II
1 Patrones para la construcción del esquema relacional
En todos los ejemplos realizaremos transformaciones del siguiente diagrama de
clases:
Figura 1
1.1 Patrón "una clase, una tabla"
Mediante este patrón, se construye una tabla por cada clase en la capa de dominio.
Todas las clases que no sean abstractas se transforman en tablas. La herencia se
representa mediante propagación de clave.
En el caso de la Figura 1, puesto que no hay ninguna clase abstracta, el diagrama
relacional sería el siguiente (Figura 2):
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
1
Figura 2
Suponiendo que la clase Vehículos fuera abstracta, habríamos obtenido el siguiente
diagrama relacional (Figura 3):
Figura 3
1.2 Patrón "un árbol de herencia, una tabla"
Con este patrón, cada árbol de herencia se representa en una única tabla, que
contendrá como columnas todos los atributos de todas las clases del árbol de herencia.
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
2
Mediante esta solución, habrá muchos registros en la tabla que tengan varias
columnas a NULL.
En el ejemplo de la Figura 1, el árbol de herencia que tiene como nodo raíz a la
clase Vehículos se transformaría en la siguiente tabla:
Figura 4
Al insertar información en la tabla de la Figura 4, se insertará el valor NULL en la
columna "Toneladas" cuando se inserte un registro correspondiente a un coche, y NULL
en "Potencia" cuando se inserte un camión.
El diagrama relacional completo tendría esta forma:
Figura 5
1.3 Patrón "un camino de herencia, una tabla"
Con este patrón, se construye una tabla por cada camino en el árbol de herencia. De
este modo, podemos considerar que aplicamos el patrón "un árbol de herencia, una
tabla" a cada camino de herencia.
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
3
Apliquemos este patrón al árbol que tiene como raíz a la clase "Personas": en él
identificamos seis caminos:
•
Persona-empleado-administrativo
•
Persona-empleado-conductor
•
Persona-empleado-profesor
•
Persona-alumno-ciclo1
•
Persona-alumno-ciclo2
Debemos crear, por tanto, seis tablas. El diagrama relacional quedaría así:
Figura 6
En este ejemplo concreto, una desventaja importante sería el hecho de que, en el
diagrama de clases de la Figura 1, se especifica que en un asignatura puede haber
matriculados muchos alumnos, independientemente de que sean de primer o segundo
ciclo. Con el diagrama de la Figura 6, tendríamos un problema de integridad referencial,
ya que estaríamos exigiendo que todo alumno que aparezca en la tabla "Asignatura" esté
presente también en las tablas "Ciclo1" y "Ciclo2". Nótese que en ninguno de los
diagramas de las figuras anteriores teníamos este problema. Esto demuestra el hecho de
que no tiene por qué utilizarse siempre el mismo patrón para todo el diagrama de clases:
al árbol correspondiente a la clase Persona podemos aplicarle un patrón, y otro distinto
al de Vehículos.
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
4
2 Patrones
para
la
asignación
de
responsabilidades
relacionadas con la persistencia
En general, todas las clases persistentes deberán implementar de alguna manera los
métodos necesarios para manipular sus instancias desde el punto de vista de la
persistencia. Es decir, que deben contar con métodos que permitan:
•
Materializar instancias: construir objetos a partir de registros almacenados en la base
de datos.
•
Insertar registros en la base de datos, a partir de una instancia.
•
Actualizar el valor de un registro correspondiente a un objeto.
•
Eliminar de la base de datos el registro correspondiente a la instancia.
Típicamente, estos métodos se implementarán en forma de instrucciones Select,
Insert, Update y Delete del lenguaje SQL, o bien mediante llamadas a procedimientos
almacenados que realicen estas funciones.
Existen varias políticas para realizar la asignación de estas responsabilidades, que
se describen en forma de patrones.
2.1 Patrón "tablas como objetos"
Mediante este patrón, cada clase es responsable de implementar sus métodos
persistentes. Es decir, que podríamos reescribir la Figura 1 de este modo (Figura 7):
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
5
Figura 7
Como se observa, las superclases (Persona y Vehículo) y las clases que no heredan
de ninguna otra (Viaje y Asignatura) definen las cuatro operaciones persistentes básicas
(la operación "Materializar" será típicamente un constructor, que tomará tantos
parámetros como columnas haya en su correspondiente tabla de la base de datos).
Evidentemente, cada subclase debe redefinir las cuatro operaciones, ya que la
instrucción SQL necesaria para insertar un Conductor no es la misma que la utilizada
para insertar una Persona.
El patrón utilizado para transformar el diagrama de clases al diagrama relacional
afecta en gran medida a la implementación de las operaciones de persistencia:
a) Si hemos utilizado el patrón "un árbol de herencia, una tabla" (Figura 5), el
método para insertar en la base de datos un objeto de clase Coche sería:
public void insert() {
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
6
String SQL="Insert into Vehículos (Matrícula, Marca, Potencia) values
('" + mMatricula + "', '" + mMarca + "', " + mPotencia + ")";
// Nótese que
no insertamos valor en la columna "Toneladas", pq. corresponde a los camiones.
/*
y aquí, de alguna manera (ya veremos varias), ejecutar la
instrucción
*/
}
b) Si hemos usado el patrón "Una clase, una tabla" (Figura 2), tendremos que
insertar dos registros: uno en la tabla Vehículos (para que no se viole la regla de
integridad referencial) y otro en la tabla Coches:
public void insert() {
// Iniciar transacción, para garantizar que o se ejecutan las dos
instrucciones o no se ejecuta ninguna.
String SQL="Insert into Vehículos (Matrícula, Marca) values ('" +
mMatricula + "', '" + mMarca + "')";
// Ejecutar instrucción anterior
SQL="Insert into Coches (Matrícula, Potencia) values ('" + mMatricula +
"', " + mPotencia + ")";
// Ejecutar instrucción
// Finalizar transacción
}
2.2 Patrón "Fabricación pura"
Con este patrón se pretende aumentar la cohesión de las clases de la capa de
Dominio, mediante la delegación de las operaciones persistentes a clases asociadas. De
este modo, las clases de la capa de Dominio se responsabilizan únicamente de las
operaciones relacionadas con el enunciado del problema.
Lo que se hace es crear una clase "Fabricación pura" por cada clase de Dominio.
Cuando una instancia de una clase de Dominio quiere insertarse, se lo dice (le pasa un
mensaje) a su clase asociada.
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
7
Figura 8
Como puede intuirse a partir de la Figura 8, las clases de la capa de Dominio que
forman parte del enunciado del problema (Conductor, Viaje, etc.) quedan más simples,
más fáciles de leer, de comprender y se afectan menos por los cambios en la base de
datos; sin embargo, el acoplamiento del sistema aumenta.
En este caso, las clases de la capa de Dominio también deben tener métodos
persistentes, pero ahora mucho más sencillos. Por ejemplo, para insertar un Coche,
tendríamos lo siguiente:
class Coche {
// atributos de "dominio" (marca, etc.)
FPCoche mFP;
// métodos no persistentes
public void insert() {
mFP.insert(this);
}
}
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
8
2.3 Patrón "método-plantilla"
Mediante este patrón, se declaran en una superclase todos los métodos relacionados
con la persistencia, de la cual heredan todas las clases persistentes. La superclase dará
implementación a todos los métodos comunes a las clases persistentes, mientras que
declara como abstractas todas las operaciones cuya implementación depende de la
subclase.
Por ejemplo, tal vez todas las clases deban identificar al usuario actual ante la base
de datos antes de realizar una operación persistente. Si la implementación de esta
operación es común a todas las clases persistentes, entonces podría ser implementada en
la superclase. El resto de operaciones, como insert, update y delete, serían declaradas
como abstractas y tendrían que ser implementadas en cada clase persistente.
Figura 9
2.4 Combinaciones de patrones
Evidentemente, pueden utilizarse diferentes combinaciones de patrones de
asignación de responsabilidades. Por ejemplo, pueden utilizarse "fabricaciones puras"
que hereden de una clase "Método-plantilla"; o puede usarse el patrón "Fabricación
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
9
pura" para un fragmento del diagrama de clases, el "Tablas como objetos" para otro
trozo, el "Método-plantilla" para otro y una combinación para el resto.
Es importante resaltar que el patrón que se utilice para "traducir" el diagrama de
clases al diagrama relacional tiene mucha influencia en la implementación de las
operaciones persistentes.
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Macario Polo Usaola
10

Documentos relacionados