Modelado Orientado a Objetos Aplicado a Entornos de Desarrollo Relacionales Oscar Pastor, Emilio Insfrán, Vicente Pelechano Departament de Sistemes Informàtics i Computació Universitat Politècnica de València Camí de Vera, S/N, 46071 València
tlf: 34 + 6 3877350 fax. 34 + 6 3877357; e-mail: {opastor,einsfran,pele}@dsic.upv.es Resumen En este trabajo se presentan las ventajas del uso del Modelo Orientado a Objetos para el modelado conceptual y la implementación de sistemas de información. La mayoría de las metodologías actuales [Rum91], [Boo94], [BRJ96] carecen de guías precisas y rigurosas (desde el punto de vista del proceso de especificación) que nos permitan obtener productos finales a partir de los modelos conceptuales construidos. Nuestro trabajo intenta cubrir dichas carencias proporcionando un enfoque metodológico (OO-Method [Pas96], [Pas97]) que abarca la construcción de modelos de análisis y la definición de un patrón de traducción preciso de estos modelos a esquemas de bases de datos relacionales avanzados. Este artículo presenta un proceso de traducción fácil y preciso a la vez, que nos va a permitir implementar los modelos conceptuales de OO-Method sobre un entorno de desarrollo relacional (usando ORACLE v7 como servidor de datos y Developer/2000 como herramienta de desarrollo), explicando cómo trasladar los aspectos estáticos y dinámicos recogidos durante la fase de análisis, a estructuras relacionales y código para constituir el producto software final.
1. Introducción Muchas de las aplicaciones que se desarrollan actualmente utilizan técnicas de Análisis OO para obtener el modelo conceptual del sistema y entornos de desarrollo visuales con bases de datos relacionales para su implementación. En este tipo de aplicaciones, el modelo conceptual OO obtenido en la fase de análisis se traduce básicamente en un esquema relacional específico de la base de datos subyacente sin incluir la dinámica de la aplicación. Nuestro trabajo se centra en el Modelado Conceptual OO y en la generación automática de código a partir de los modelos obtenidos, incluyendo estática y dinámica, siguiendo el paradigma de la programación automática [Bal83]. Uno de los objetivos más interesantes es producir aplicaciones de calidad a partir de los modelos de análisis, utilizando la tecnología ofrecida por los entornos de bases de datos relacionales. Para conseguirlo, hemos desarrollado OO-Method [Pas96] [Pas97] un enfoque metodológico que proporciona entre otras características una estrategia de traducción bien definida que permite implementar los modelos conceptuales en entornos relacionales avanzados. Dicha estrategia utiliza las características (procedimientos almacenados, paquetes y disparos) que aportan estos nuevos entornos, y proporciona un patrón a utilizar por los diseñadores para generar el producto software final. Para mostrar esta estrategia hemos usado Oracle v7 como servidor principal y Developer/2000 como herramienta de desarrollo, aunque el enfoque puede ponerse en práctica en cualquier otro entorno de similares características. La propuesta metodológica OO-Method tiene dos fases principales: 1. Modelado conceptual: se recogen las propiedades esenciales que definen el sistema. Las principales características de esta fase son las siguientes: • Se obtienen tres modelos de análisis: modelo de objetos, dinámico y funcional. • Se obtiene una especificación formal y orientada a Objetos en OASIS [Pas92] [Pas95-1] que constituye un diccionario de datos de alto nivel y que se genera automáticamente a partir de los modelos de análisis. 2. Modelo de Ejecución: establece los detalles a considerar para implementar adecuadamente el Modelo Conceptual obtenido. Especifica claramente cómo trasladar cada una de las nociones recogidas en los modelos de análisis a estructuras asociadas a un entorno relacional avanzado, en este caso Oracle. Este Modelo de Ejecución se utilizará para generar el producto software final.
Este proceso de traducción sigue estos pasos: • generación de las sentencias CREATE restricciones de integridad
TABLE correspondientes, que incluyen atributos y
• generación de los procedimientos, paquetes y disparos de la BD (PROCEDURES, PACKAGES y TRIGGERS) correspondientes a la especificación OO. • generación de las ventanas necesarias (FORMS) para implementar la interfaz de usuario. • definición de roles, usuarios y privilegios otorgados para establecer el modelo final de protección. El trabajo que presentamos está estructurado como sigue a continuación. En el siguiente punto introducimos brevemente la metodología OO-Method mediante un ejemplo práctico que nos va a permitir exponer en el tercer punto cómo se implementa dicho ejemplo en Oracle, mostrando que la conexión entre los modelos de análisis y la implementación es lo suficientemente fácil como para ser usada por un grupo de desarrollo de aplicaciones Oracle. Este trabajo es la continuación de un proyecto de I+D entre la Universidad Politécnica de Valencia y la Conselleria de Sanidad y Consumo de la Generalitat Valenciana y cuyos primeros trabajos se han presentado en [Pas94] [Pas95-2].
2. La metodología: OO-Method OO-Method es una metodología OO de producción de software que ofrece un marco riguroso para la especificación de sistemas de información. OO-Method incluye: •
una notación gráfica para abordar la fase de análisis.
•
Oasis como un lenguaje de especificación formal y OO que constituye el repositorio de alto nivel del sistema.
•
la definición de un modelo de ejecución preciso que guía la fase de implementación.
En la fase de modelado conceptual determinaremos los componentes de la sociedad de objetos sin considerar ningún detalle de implementación. El problema a este nivel consiste en obtener una definición precisa del sistema a desarrollar. A continuación, el modelo de ejecución determinará las características del producto software final en términos del control de acceso a usuarios, activación de servicios, interfaz de usuarios, … es decir, todas aquellas propiedades dependientes de la implementación que no forman parte directa del espacio del problema. Para ilustrar los conceptos que aparecen en el trabajo vamos a hacer referencia a un Sistema de Administración de Personal. Observando el problema desde el punto de vista estático, los ejemplares de una clase Trabajo se identificarán con un único número, tendrán una descripción y una especialidad. Un trabajo particular podrá asignarse a un Centro y a un Programa Económico y estar en una situación (libre, contratado). Desde la perspectiva dinámica, tendremos eventos que crean ejemplares, eventos que los destruyen y otros eventos como contratar que relaciona un trabajo con una persona. Un trabajo se marca cuando se realiza una operación sobre él y no puede ser contratado hasta que un evento desmarcar ocurra. Más adelante iremos dando detalles del problema según sean necesarios.
2.1. Modelo Conceptual En la fase de análisis se construyen tres modelos del sistema: Modelo de Objetos, Dinámico y Funcional. Estos tres modelos describen la sociedad de objetos desde tres puntos de vista ortogonales pero complementarios.
2.1.1. Modelo de Objetos El Modelo de Objetos utiliza un Diagrama de Configuración de Clases (DCC) para definir y mostrar la estructura y comportamiento de todas las clases identificadas en el dominio del problema, así como sus relaciones. El DCC es un modelo semántico extendido. Una clase se representa gráficamente como una caja dividida en tres áreas: • Cabecera: contiene la declaración del nombre de la clase. • Parte Estática: contiene la definición de los atributos que representan el estado de los objetos de la clase. Los atributos podrán ser constantes, variables y derivados. Aquellos atributos utilizados para identificar objetos se subrayan.
• Parte Dinámica: contiene la declaración de los servicios1 de la clase. Cada servicio se declara especificando su nombre y argumentos (con sus tipos respectivos). Se distinguirá (gráficamente) entre los eventos de creación, borrado y los eventos compartidos con otras clases2. Las acciones son servicios que un objeto puede activar (actuando como agente) para consultar o modificar el estado de otro objeto. En la Figura 1, un objeto de la clase ADMIN puede crear o destruir un objeto de la clase TRABAJO, también se puede observar que el evento contratar es un evento compartido entre PERSONA y TRABAJO. Figura 1. Un evento compartido y una relación de agente.
Las relaciones estructurales que podemos modelar son la agregación (parte-de) y la herencia (es-un). En la Figura 2 se presenta la relación de agregación entre clases, incluyendo información sobre cardinalidades (mínimas y máximas) que determinan cuántos objetos componentes forman parte de un objeto compuesto e inversamente, cuántos objetos compuestos pueden estar compuestos de un objeto en particular.
Figura 2. Relación de agregación.
La herencia se define gráficamente trazando una flecha desde la subclase hacia la superclase correspondiente. Esta flecha de especialización puede etiquetarse con una condición de especialización o con los eventos correspondientes de activación/cancelación de la especialización temporal (rol). Ver Figura 3. En el modelo de objetos, una clase estará completamente definida por un conjunto de fórmulas que cubren el resto de propiedades, como son las:
Figura 3. Relación de herencia. Un caso general y un ejemplo.
• restricciones de integridad: establecen condiciones que el estado de los objetos debe satisfacer siempre (estáticas) o durante un determinado período de su existencia (dinámicas). • Derivaciones: sirven para calcular el valor de los atributos derivados. Dicho valor se determinará en función de otros que ya fueron definidos.
2.1.2. Modelo Dinámico En el Modelo Dinámico se representan aspectos relacionados con las secuencias posibles de eventos (vidas posibles) y la interacción entre objetos. Para representar estos aspectos, tenemos dos tipos de diagramas: El Diagrama de Transición entre Estados (DTE), uno por clase, y el Diagrama de Interacción entre Objetos (DIO), uno por aplicación.
Diagramas de Transición entre Estados Los DTE se utilizan para describir el comportamiento de los objetos estableciendo las sus vidas posibles. Una vida válida de un objeto, es una secuencia de eventos que caracteriza un comportamiento correcto para todos los objetos de la clase. En este contexto, los estados del DTE denotan situaciones3 en las que pueden encontrarse los objetos durante su existencia como consecuencia de la ocurrencia de eventos relevantes. Las transiciones representan cambios de 1 Servicios: Cuando hablemos de servicios de una clase nos referiremos a los servicios de los objetos de una clase, exceptuando el evento de creación que es de la clase. Además utilizamos el término servicio porque un objeto visto desde una perspectiva servidor ofrece a la sociedad de objetos eventos (unidades de proceso atómicas que ocurren en un instante de tiempo), transacciones (unidades de proceso moleculares compuestas de servicios que poseen las propiedades de no observabilidad de estados intermedio y la política de todo-o-nada durante su ejecución). 2 Eventos compartidos: eventos cuya ocurrencia afecta al estado de dos o más objetos de clases distintas en el mismo instante de tiempo. 3 Situación: conjunto de estados (valores de los atributos del objeto en un momento dado) a los que llegamos o que abandonamos mediante la ocurrencia de eventos, acciones o transacciones locales.
estado permitidos que pueden restringirse introduciendo condiciones. La especificación de una transición posee la sintaxis siguiente: evento | acción | transacción [if precondición] [when condición-de-control ] donde precondición es una condición definida sobre atributos del objeto que debe satisfacerse en el estado de partida para que el servicio pueda ocurrir. Una condición-de-control es Adm:contratar if situacion = 0 Adm:actualizar una condición que sirve para evitar el Adm:desmarcar if control 0 posible no-determinismo entre dos o TRA más transiciones que partiendo del Adm:crear_trabajo TRA mismo estado van a estados diferentes, estando etiquetadas con la Adm: marcar if control = 0 misma acción. En la Figura 4 se Adm:borrar_trabajo puede ver un ejemplo de DTE.
Diagrama de Interacción entre Objetos Figura 4. Diagrama de Transición de Estados para la clase TRABAJO. La interacción entre objetos se modela gráficamente mediante un Diagrama de Interacción entre Objetos (DIO). En el DIO podemos especificar dos interacciones básicas:
• disparos: son servicios de una clase que se activan de forma automática cuando se satisface una condición en un objeto dicha clase. • interacciones globales: son transacciones compuestas por servicios de clases diferentes. En el DIO representamos las clases como cajas con una cabecera en la que se incluye el nombre de la clase. Los servicios de los objetos de la clase se self::(condicion) Clase3 representan mediante pequeñas cajas Clase1 rectangulares dentro de la clase. Las cajas de evento4 los servicios se conectarán para definir los evento1 evento3 anteriores tipos de interacción. Los disparos se idIG definirán dibujando una flecha que vaya de la cabecera de una clase a la acción disparada y Clase2 etiquetada con la condición de disparo. Las idIG evento2 interacciones globales se introducen conectando los servicios que componen la interacción y nominándola mediante un identificador de interacción global común Figura 5. Diagrama de Interacción entre Objetos General. (idIG). En la Figura 5, puede ver un modelo general de DIO.
2.1.3 Modelo Funcional El propósito del Modelo Funcional es capturar la semántica asociada a los cambios de estado de forma fácil e intuitiva. En este modelo especificaremos mediante un diálogo interactivo el efecto de un evento sobre los atributos. El valor de cada atributo se modificará dependiendo de la acción ocurrida, de los argumentos del evento y del estado actual del objeto. OO-Method proporciona un modelo mediante el cual el analista sólo tiene que categorizar cada atributo de entre un conjunto predefinido de tres categorías no disjuntas. Estas categorías determinan qué información se necesita para determinar cómo cambia el valor del atributo ante la ocurrencia de determinados eventos. Las tres categorías de atributos son: cardinales, independientes del estado y enumerados. • Cardinales: sus eventos relevantes incrementan o decrementan su valor en una determinada cantidad. En la Figura 6 podemos ver el atributo cardinal numero_marcas de la clase Trabajo, con Adm:marcar como acción incrementadora. Clase: Trabajo Tipo de acción Incr.
Atributo : numero_marcas Categoría : cardinal Acción
Efecto
Adm:marcar
+1
Condición de Evaluación -
Figura 6. Atributo cardinal numero_marcas.
• Independientes del estado: tienen un valor que sólo depende de la última acción ocurrida. Una vez ha ocurrido una acción relevante el nuevo valor del atributo es independiente del valor que tenía antes. En la Figura 7 podemos ver el atributo independiente del estado control de la clase Trabajo, con Adm:marcar como acción portadora. Clase: Trabajo
Atributo : control Categoría: indep.estado
Acción
Efecto Acción
Adm: marcar
= uc
Condición de Evaluación
Figura 7. Atributo independiente del estado control
• Enumerados: Mediante la activación de una acción portadora se le asigna al atributo un valor de un dominio discreto.Vamos a considerar como ejemplo el atributo situación de la clase Trabajo. El valor de situación indica cual es la situación actual de un objeto de la clase trabajo (libre, contratado...). El evento portador contratar deja al objeto en el estado en el cual el atributo situación tiene el valor contratado. Ver Figura 8. Clase: Trabajo Valor Actual libre
Atributo : situación Acción Portadora Adm:contratar
Categoría: enumerado
Nuevo valor
Condición de Evaluación
contratado
Figura 8. Atributo enumerado situación.
La información que se obtiene al finalizar la construcción de los tres modelos constituye la especificación del sistema, y posee una representación textual en OASIS un lenguaje de especificación formal OO desarrollado en nuestro departamento. La especificación textual OASIS constituye un repositorio completo y formal del sistema, y además se puede obtener en cualquier momento ya que existen traductores que permiten obtenerla a partir de la información gráfica.
2.2. El Modelo de Ejecución El modelo de ejecución es un patrón genérico de comportamiento, aplicable a cualquier modelo conceptual construido siguiendo la estrategia propuesta por OO-Method. Una vez recogida en la especificación toda la información relevante del sistema, el modelo de ejecución explicará cómo se ejecuta/prototipa la sociedad de objetos en cualquier entorno de desarrollo. La idea consiste en dar una visión abstracta de un modelo de ejecución que determinará directamente el patrón de programación a seguir cuando un desarrollador (o una herramienta CASE) tenga que implementar un modelo conceptual. El modelo de ejecución tiene tres fases esenciales: 1. Control de acceso: en primer lugar, el objeto4 que desee conectarse al sistema deberá identificarse como miembro de la sociedad de objetos. 2. Vista del sistema: una vez se ha conectado un usuario (u otro objeto del sistema), éste tendrá una visión clara de la sociedad de objetos (qué clases de objetos puede ver, servicios que puede activar y atributos que puede consultar). 3. Activación de servicios: por último después de las fases anteriores, el objeto deberá ser capaz de activar cualquier servicio disponible en su visión del mundo, y de realizar las observaciones pertinentes. Cualquier petición de servicio se caracterizará por la siguiente secuencia de acciones: 1. Identificación del objeto: en primer lugar, se identificará el objeto que ha de servir la petición. La existencia de este objeto es una condición implícita para poder ejecutar el servicio, excepto si se trata del evento de creación5. Si el objeto existe se recuperarán los valores de los atributos que caracterizan su estado.
4 En nuestra visión de las aplicaciones los usuarios son también objetos. Lo que nos da una gran potencia a la hora de prototipar porque podemos introducirnos en el sistema como cualquier objeto y observar que visión de la sociedad tendría 5 Formalmente, el evento de creación es un servicio de un metaobjeto que representa a la clase, y que actúa como fábrica de objetos capaz de crear ejemplares individuales pertenecientes a la clase. Este metaobjeto (uno por cada clase) tiene como propiedades destacables el atributo población de la clase, el atributo siguiente oid y el evento de creación.
2. Introducción de los argumentos del evento: se introducen el resto de argumentos del evento a activar. 3. Corrección de la transición entre estados: verificaremos en el estado actual y para el servicio en cuestión que existe en el proceso una transición entre estados válida. 4. Satisfacción de precondiciones: Comprobaremos que se cumple la precondición asociada al servicio que va a ejecutarse. Si no se cumple se elevará una excepción informando que el servicio no puede activarse porque se ha violado su precondición. 5. Realización de las evaluaciones: una vez verificada la precondición, se hacen efectivas en el sistema de almacenamiento las modificaciones en el estado del objeto inducidas por el evento. 6. Comprobación de las restricciones de integridad en el nuevo estado: para asegurar que la activación del servicio deja al objeto en un estado válido, se debe comprobar que las restricciones de integridad (estáticas y dinámicas) se cumplen en el estado final resultante. 7. Comprobación de las relaciones de disparo: después de un cambio de estado válido, y como acción final, se deben verificar el conjunto de reglas condición-acción que representan la actividad interna del sistema. Si alguna de ellas se cumple, se disparará la correspondiente activación de servicio. Será responsabilidad del analista garantizar la terminación y confluencia de los disparos. Los pasos anteriores guiarán la implementación de cualquier aplicación para asegurar la equivalencia funcional entre la descripción del sistema recogida en el modelo conceptual y su reificación en un entorno de programación de acuerdo con el modelo de ejecución.
3. Implementación en ORACLE Vamos a presentar una implementación concreta del modelo de ejecución anterior. En este caso describiremos de forma simple, el conjunto de reglas necesarias para implementar un modelo conceptual OO de OO-Method en un entorno Oracle-v7. Resumidamente, por cada clase se genera una tabla ORACLE, cuya clave primaria estará formada por los atributos subrayados en la especificación gráfica de la clase. Cada atributo constante o variable se implementará como una columna en la tabla. Además, cada clase generará un usuario y un esquema. Las clases cuyos objetos sean activos (agentes de otros) generarán un rol. Este rol incluirá todos los privilegios concedidos a los usuarios. Cada clase tendrá un conjunto de formularios que se utilizarán para implementar las transacciones de los objetos de la clase, como veremos más adelante. El proceso de traducción lo podemos dividir en dos fases, en las cuales generamos: • El modelo lógico relacional. • Los paquetes, procedimientos, funciones, disparos y formularios necesarios para introducir la dinámica en nuestro sistema.
3.1. El Modelo de Datos Para obtener el modelo lógico relacional nos centraremos en dos secciones de la especificación de la clase: • Definición de atributos. • Restricciones de integridad estáticas. Cada clase se representa como una tabla dentro de su propio esquema. Las columnas de esta tabla serán cada uno de sus atributos constantes y variables. Cada ejemplar de la clase será una fila en la tabla. Los atributos derivados se representarán como una columna de la tabla o como una función dependiendo del diseñador. Si se ven como atributos virtuales, la función que calcule su valor tendrá que definirse en el paquete que, como veremos más tarde, incluirá los servicios del objeto. Si elegimos almacenarlos, se definirán de la misma manera que los otros, pero además será necesario declarar disparos que mantengan actualizado este campo (por ejemplo, disparos pre-insert y pre-update asociados a la tabla). Los atributos que componen el identificador de los objetos de la clase se representarán como la(s) columna(s) que constituye(n) la clave primaria de la tabla. Los atributos constantes por definición son not null. Los atributos variables se definirán como not null si deben introducirse obligatoriamente como un argumento del evento de creación o si se han declarado con un valor por defecto. Toda esta información se habrá introducido a nivel conceptual durante la definición de la clase. Las restricciones de integridad estáticas se representarán como
restricciones de la tabla, que se validarán sobre los atributos del objeto. Como ejemplo, podemos ver la siguiente sentencia CREATE TABLE para la clase Trabajos: CREATE TABLE Trabajos (nro_trabajo(6) CONSTRAINT pk_trabajo PRIMARY KEY CONSTRAINT ck_trabajo CHECK(nro_trabajo