1 La especificación de expresiones OCL en Modelos UML/OCL combinadosMg. Luis Reynoso Universidad de Castilla La Mancha, España Universidad Nacional del Comahue, Argentina UCM 2005
2 Índice Motivación La especificación de OCLCompletando diagramas de clases Conclusiones Acreditación UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
3 1. Motivación UCM 2005
4 Algunos conceptos RestriccionesUn modelo es un conjunto consistente, coherente de elementos del modelo que tienen características y restricciones Un repositorio del modelo es el almacenamiento de todos los elementos del modelo en una herramienta automatizada Un diagrama es una vista de los elementos del modelo en un modelo Los diagramas no siempre muestran todas las características de sus elementos Restricciones Elementos del modelo Antes de comenzar a explicar como construír modelos UML/OCL necesitamos comprender que es un modelo, debido a que es término es utilizado en distintos contextos con diferentes significados. En este documento, como así también en el desarrollo del curso, un modelo describe un sistema utilizando un lenguaje bien definido. Utilizamos la palabra modelo para referirnos a un conjunto consistente y coherente de elementos del modelo que tienen características y restricciones. Por ejemplo, las clases son elementos de un modelo, como lo son los estados. Los atributos y operaciones son características de clases, y las reglas de derivación y las condiciones invariantes son restricciones en atributos y clases, respectivamente. Debido a que la mayoría de los modelos son construídos utilizando herramientas, denominaremos al almacenamiento de todos los elementos del modelo como un repositorio del modelo. Para indicar una vista en el repositorio de los elementos del modelo utilizamos la palabra diagrama. Los elementos del modelo pueden ser mostrados en un diagrama o en muchos. Cuando un elemento está presente en el repositorio del modelo, este es parte del modelo. Warmer and Kleppe consideran que no es necesario mostrar todas las características de un elemento del modelo cuando este esta presente en un diagrama. Por ejemplo, una clase puede mostrarse en dos diagramas. En el primer diagrama, todos sus atributos podrían mostrarse pero no sus operaciones, sin embargo en el segundo diagrama, todas sus operaciones podrian mostrarse, pero no sus atributos. Estas definiciones pueden resumirse como se muestra a continuación: Un modelo es un conjunto coherente y consistente de elementos del modelo que tienen características y restricciones. Un repositorio de modelo es el almacenamiento para todos los elementos del modelo en una herramienta automatizada. Un diagrama es una vista de elementos del modelo en un modelo. Cualquier modelo debe ser una unidad integrada, consistente y coherente. Debe ser claro cómo las entidades mostradas en un diagrama se relacionan con otras partes visibles del modelo. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
5 Motivación la especificación del sistema OO se limitaba a especificar elementos del modelo y sus características Restricciones Los diagramas UML ponian enfasis en los elementos del modelo y sus características, y en menor medida en sus restricciones. El modelado, especialmente el modelamiento de software ha sido tradicionalmente sinonimo de producir diagramas. La mayora de los modelos consiste de un numero de graficos y de texto complementario. La informacion de tales modelos tiene tendencia a ser incompleta, informal, imprecisa y a veces inconsistente. Pero las restricciones son sumamente importantes, por ejemplo simplemente tengamos en cuenta la importancia que tienen las reglas de negocio de un sistema ! Podemos decir que existe una brecha en la especificacion del sistema, podemos especificar los eltos del modelo y sus caracteristicas pero con la notacion gráfica de UML no podemos expresar libremente todas las restricciones existentes en el modelo. Para cubrir esta brecha se define el lenguaje OCL. OCL son las siglas de Object Constraint Language. Es un lenguaje formal facil de leer y escribir. Ha sido desarrollado como un lenguaje de modelamiento de negocios dentro de la division de Seguros de IBM, y tiene su raz en el metodo Syntropy. Producción de diagramas Información incompleta, imprecisa... Elementos del modelo Lenguaje unificado de modelado UML esta en pleno proceso de estandarización con el Grupo de administración de objetos OMG UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
6 Motivación Cuando diseñamos un sistema OO, es necesario especificar un conjunto de restricciones semánticas: utilizar lenguaje natural conduce a ambiguedades no a todos les resulta familiar utilizar métodos formales UML no cuenta con la expresividad suficiente para modelar muchas restricciones Debido a estas razones ha surgido OCL (Object Constraint Language): permite describir restricciones (expresiones) sobre modelos UML permite definir y documentar modelos UML en forma más precisa Pero que otros problemas existen.... Cuando diseñamos un sistema OO es necesario especificar un conjunto de restricciones semánticas... Los diagrama UML como por ejemplo un diagrama de clases, diagramas de estados no constituyen una especificación lo suficientemente precisa y libre de ambigüedades de un sistema. Es decir, no son lo suficientemente refinada para proveer todos los aspectos relevantes de la especificacion [10]. Por ello los modeladores deben agregar restricciones semánticas adicionales al modelo que esta siendo definido. Tales restricciones son a veces descriptas en lenguaje natural. La practica ha mostrado que esto siempre resultara en ambiguedades. Con el objeto de escribir restricciones libres de ambiguedades se han desarrollado lenguajes formales. La desventaja de lenguajes formales tradicionales es que ellos no resultan amigables (o familiares) a aquellas personas que no tiene una solida formacion disciplinar en matematica. Esto hace que los lenguajes formales mas tradicionales sean difciles de utilizar por parte de un amplio conjunto de modeladores de sistemas o incluso por personas relacionadas a actividades de negocio. OCL ha sido desarrollado para cubrir esta brecha. OCL permite describir restricciones (expresiones) sobre modelos UML OCL permite definir y documentar modelos UML en forma más precisa. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
7 Motivación OCL (Object Constraint Language), definido por OMG, es:un lenguaje declarativo a partir del cual se establece que debe ser hecho por el sistema, y no como debe ser hecho un lenguaje tipado Todas las expresiones (y sus subexpresiones) tienen un tipo y se requiere conformidad de tipo un lenguaje de expresión puro (libre de efectos laterales) No modifica nada en el modelo El estado nunca cambiará debido a una expresión OCL Debido a que OCL es un lenguaje declarativo, este especica que hace el sistema pero no como lo hace. OCL es un lenguaje de expresión puro. Por consiguiente, se garantiza que toda expresión OCL es libre de efectos laterales; es decir la expresión no modifica nada en el modelo. Esto significa que el estado del sistema nunca cambia debido a una expresión OCL, aún cuando una expresión OCL pueda ser usada para especificar un cambio de estado, por ejemplo una post-condición. Todos los valores para todos los objetos no se ven modificados. Siempre que una expresión es evaluada, simplemente produce un valor. OCL no es un lenguaje de programación, no es posible escribir lógica de programas o flujo de control en OCL. No es posible con OCL invocar procesos o activar operaciones que no sean de consulta. OCL es un lenguaje tipado (typed language), de esta forma cada expresión de OCL tiene un tipo. En una expresión correcta de OCL todos los tipos usados deben tener conformidad de tipos. Por ejemplo, no es posible comparar un entero con un string. Cada Clasificador definido en UML representa un tipo distinto que puede ser utilizado en expresiones OCL. Como todo lenguaje de especificación todas las características de implementación están fuera del alcance de OCL y no pueden ser expresadas a partir de el. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
8 Motivación <
9 Usos de OCL OCL (Object Constraint Language)Especificar modelos precisos y completos a partir de la construcción de modelos UML/OCL combinados Diagramas sin expresiones / expresiones sin diagramas Especificar reglas de negocio Definir la semántica de UML Especificar PIM para MDA Como decia anteriormente un diagrama UML como por ejemplo un diagrama de clases, no constituye una especificacion sucientemente precisa y libre de ambiguedades de un sistema. Es decir, no es lo suficientemente refinada para proveer todos los aspectos relevantes de la Especificacion. Note que para obtener modelos que sean completos, son necesarios tanto los diagramas como las expresiones OCL. Sin las expresiones OCL, al modelo le faltara especificacion; sin los diagramas UML, las expresiones OCL no podrán referir a elementos de modelamiento, debido a que no hay manera en OCL de especificar clases y asociaciones. Solo al combinar diagramas y restricciones podemos especificar completamente el modelo. Las expresiones OCL nos permiten especificar reglas de negocio. Actualmente OCL es utilizado en el documento de Semántica de UML para especificar las reglas bien formadas del metamodelo UML. Las primeras versiones de UML fueron criticadas por numerosos autores debido a que carecía de definiciones precisas como una herramienta de modelamiento. Un uso distintivo de la construcción de modelos UMLOCL es MDA UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
10 MDA MDA (Model Driven Architecture) Arquitectura Dirigida por modelosdefine como los modelos en un lenguaje se pueden traducir a modelos en otro lenguaje La esencia de MDA es que los modelos son la base del desarrollo de software Warmer y Kleppe argumentan que estamos siendo testigos del nacimiento de un cambio de paradigma, el desarrollo de software desplaza su foco de código a modelos Recientemente, se ha denido una nueva version de OCL, la versión 2.0. Explicaremos en este curso esta versión de OCL. Existe una fuerte relación entre todos los estandares OMG. Una de las más recientes iniciativas de OMG es la Arquitectura Dirigida por Modelos (Model Driven Arquitecture, MDA [7]). La esencia del acercamiento MDA es que los modelos son la base del desarrollo de software. Por consiguiente, los modelos deberían ser buenos, sólidos, consistentes y coherentes. Aplicando la combinación de UML y OCL es posible construír modelos que reunen buenas características. MDA se esta tornando gradualmente en un importante aspecto del desarrollo de software. Muchas herramientas son, o al menos se reclaman que sean MDA-compliant, pero que es exactamente MDA? MDA es un framework que esta siendo construído bajo la supervisión de OMG. Define como los modelos definidos en un lenguaje pueden ser transformados en modelos en otros lenguajes. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
11 MDA El proceso MDA se divide en tres pasos:Construír un PIM (Platform Independent Model): Construír un modelo con alto nivel de abstracción, independiente de cualquier tecnología Transformar el PIM en uno o mas PSM (Platform Specific Models): Se especifica el sistema en término de los constructores de implementación disponibles de una tecnología específica (un modelo de base de datos, EJB, etc) Transformar el PSM a código PIM Un ejemplo de tal transformación en la generación de un esquema de base de datos desde un modelo UML siendo UML el lenguaje fuente, y SQL el lenguaje destino. El código fuente es considerado también un modelo. La generación de código desde un modelo UML es por consiguiente otra forma de transformación. El elemento clave para MDA es la importancia de los modelos en el proceso de desarrollo de software. El proceso MDA esta dividido en tres pasos: construír un modelo con un alto nivel de abstracción, independiente de cualquier tecnología de implementación. Este es llamado modelo independiente de la plataforma, Platform Independent Model, PIM. 2. transformar el PIM en uno o mas modelos que especifican el sistema en términos de los constructores que están disponibles en una tecnología de implementación específica; por ej, un modelo de base de datos o un modelo EJB (Enterprise Java Beans). Estos modelos son llamados modelos específicos de la plataforma, Platform Specic Models, PSMs. 3. Transformar los PSMs en código. El paso mas complejo es aquel en el cual un PIM es transformado en un PSM. La relación entre PIM, PSM, y código fuente, y las transformaciones entre ellos, es dibujado en el la figura PSM PSM código código UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
12 MDA El nivel de madurez del proceso de software se incrementa al construír modelos combinados UML/OCL Nivel 0: sin especificación Nivel 1: textual Nivel 2: texto con diagramas Nivel 3: modelos con texto Nivel 4: modelos precisos Nivel 5: solo modelos 1 ... 4 Dentro del proceso MDA, el foco del desarrollo de software esta puesto en producir un modelo del sistema de alto nivel. Muchas personas utilizan UML u otro lenguaje de modelamiento durante el desarrollo de software. Sin embargo, todos utilizan este lenguaje estandard de distintas maneras. Para crear orden y transparencia al tratar con modelos, Warmer & Kleppe definieron el concepto de niveles de madurez de modelamiento (modeling maturity levels, MMLs). Estos niveles se pueden comparar con los niveles CMM. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
13 Modeling Maturity Levels MMLsNivel 0: sin especificación la especificación del software esta presente en la conceptualización mental de los desarrolladores. Diferentes puntos de vista Adecuado para aplicaciones pequeñas Comprender el código Nivel 1: textual la especificacion del software esta escrita en documentos a partir de lenguaje natural. Ellos pueden ser mas o menos formales, enumerando cada requerimiento o cada funcion del sistema. la especificacion es ambigua, El desarrollador hace decisiones de negocio Es imposible conservar la especificacion actualizada 1 ... 4 Nivel 0: Sin especificacion En el nivel mas bajo, la especificacion del software esta solo presente en la conceptualización mental de los desarrolladores. Este nivel es común entre desarrolladores de software no profesional. Las características de este nivel son las siguientes: - existen puntos de vistas conflictivos entre desarrolladores, y entre desarrolladores y usuarios. esta manera de trabajar es adecuada para aplicaciones pequeñas;aplicaciones grandes o mas complejas necesitan realizar un buen dise - es imposible comprender el código si los desarrolladores se van de la organización (y siempre lo hacen [20]). - los desarrolladores realizan muchas elecciones de una manera ad hoc. Nivel 1: Textual En este nivel de madurez, la especificacion del software esta escrita en documentos a partir de lenguaje natural. Ellos pueden ser mas o menos formales, enumerando cada requerimiento o cada función del sistema. Este es el nivel mas bajo de desarrollo de software profesional. Las características de este nivel son: - la especificacion es ambigua, debido a que el lenguaje natural es inherentemente ambiguo. -El desarrollador hace decisiones de negocio basado en sus interpretaciones personales del texto. - Es imposible conservar la especicacion actualizada luego de cambiar el código. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
14 Modeling Maturity Levels MMLsNivel 2: Texto con diagramas la especificación del software esta provista por uno o más documentos escritos en lenguaje natural aumentados con diversos diagramas de alto nivel. el texto aún especifica el sistema, pero es mas facil comprenderlo debido a los diagramas. Nivel 3: Modelos con diagramas Un conjunto de modelos, i.e., diagramas o texto con significado muy específico y bien definido, forma la especificación del software Los diagramas o los textos formales son las representaciones reales del software. Los implementadores hacen decisiones de negocio. Nivel 2: Texto con Diagramas En este nivel de madurez de modelamiento, la especicacion del software esta provisto por uno o mas documentos escritos en lenguaje natural aumentados con diversos diagramas de alto nivel para explicar la arquitectura general y/o detalles mas complejos. Las caractersticas de este nivel son las siguientes: el texto aun especica el sistema, pero es mas facil comprenderlo debido a los diagramas. ademas todas las caractersticas del nivel 1 tambien son validas. Nivel 3: Modelos con Texto. Un conjunto de modelos, i.e., diagramas o texto con significado muy específico y bien definido, forma la especificación del software en el nivel de madurez de modelamiento 3. Texto adicional en lenguaje natural explica el background y la motivación de los modelos, y completa muchos detalles, pero los modelos son la parte mas importante que produce el análisis y diseño. Las características de este nivel son las siguientes: - Los diagramas o los textos formales son las representaciones reales del software. - La transicion de modelos a codigo es manual. - Es aun imposible (o muy difcil) conservar actualizada la especicacion luego de algún cambio en el código. - Los implementadores hacen decisiones de negocio, pero tienen menos influencia en la arquitectura del sistema 1 ... 4 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
15 Modeling Maturity Levels MMLsNivel 4: Modelos precisos el software es especificado por un modelo representando un conjunto consistente y coherente de texto y/o diagramas con significados muy específicos y bien definidos. los implementadores no realizan decisiones de negocio. mantener los modelos y el código actualizado es más facil Nivel 5: Solo Modelos Un modelo en nivel 5 es una descripción completa, consistente, detallada y precisa del sistema. A nivel 5, los modelos son lo sucientemente buenos para permitir la generación de codigo completo. Nivel 4: Modelos Precisos. En el nivel de madurez de modelamiento 4 el software es especificado por un modelo representando un conjunto consistente y coherente de texto y/o diagramas con significados muy específicos y bien definidos. Aquí también se utiliza texto escrito en lenguaje natural para agregar comentarios que explican el background y la motivación del modelo. Sin embargo, ellos tienen un nivel diferente de abstraccion. En este nivel: los implementadores no realizan decisiones de negocio. mantener los modelos y el codigo actualizado es esencial y facil. el desarrollo iterativo e incremental se facilita por la transformacion directa de modelo a codigo. Nivel 5: Solo Modelos. Un modelo en nivel 5 es una descripcion completa, consistente, detallada y precisa del sistema. A nivel 5, los modelos son lo sucientemente buenos para permitir la generacion de codigo completo. Los desarrolladores de software pueden conar en la generacion de modelo a codigo en la misma manera que hoy en da los implementadores conan en sus compiladores. Este nivel no se ha alcanzado en ninguna parte del mundo, y es parte de la futura tecnología. 1 ... 4 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
16 Motivación Los modelos UML no son lo suficientemente refinados para proveer todos los aspectos relevantes de la especificación de software OO OCL Restricciones Los diagramas UML ponian enfasis en los elementos del modelo y sus características, y en menor medida en sus restricciones. El modelado, especialmente el modelamiento de software ha sido tradicionalmente sinonimo de producir diagramas. La mayora de los modelos consiste de un numero de graficos y de texto complementario. La informacion de tales modelos tiene tendencia a ser incompleta, informal, imprecisa y a veces inconsistente. Pero las restricciones son sumamente importantes, por ejemplo simplemente tengamos en cuenta la importancia que tienen las reglas de negocio de un sistema ! Podemos decir que existe una brecha en la especificacion del sistema, podemos especificar los eltos del modelo y sus caracteristicas pero con la notacion gráfica de UML no podemos expresar libremente todas las restricciones existentes en el modelo. Para cubrir esta brecha se define el lenguaje OCL. OCL son las siglas de Object Constraint Language. Es un lenguaje formal facil de leer y escribir. Ha sido desarrollado como un lenguaje de modelamiento de negocios dentro de la division de Seguros de IBM, y tiene su raz en el metodo Syntropy. Definir PIM Nivel 4 en MML Elementos del modelo UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
17 2. La especificación de OCLUCM 2005
18 OCL 2.0 Object Management Group.UML 2.0 OCL Final Adopted Specification. UML 2.0 UML 2.0 Infrastructure Final Adopted Specification UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
19 Índice de la especif. de OCLContexto de una expresión Tipos de expresiones Diseño por contratos Navegaciones Tipos y conformidad de Tipos Propiedades de objetos Colecciones y Operaciones de colección Resolviendo propiedades UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
20 Expresiones OCL En OCL es posible especificar expresiones OCL.Podemos especificar expresiones OCL de diferente tipo o propósito Antes de dar ejemplos de estos tipos, necesitamos introducir, al mismo tiempo, otros conceptos básicos utilizados en una expresión OCL UML OCL UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
21 Contexto de una expresiónLas expresiones se pueden mostrar en un diagrama UML o no Es importante establecer como se conectan los diagramas UML y las expresiones OCL El vínculo entre una entidad en un diagrama UML y una expresión OCL se denomina definición de contexto de una expresión OCL La definición de contexto de una expresión OCL especifica la entidad del modelo para la que se define la expresión OCL. <
22 Tipo contextual e instancia contextualEl tipo contextual de una expresión OCL se corresponde con la entidad del modelo para la cual se define la expresión OCL. Nota: Utilizaremos un término de UML estandard, denominado Clasificador (classifier) para indicar con él que nos referimos a una clase, una interfaz, un tipo de dato o un componente. El tipo contextual de una expresión OCL, se escribe luego de la palabra reservada context. Una expresión OCL se evalúa para un único objeto, el cual es siempre una instancia del tipo contextual (instancia contextual). La definicion de contexto de una expresión OCL específica la entidad del modelo para el cual la expresión OCL esta definida. Usualmente este es un clasificador. Las expresiones OCL se escriben utilizando caracteres ASCII. Las expresiones OCL seran escritas en este documento con tipo de letra sans serif. A continuación de la palabra reservada context se detalla el nombre de un tipo para determinar el contexto de la expresión. Cada expresión OCL se escribe en el contexto de una instancia de un tipo específi co, utilizando el nombre self para referir a la instancia contextual. Nota: La instancia contextual es el punto principal para la interpretacion (entendibilidad) de una expresión OCL. Semejante al sujeto de una oracion en lenguaje natural. A veces es necesario referirnos explícitamente a la instancia contextual, por ello utilizamos la palabra self UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
23 Contexto y tipo de expresiónPersona nombre: String edad: Integer .... Tipo contextual context Person inv: self.edad > 18 etiqueta Instancia contextual UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
24 Tipos de expresiones OCLInvariantes Pre/post-condiciones Valores iniciales Valores derivados De consulta otros UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
25 invariantes Un invariante es una condición que debe ser verdadera para todas las instancias de un tipo específico en cualquier momento. Su tipo contextual es un clasificador Habitación context Habitación inv: self.número_de_camas <= 5 inv: número_de_camas <= 5 context h: Habitación inv: h.número_de_camas <= 5 número_piso : Integer número_habitación : Integer número_de_camas : Integer tipo : {A, B} Las expresiones OCL pueden ser parte de un Invariante, el cual es un restriccion estereotipada con <
26 Pre y postcondiciones Una precondición /postcondición es una condición que debe ser verdadera antes /después de la ejecución de una operación. La instancia contextual self es una instancia del tipo que es dueño de la operación. La declaración incluye la palabra context, seguida del contexto y de la declaración de la operación y el tipo. Las etiquetas pre y post declaran si se trata de una pre/postcondición. context Empleado::aumentarsalario( cantidad: Real ): Real pre: salario > 0 post: self.salario = + cantidad and result = self.salario La expresión OCL puede ser parte de una Precondicion o Postcondicion, la cuales son restricciones estereotipadas con <
27 Pre y postcondiciones En una postcondición, nos podemos referir a los valores de cada propiedad de un objeto en dos momentos en el tiempo: El valor de la propiedad al comienzo de la operación o método (utilizamos el El valor de la propiedad una vez que la operación o método se ha ejecutado. Nota: solo se permite en expresiones del tipo postcondicion ! context Empleado::aumentarsalario( cantidad: Real ): Real pre: salario > 0 post: self.salario = + cantidad and result = self.salario Valores Previos en Postcondiciones En postcondiciones, podemos referirnos a los valores en dos momentos en el tiempo: - el valor al comienzo de la operación - el valor una vez que la operación se ha completado El valor normal de un atributo, extremo de asociación u operación de consulta en una postcondición es el valor una vez que la operación se ha completado. Para referirnos al valor de una propiedad al comienzo de una operacion, utilizamos el en conjunto con el nombre de la propiedad, como en el ejemplo siguiente: El término salario se refiere al valor del atributo luego de la operacion. El término reere al valor del atributo age antes de la ejecucion de la operacion. Cuando necesitamos el valor previo de una operacion de consulta, el se utiliza luego del nombre de la operacion y antes de los parametros, como en el siguiente ejemplo: context Service::upgradePointsEarned(amount:Integer) post: calcPoints() = + amount El solo se permite en expresiones OCL que son parte de postcondiciones. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
28 Diseño por Contratos La definición de contratos en el principio de diseño por contratos se deriva del término legal de contratos (pero no es completamente análogo) En términos de OO un contrato es un medio de establecer las responsabilidades de un objeto de una manera clara y no ambigua. Un objeto es responsable de ejecutar servicios (las obligaciones) si y solo si ciertas estipulaciones (o derechos) son alcanzados. Clientes o consumidores / Proveedores Un contrato es ofrecido por un objeto independientemente de la presencia de un cliente Una manera efectiva de especificar restricciones sobre operaciones ó métodos es definir pre- y post- condiciones. Dentro de UML, es posible usar expresiones OCL para especificar precondiciones y postcondiciones de operaciones y métodos en clases, tipos e interfaces. El principio detrás de la utilización de pre- y postcondiciones es a veces referido como el principio de diseño por contratos. El diseño por contratos es comúnmente utilizado en el contexto de modelamiento orientado a objetos. La definición de contratos en el principio de diseño por contratos está derivado de la notación legal de contratos. Esto es, un acuerdo entre dos partes en la cual cada parte acepta obligaciones y en la cual cada parte tiene también derechos. En términos de orientación a objetos, un contrato es un medio de establecer las responsabilidades de un objeto de una manera clara y no ambigua. Un objeto es responsable de ejecutar servicios (las obligaciones) si y solo si ciertas estipulaciones (o derechos) son alcanzados. Un contrato es una especificación exacta de la interfaz de un objeto. Todos los objetos que usan los servicios ofrecidos son llamados clientes o consumidores. El objeto que ofrece los servicios es llamado proveedor. Aunque la noción de contrato se deriva del mismo término en el dominio legal, no es completamente análogo cuando es empleado en tecnología de objetos. Un contrato es ofrecido por un objeto independientemente de la presencia de un cliente. Pero cuando un cliente usa el servicio ofrecido en el contrato, el cliente se debe ajustar a las condiciones del contrato. Un contrato describe los servicios que son provistos por un objeto. Para cada servicio,se describe específicamente dos cosas. Las condiciones bajo las cuales el servicio será provisto. Una especificación del resultado del servicio que es provisto, si se cumplen determinadas condiciones. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
29 Ventajas de Diseño por ContratosCon el objeto de que los derechos y obligaciones no sean ambiguos es útil la especificación formal de los mismos. El proveedor conoce las condiciones exactas bajo las cuales su servicio puede ser usado.Si el cliente no respeta sus obligaciones, el proveedor no es responsable por las consecuencias.Esto significa que el proveedor puede asumir que las condiciones siempre se cumplen. El cliente conoce las condiciones exactas bajo las cuales puede o no usar los servicios ofrecidos. Si el cliente tiene cuidado de que las condiciones se cumplan, se garantiza la ejecución correcta del servicio. Con el objeto que derechos y obligaciones no sean ambiguos es útil la especificación formal de los mismos. Ventajas de Contratos. Tanto los clientes como los proveedores obtienen beneficios al ser especificados a partir de un contrato claro. - El proveedor conoce las condiciones exactas bajo las cuales su servicio puede ser usado. - Si el cliente no respeta sus obligaciones, el proveedor no es responsable por las consecuencias. - Esto significa que el proveedor puede asumir que las condiciones siempre se cumplen. -El cliente conoce las condiciones exactas bajo las cuales puede o no usar los servicios ofrecidos. - Si el cliente tiene cuidado de que las condiciones se cumplan, se garantiza la ejecución correcta del servicio. Pre-/Post-condiciones La interfaz que es ofrecida por un objeto consiste de un número de operaciones que puede ser realizada por el objeto. Para cada operación se especifican de acuerdo a precondicones -los derechos del objeto que ofrece el contrato-. Una precondición se debe cumplir en todo momento que la operación deba ejecutarse. Las obligaciones se especifican como postcondiciones. Una postcondición debe ser verdadera en el momento que la operación ha finalizado la ejecución. Un fallo de las pre- o post-condición significa que el contrato se ha quebrado. De allí, la importancia de los mecanismos de excepción en el principio de diseño por contratos. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
30 Diseño por contratos Derechos -> precondicionesObligaciones -> postcondiciones Invariantes UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
31 Expresiones para valores iniciales y derivadosUna expresión OCL puede ser utilizada para indicar el valor inicial (o derivado) de un atributo o un extremo de asociación. La expresión debe ser conforme al tipo resultante del atributo, ó En el caso que el contexto es un extremo final de asociación la expresión debe ser conforme con el clasificador en tal extremo final context Persona:: salario : Integer init: 500 derive: (50 * antigüedad) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
32 Expresiones de consultaUna expresión OCL puede ser utilizada para indicar el resultado de una operación de consulta. Esto se realiza utilizando la siguiente sintaxis: context Typename:: operationName(parameter1: Type1, ...) : ReturnType body: -- alguna expresión No cambian el estado del sistema, solo retornan un valor o conj. de valores. La expresión debe ser conforme con el tipo de la operación. Al igual que en pre y postcondiciones los parámetros pueden ser utilizados en la expresión. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
33 Tipos de expr. OCL Invariantes (inv:) Precondiciones (pre:)post-condiciones (post:) Valores iniciales (init:) Valores derivados (derive:) De consulta (body:) otros UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
34 Navegaciones Las navegaciones nos permiten hacer referencia a objetos que están asociados con la instancia contextual Hay dos tipos de navegaciones simples y combinadas Requerimiento: la cantidad de huéspedes de una habitacion no debe superar la cantidad de camas de la habitación. Habitación Huésped número_piso : Integer * nombre : String número_habitación : Integer edad : Integer número_de_camas : Integer sexo : {hombre, mujer} tipo : {A, B} +huéspedes UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
35 Navegaciones context Habitacióninv: self.huespedes->size() <= self.número_de_camas Navegamos una relación cuando se utiliza en una expresión el nombre de rol (del extremo opuesto de una relación) que vincula la clase donde se define la expresión con otra clase del diagrama. Habitación Huésped número_piso : Integer * nombre : String número_habitación : Integer edad : Integer número_de_camas : Integer sexo : {hombre, mujer} tipo : {A, B} +huéspedes UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
36 Navegaciones context Habitacióninv: self.Huesped->size() <= self.número_de_camas Navegamos una relación cuando se utiliza en una expresión el nombre de una clase (si el modelador ha omitido el nombre de rol de la asociación) Habitación Huésped número_piso : Integer * nombre : String número_habitación : Integer edad : Integer número_de_camas : Integer sexo : {hombre, mujer} tipo : {A, B} UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
37 Colecciones La manipulación de colecciones !El tipo Collection es un tipo abstracto, con tipos de colección concretos como sus subtipos. Set (Conjunto), OrderedSet (Conjunto ordenado) Bag (Bolsa) Sequences (Secuencias) context Habitación inv: self.Huesped->size() <= self.número_de_camas UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
38 Navegaciones CombinadasLas navegaciones no se limitan a una única asociación. Las expresiones OCL pueden estar encadenadas navegando un conjunto de asociaciones context Vuelo inv: self.avion.tipo.cant_de_asientos >= self.pasajeros->size() Avion id_avion : Integer +avion Tipo_Avión Vuelo +tipo 1 1 1..* 1..* tipo : String id_vuelo : Integer serie : String origen : String 1..* 1..* 1 1 cant_de_asientos : Integer destino : String cant_de_tripulantes : Integer * * * * +pasajeros 1..* 1..* Pasajeros id_pasajero : Integer +tripulantes pasaporte : String 1..* 1..* UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
39 Navegaciones CombinadasPreguntas: Hacia cuantas clases he navegado? Que tipo de navegaciones hay? Cuantas? context Vuelo inv: self.avion.tipo.cant_de_asientos >= self.pasajeros->size() Avion id_avion : Integer +avion Tipo_Avión Vuelo +tipo 1 1 1..* 1..* tipo : String id_vuelo : Integer serie : String origen : String 1..* 1..* 1 1 cant_de_asientos : Integer destino : String cant_de_tripulantes : Integer * * * * +pasajeros 1..* 1..* Pasajeros id_pasajero : Integer +tripulantes pasaporte : String 1..* 1..* UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
40 Navegaciones y coleccionesLos tipos de colecciones juegan un importante rol en las expresiones OCL ! Una única navegación resulta en un conjunto (Set), navegaciones combinadas en un Bag, navegaciones sobre asociaciones adornadas con {ordered} resultan en un OrderedSet. ! Las navegaciones definen acoplamiento de objetos. El acoplamiento debe reducirse en todo sistema OO. Cuan lejos están otros objetos...? UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
41 Navegaciones a clases de asociaciónPara especificar la navegación a clases de asociación, OCL utiliza un punto y el nombre de la clase de asociación context Persona inv: self.job .... Persona Compañía nombre : String +empleado +empleador nombre : String edad : Integer numerodeEmpleados : Integer esDesocupado : Boolean 0..* 0..* 0..* 0..* Job titulo : String diaComienzo : Date salario : Integer UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
42 Navegaciones desde clases de asociaciónEs posible navegar desde la clase de asociación a los objetos que participan en la asociación. context job inv: self.empleado.edad > 21 Persona Compañía nombre : String +empleado +empleador nombre : String edad : Integer numerodeEmpleados : Integer esDesocupado : Boolean 0..* 0..* 0..* 0..* Job titulo : String diaComienzo : Date salario : Integer UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
43 Sobre Tipos y conformidad de tiposUCM 2005
44 Tipos básicos En OCL, se definen un número de tipos básicos, los cuales están disponibles para el modelador en todo momento. Estos tipos son valores predefinidos y son independientes de cualquier modelo de objetos. Tipos Básicos: Boolean: true, false Integer :1, -5, 2, 34, 26524, ... Real: 1.5, 3.14, ... String: ‘esto es un string‘ Colecciones (definidas anteriormente) Operaciones definidas en los tipos Integer: *, +, -, /, abs(), etc. Real: *, +, -, /, etc. Boolean: and, or, xor, not, implies, if-then-else-endif String: concat(), size(), substring() UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
45 Tipos Básicos Cada expresión OCL se escribe en el contexto de un modelo UML. En UML un clasificador (classifier) es una clase, o una interfaz, un tipo de dato. Todos los clasificadores de un modelo UML son tipos que pueden ser utilizados en las expresiones OCL que estén asociadas a dicho modelo. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
46 Tipos Enumerados Las enumeraciones son tipos de datos en UML y tienen un nombre. Una enumeración define un número de literales, que son valores posibles de la enumeración. En OCL podemos referirnos a los valores de una enumeración. context Persona inv: genero = Genero::masculino <
47 La especificación de expresiones OCL en Modelos UML/OCL combinados Día 2UCM 2005
48 Contenidos principales del día 1OCL es un lenguaje declarativo, tipado, de expresiones puro. Utilidad de OCL. La importancia de los Modelos UML/OCL combinados Modelos PIM lo suficientemente abstractos, precisos y con un alto nivel de madurez. Contexto de una expresión: tipo contextual, la instancia contextual. Tipos de expresiones OCL: invariantes, pre y postcondiciones, valores iniciales o derivados, de consulta. Tipos colección (set, orderedset, bag, sequence) Navegaciones simples y combinadas Notación flecha Operaciones de colección Definen acoplamiento de objetos UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
49 Operación if-then-else en el tipo Booleanif
50 Ejemplo de expresión de consultacontext CursoUCM::obtenerCantidadDeAlumnos(): Integer body: self.alumnos->size() context CursoUCM inv: self.obtenerCantidadDeAlumnos() > 15 CursoUCM Alumno nombre : String DNI : Integer modalidad : Mod +alumnos nombre : String apellido : String obtenerCantidadDeAlumnos() : Integer 1..* 1..* esbecado : Boolean obtenerAlumnosbecados() : Set(Alumnos) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
51 Ej de expresión init para un extremo de asociaciónMovimiento mImporte: Real mConcepto: String mFecha: Fecha context Tarjeta::mMovs: Set (Movimiento) init: Set{} 0..* mMovs Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero 1 mtitular 0..* mtarjetas Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
52 Navegaciones que resultan en un SetLas navegaciones simples resultan en un Set El valor de una navegación simple es un objeto o conjuntos de objetos, dependiendo de la multiplicidad del extremo final de la asociación. context Compañía inv: self.gerente.esDesocupado = false inv: self.empleados->notEmpty() .... self.gerente->size() = 1 +gerente Persona 1 1 Compañía nombre : String edad : Integer nombre : String esDesocupado : Boolean * * +empleados UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
53 Navegaciones que resultan en Sets o BagsW&K: When you navigate through more than one association with multiplicity greater than 1, you end up with a bag. OCL specification: combined navigations results in a Bag Porque las navegaciones combinadas resultan en un bag? +asociados Medico +trabaja ObraSocial +obras_sociales +afiliados Afiliado 1..* 1..* 1..* 1..* 1..* 1..* 1..* 1..* context Medico ... self.trabaja.afiliados UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
54 Navegaciones que resultan en Sets o BagsQue sucede si queremos obtener el número de potenciales pacientes de un médico, pero quisiéramos contar tantas veces a un afiliado como obras sociales éste tenga. +asociados Medico +trabaja ObraSocial +obras_sociales +afiliados Afiliado 1..* 1..* 1..* 1..* 1..* 1..* 1..* 1..* Obra1 af1 med1 af2 obra2 Context Medico ... self.trabaja.afiliados af3 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
55 Navegaciones que resultan en Sets o BagsQue sucede si queremos obtener el número de potenciales pacientes de un médico, y pero NO queremos contar tantas veces a un afiliado como obras sociales éste tenga. +asociados Medico +trabaja ObraSocial +obras_sociales +afiliados Afiliado 1..* 1..* 1..* 1..* 1..* 1..* 1..* 1..* Obra1 af1 med1 af2 obra2 Context Medico ... self.trabaja.afiliados->asSet() af3 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
56 Navegaciones que resultan en OrderedSets y SequencesCuando navegamos una asociación etiquetada con {ordered}, la colección resultante es de tipo OrderedSet, Cuando navegamos mas de una asociación y uno de ellas esta etiquetada con {ordered}, la colección resultante es una secuencia. context escuelaInternacional ... self.numero = ‘VIII’ and self.cursos->at(3) Curso EscuelaInternacional nombre : String {ordered} numero : Integer modalidad : Mod fecha : Date 1..* +cursos 1..* obtenerCantidadDeAlumnos() : Integer obtenerAlumnosbecados() : Set(Alumnos) orderedSet UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
57 Conformidad de Tipos OCL es un lenguaje tipado.Una expresión OCL en el cual todos los tipos son conformes (es decir hay conformidad de tipos) es una expresión válida, sino existirá un Error de conformidad de tipo!! 1 + ‘motocicleta’ 23 * falso Un tipo es conforme con su(s) supertipo(s) Herramientas: IBM parser, Dresden Toolkit, TU Munich Tool, ModelRun, Bremer USE, Octupus UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
58 Reglas de Conformidad de TiposLos tipos Set(X), Bag(X) y Sequence(X) son todos subtipos de Collection(X) Reglas de conformidad de tipos: T1 es conforme a T2 cuando ellos son idénticos T1 es conforme a T2 cuando T1 es un subtipo de T2 Collection(T1) es conforme a Collection(T2), cuando T1 es conforme a T2. Esto es verdadero para Set(T1)/Set(T2), Sequence(T1)/Sequence(T2), Bag(T1)/Bag(T2) La conformidad de tipo es transitiva UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
59 ejemplos de Conformidad de TiposSi Bicycle y Car son dos subtipos de Transport entonces: Set(Bicycle) es conforme a Set(Transport) Set(Bicycle) es conforme a Collection(Bicycle) Set(Bicycle) es conforme a Collection(Transport) Ejemplo: Set(Bicycle) NO es conforme a Bag(Bicycle) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
60 Accediendo a propiedades de objetosUCM 2005
61 propiedades Una propiedad es: Un atributo Un extremo de asociaciónUna operación/método libre de efectos laterales Una operación o método se define como libre de efectos laterales si no modifica el estado del sistema Notación “Punto”: El valor de una propiedad en un objeto se especifica en una expresión OCL con un punto seguido del nombre de la propiedad self.mEdad >= 17 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
62 Propiedad: Atributo Por ejemplo, la siguiente expresión OCL: “la edad de cliente es mayor o igual a 17 años”: context Cliente inv: self.mEdad >= 17 El valor de la subexpresión self.mEdad es el valor de mEdad en la instancia particular de Cliente identificada por self. El tipo de la subexpresión self.mEdad es el tipo del atributo mEdad, que es un tipo Integer estándar. Cliente mNombre: String mApellidos: String mEdad: Integer lim_max_mov:Integer UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
63 Propiedad: OperacionesPara referirnos a una operación o método que no tiene parámetros, se requiere especificar una lista vacía de argumentos: context Producto Inv: self.obtenerprecio() > 0 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
64 Propiedad: Extremos finales de asociacionesA partir de un objeto específico, es posible navegar una asociación en el diagrama de clase para referirnos a otros objetos y sus propiedades. objeto.nombredelextremoFinal El valor de la subexpresión es un objeto o conjuntos de objetos, dependiendo de la multiplicidad del extremo final de la asociación. context Compañía inv: self.gerente.esDesocupado = false inv: self.empleados->notEmpty() En self.empleados->notEmpty() estamos accediendo a la propiedad notEmpty en el conjunto self.empleados +gerente Persona 1 1 Compañía nombre : String edad : Integer nombre : String esDesocupado : Boolean * * +empleados UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
65 Combinando propiedadesLas propiedades se pueden combinar para escribir expresiones más complejas. Una regla importante es que una expresión OCL siempre se evalúa a un objeto específico de un tipo especifico. Luego de obtener el resultado, es posible aplicar otra propiedad para obtener un nuevo resultado. Cada expresión OCL puede ser leída y evaluada de izquierda a derecha context Cliente inv: self.lim_max_mov >= self.cuentas.mMovs->size() Cliente mNombre: String mApellidos: String mEdad: Integer lim_max_mov:Integer Cuenta /msaldo: Real 0..* Movimiento mImporte: Real mConcepto: String mFecha: Date mTitulares 0..* 1..* cuentas mMovs UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
66 Colecciones y operaciones de colecciónUCM 2005
67 Colecciones Siempre que una navegación resulta en una colección de objetos podemos utilizar operaciones de colección para manipular la colección. El tipo Collection es un tipo predefinido en OCL. El tipo esta definido en conjunto con operaciones predefinidas. Las operaciones de colección nunca modifican las colecciones. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
68 Colecciones Hay tres formas de obtener colecciones:(1) A partir de un literal Ejemplo de literales: Set {1, 2, 3, 5} OrderedSet {1 , 2, 3 , 5 , 7 , 11, 13, 17 } Sequence {1 , 2, 3 , 5 , 7 , 11, 13, 17 }, Bag {1, 2, 3, 2, 1} UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
69 Colecciones (2) A partir de una navegación (que resulte en una colección): context Compañía inv:self.empleados ... (3) A partir de operaciones en colección que resulten en nuevas colecciones. collection1->union(collection2) +gerente Persona 1 1 Compañía nombre : String edad : Integer nombre : String esDesocupado : Boolean * * +empleados UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
70 Operaciones de coleccionesOCL define muchas operaciones en tipos de colección. Estas operaciones permiten contar con una manera flexible y poderosa de proyectar nuevas colecciones desde colecciones existentes. Notación flecha “->”: colección->operaciónDeColeccion() Las operaciones son: size, select, reject, collect, forAll, exists, etc UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
71 Operación Size La operación predefinida size() nos permite obtener la cantidad de elementos de una colección. context Cliente inv: self.mCuentas->size() < 10 mCuentas Cuenta /msaldo: Real 0..* mTitulares 1..* Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero mCuentaNómina UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
72 Operación Select Permite obtener un subconjunto específico de una colección. select es una operación sobre una colección y es especificada utilizando la sintáxis de flecha: collection->select( expresión booleana) El resultado es una colección que contiene todos los elementos de la colección origen para los cuales es verdadera la expresión booleana. Para encontrar el resultado de esta operación, se evalúa la expresión para cada elemento de la colección. Si el resultado de la evaluación es verdadero para un elemento, este se incluye en la colección resultante. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
73 Select (cont.) Empleado context Proyecto inv: self.participa -> select (edad > 50) ->notEmpty() El contexto de la expresión en el argumento select es el del elemento de la colección en el cual el select es invocado. inv: self.participa-> select (e: Empleado | e.edad > 50) ->notEmpty() inv: self.participa-> select (e | e.edad > 50) ->notEmpty() nombre : String Proyecto apellido : String nombre : String edad : Integer esCasado : Boolean * * +participa * * presupuesto : Integer +trabaja_en diaNacimiento : Date UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
74 Forma general de especificar una oper. de coleccióncolección->operación( v: Type | expresión-booleana-utilizando-v ) colección->operación( v | expresión-booleana-utilizando-v ) colección->operación( expresión-booleana) “ v ” un iterador, es una referencia a los objetos en la colección El contexto para la expresión del argumento de operación es el contexto que le corresponde al elemento de la colección en el cual la operación es invocada. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
75 Operador reject El operador reject permite obtener un subconjunto de todos los elementos de una colección para el cual la expresión se evalúa a falso. context Proyecto inv: self.participa -> reject ( esCasado ) ->isEmpty() ... colección de las personas que no están casadas es vacía. Empleado nombre : String Proyecto apellido : String nombre : String edad : Integer * * presupuesto : Integer esCasado : Boolean * * +participa +trabaja_en diaNacimiento : Date UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
76 Select y reject La operación reject está disponible en OCL por conveniencia, debido a que cada reject se puede escribir como un select con la expresión booleana negada. collection->reject( v | expresión-booleana-utilizando-v ) collection->select( v | not (expresión-booleana-utilizando-v ) ) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
77 Operador collect El operador collect se utiliza cuando queremos derivar una nueva colección a partir de otra, pero que contiene objetos diferentes de la colección original. Por ejemplo: deseamos obtener una colección de las fechas de cumpleaños de los empleados de la compañía: self.empleados->collect( fechaNacimiento ) self.empleados->collect( emp : Empleado | emp.fechaNacimiento ) Empleado nombre : String Proyecto apellido : String edad : Integer nombre : String * * presupuesto : Integer esCasado : Boolean * * +participa +trabaja_en diaNacimiento : Date UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
78 Operador collect La colección resultante no es un conjunto es un bag.Para convertir el bag en un set: self.empleados->collect( fechaNacimiento )->asSet() Nota: El Bag resultante de la operación collect siempre tiene el mismo tamaño que la colección original. Empleado nombre : String Proyecto apellido : String nombre : String edad : Integer * * presupuesto : Integer esCasado : Boolean * * +participa +trabaja_en diaNacimiento : Date UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
79 Forma resumida de collectExiste una forma resumida de escribir la operación collect y que hace que las expresiones OCL sean mas fáciles de leer (?). En lugar de escribir: self.empleados->collect( fechaNacimiento ) es posible escribir: self.empleados.fechaNacimiento Esto es válido para cualquier propiedad que esté definida como una propiedad de los objetos pertenecientes a una colección collection.propertyname collection->collect(propertyname) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
80 Ej. de collect El saldo de toda cuenta debe ser siempre mayor o igual a cero (el saldo se calcula como la suma del importe de sus movimientos). context Cuenta inv: self.mMovs->collect(imImporte)->sum() > 0 mCuentas Cuenta /msaldo: Real 0..* mTitulares 1..* Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero mCuentaNómina 0..* Movimiento mImporte: Real mConcepto: String mFecha: Fecha mMovs 0..* UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
81 Ej. de collect El saldo de toda cuenta debe ser siempre mayor o igual a cero (el saldo se calcula como la suma del importe de sus movimientos). context Cuenta inv: self.mMovs.imImporte->sum() > 0 mCuentas Cuenta /msaldo: Real 0..* mTitulares 1..* Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero mCuentaNómina 0..* Movimiento mImporte: Real mConcepto: String mFecha: Fecha mMovs 0..* UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
82 Operación ForAll Este operador permite especificar una expresión booleana que debe ser verdadera para todos los elementos de una colección. La exp. forAll tiene como resultado un valor booleano. context Proyecto inv: self.participa->forAll( p: Empleado | p.edad <= 65) Empleado nombre : String Proyecto apellido : String edad : Integer nombre : String esCasado : Boolean * * +participa * * presupuesto : Integer +trabaja_en diaNacimiento : Date UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
83 Operación ForAll El operador forAll tiene una variante extendida en el cual se utiliza más de un iterador. Ambos iteradores iterarán sobre la colección completa. Efectivamente esto constituye el operador forAll en el producto cartesiano de la colección. context Proyecto inv: self.participa-> forAll (e1, e2: Empleado | e1<> e2 implies e1.apellido <> e2.apellido) Empleado nombre : String Proyecto apellido : String edad : Integer nombre : String * * presupuesto : Integer esCasado : Boolean * * +participa +trabaja_en diaNacimiento : Date UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
84 Operación Exists Muchas veces es importante saber si al menos para un elemento de una colección se verifica una condición: context Proyecto inv: self.participa->exists( p | p.nombre = ‘Jack’) Empleado nombre : String Proyecto apellido : String edad : Integer nombre : String * * * * presupuesto : Integer esCasado : Boolean +participa +trabaja_en diaNacimiento : Date mCuentas Cuenta /msaldo: Real 0..* mTitulares 1..* Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero mCuentaNómina context Cuenta inv: self.mTitulares->exists(c : Cliente | c.mEdad>=18) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
85 notEmpty() En el caso de una asociación con multiplicidad 0..1 es útil verificar si existe un objeto o no cuando navegamos la asociación context Persona inv: self.esposa->notEmpty() implies self.esposa.genero = Genero::femenino Persona <
86 Operación iterate() Collection->iterate( element: Type 1 ;acum : Type2 =
87 Operación iterate() Las operaciones reject, select, forAll, exists, collect pueden definirse en término de iterate(). Por ejemplo podríamos definir la operación collect. también utilizaremos para ello la operación including() Set{1, 2}->including(3) retornaría Set{1, 2, 3} collection->collect(x : T | x.property) -- es idéntico a: collection->iterate(x : T; acc : T2 = Bag{} | acc->including(x.property)) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
88 El metamodelo de OCL En el metamodelo de OCL se define la jerarquía de colecciones de OCL y las operaciones de colección collection set orderedset bag sequence UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
89 Operación count() self-> count(object)El número de veces que la colección (self) incluye el objeto “object” Bag{1, 2, 3, 2, 4, 2}->count(2) = 3 La regla bien formada de la operación count() en el metamodelo de OCL count(object: T): Integer post: result = self->iterate( elem; acc : Integer = 0 | if elem = object then acc + 1 else acc endif) Diferencia entre count() y size() ! UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
90 Otras Operaciones self-> includes(Object)Verdadero si el objeto es un elemento de self, falso en otro caso Ejemplo: Set{1,2,3, 5, 4}->includes(2) retorna true. includes(object: T): Boolean post: result = (self->count(object) > 0) self-> excludes(Object) Verdadero si el objeto no es un elemento de self, falso en otro caso Ejemplo: Set{1, 3, 5, 4}->excludes(2) retorna true. excludes(object: T): Boolean post: result = (self->count(object) = 0) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
91 Ejemplo de includes context EscuelaInternacional::obtenerAlumnosDeUnCurso(c: CursoCacic): Set(Alumno) body: if cursos->includes(c) then c.alumnos else Set{} endif Alumno DNI : Integer EscuelaInternacional nombre : String numero : Integer apellido : String fecha : Date esbecado : Boolean obtenerAlumnosDeUnCurso(c : CursoCacic) : Set(Alumno) +alumnos 1..* 1..* 1..* 1..* +cursos CursoCacic nombre : String modalidad : Mod obtenerCantidadDeAlumnos() : Integer obtenerAlumnosbecados() : Set(Alumnos) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
92 Otras Operaciones self-> including( Object)Retorna una nueva colección compuesta de la colección self más el elemento objeto object Ejemplo Set{1, 2}->including(3) retornaría Set{1, 2, 3} including(object: T): Set(T) post: result ->forAll(elem | self->includes(elem) or (elem = object)) post: self ->forAll(elem | result->includes(elem)) post: result ->includes(object) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
93 Otras operaciones self-> intersection( colección_de_objetos ),self->union ( colección_de_objetos ), UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
94 Includes e includesAll{subset} 1 piloto 1..* vuelos Vuelo Persona tripulación 1..* azafatas {subset} Context Flight inv: self.tripulacion -> includes(self.piloto) inv: self.tripulacion -> includesAll(self.azafatas) lider_proyecto 0..1 0..1 gerencia Persona {or} Proyecto 0..1 pertenece UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
95 Operaciones en OrderedSets y SequencesExisten varias operaciones definidas para OrderedSet y Sequence que se relacionan con el ordenamiento de elementos. Las operaciones first y last nos permiten obtener el primer y último elemento respectivamente: Sequence{‘a’,’b’,’c’,’c’,’d’,’e’}->first() = ‘a’ OrderedSet{‘a’,’b’,’c’,’d’}->last() = ‘d’ La operación at resulta en el elemento en la posición especificada en su argumento Sequence{‘a’,’b’,’c’,’c’,’d’,’e’}->at(3) = ‘c’ UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
96 Operaciones en OrderedSets y SequencesExisten varias operaciones definidas para OrderedSet y Sequence que se relacionan con el ordenamiento de elementos. Las operación indexOf resulta en un valor entero que indica la posición del elemento en la colección. Cuando un elemento esta presente mas de una vez en la colección, el resultado es la posición del primer elemento. Nota: el indice comienza con 1, no cero ! Sequence{‘a’,’b’,’c’,’c’,’d’,’e’}->indexOf(‘c’) = 3 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
97 Operaciones en OrderedSets y SequencesExisten varias operaciones definidas para OrderedSet y Sequence que se relacionan con el ordenamiento de elementos. La operación subsequence puede aplicarse a secuencias solamente, y resulta en la sequencia de elementos desde el indice inferior al indice superior, inclusive, de la colección original Sequence{‘a’,’b’,’c’,’c’,’d’,’e’}->subSequence(3,5) = Sequence{’c’,’c’,’d’} Una operación similar se define para OrderedSet denominada subOrderedSet OrderedSet{‘a’,’b’,’c’,’d’}->subOrderdSet(2,3) = OrderedSet{’b’,’c’} UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
98 Operaciones en OrderedSets y SequencesExisten varias operaciones definidas para OrderedSet y Sequence que se relacionan con el ordenamiento de elementos. Las operaciones append y prepend agregan un elemento a la secuencia como el primer o último elemento Sequence{‘a’,’b’,’c’,’c’,’d’,’e’}->append(‘X’) = Sequence{‘a’,’b’,’c’,’c’,’d’,’e’,’X’} Sequence{‘a’,’b’,’c’,’c’,’d’,’e’}->prepend(‘X’) = Sequence{‘X’,‘a’,’b’,’c’,’c’,’d’,’e’} UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
99 Otras Operaciones Ver Apéndice A del documento del curso.Las operaciones están especificadas en función de la jerarquía de tipos para colecciones. size includes excludes count includesAll isEmpty notEmpty collection sum product set orderedset bag sequence UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
100 Operaciones de coleccióncollection set orderedset bag sequence append union count = union prepend = intersection = append insertAt union - intersection flatten prepend subSequence including - asSet insertAt including at excluding indexOf asOrderedSet subOrderedSet excluding symmetricDifference asSequence first count at count asBag indexOf flatten last flatten including asSet first asSet asOrderedSet excluding asOrderedSet last asSequence asSequence asBag asBag UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
101 Let y expresiones <
102 Expresiones Let A veces una subexpresión es utilizada mas de una vez en una restricción. La expresión let nos permite definir una variable la cual puede ser utilizada en una restricción. context Persona inv: let sueldo : Integer = self.job.salario->sum() in if esDesocupado then sueldo < 100 else sueldo >= 100 endif Persona Compañía nombre : String +empleado +empleador nombre : String edad : Integer numerodeEmpleados : Integer esDesocupado : Boolean 0..* 0..* 0..* 0..* Job titulo : String diaComienzo : Date salario : Integer UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
103 expresiones <
104 Reglas de Derivación UCM 2005
105 ejemplo context Cuenta:: msaldoderive: msaldo : real = self.mMovs.mImporte->sum() mCuentas Cuenta /msaldo: Real 0..* mTitulares 1..* Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero mCuentaNómina 0..* Movimiento mImporte: Real mConcepto: String mFecha: Fecha mMovs 1 mtitular 0..* mtarjetas 0..* Tarjeta /MNombreTitular: String UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
106 ejemplo El nombre del titular que figura en toda tarjeta es la concatenación del nombre y apellidos del titular. context Tarjeta derive: self.mNombreTitular= mTitular.mNombre.concat(“ “).concat(mTitular.mApellidos) mCuentas Cuenta /msaldo: Real 0..* mTitulares 1..* Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero mCuentaNómina 0..* Movimiento mImporte: Real mConcepto: String mFecha: Fecha mMovs 1 mtitular 0..* mtarjetas 0..* Tarjeta /MNombreTitular: String UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
107 Ej de expresión init context Tarjeta::mMovs: Set (Movimiento)mImporte: Real mConcepto: String mFecha: Fecha context Tarjeta::mMovs: Set (Movimiento) init: Set{} 0..* mMovs Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero 1 mtitular 0..* mtarjetas Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
108 La especificación de expresiones OCL en Modelos UML/OCL combinados Día 3UCM 2005
109 Resolviendo propiedadesUCM 2005
110 Resolviendo propiedadesNo siempre es inmediato determinar a que objeto se aplica una propiedad: La instancia contextual puede estar implícita Una o más variables iteradoras (de las operaciones de colección) pueden estar implícitas Resolver a que objeto se aplica una propiedad puede disminuír la entendibilidad y modificabilidad de una expresión OCL. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
111 Resolviendo propiedadescontext Persona inv: empleador->forAll( empleado->exists( apellido= nombre)) Persona Compañía nombreEmp : String +empleado +empleador nombre : String Apellido: String numerodeEmpleados : Integer esDesocupado : Boolean 0..* 0..* 0..* 0..* Job titulo : String diaComienzo : Date salario : Integer En la expresión OCL existen 3 variables implícitas: La primera es self la cual es siempre la instancia a partir de la cual comienza la restricción. Se introduce un iterador implícito en la operación forAll (iter1) y luego en la operación exists (iter2). Las variables iteradoras implícitas no tienen nombre. Las propiedades empleado, empleador, apellido y nombre se aplican a objetos que no han sido omitidos en la especificación. Analizaremos como resolver esta situación. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
112 Resolviendo propiedades1. En el lugar donde empleador se utiliza sólo existe una variable implícita self: Persona. Por consiguiente empleador debe ser una propiedad de self. 2. En el lugar donde se utiliza empleado existen dos variables implícitas: self: Persona e iter1: Compañía. Por consiguiente, empleado debe ser una propiedad de self o de iter1. Si empleado fuera una propiedad de self y de iter1 entonces este debería aplicarse a la variable en el alcance más interno, el cual es iter1. Persona Compañía nombreEmp : String +empleado +empleador nombre : String Apellido: String numerodeEmpleados : Integer esDesocupado : Boolean 0..* 0..* 0..* 0..* Job context Persona inv: empleador->forAll( empleado ->exists( apellido= nombre)) titulo : String diaComienzo : Date salario : Integer UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
113 Resolviendo Propiedades3. En el lugar donde se utilizan apellido y nombre existen tres variables implícitas: self: Persona, iter1: Compañía e iter2: Persona. Por consiguiente tanto apellido como nombre deben ser una propiedad de self o de iter1 o iter2. En el modelo UML la propiedad nombre es una propiedad iter1. Sin embargo, apellido es una propiedad de self e iter2. Esto es ambiguo, por lo tanto apellido refiere a la variable en el alcance más cercano, que es iter2. Persona Compañía nombreEmp : String +empleado +empleador nombre : String Apellido: String numerodeEmpleados : Integer esDesocupado : Boolean 0..* 0..* 0..* 0..* Job context Persona inv: empleador->forAll( empleado ->exists( apellido= nombre)) titulo : String diaComienzo : Date salario : Integer UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
114 ejercicio context Componente inv:self.utiliza-> forAll (s | self.desarrolladores.conoce-> includes(s) ) Componente id_comp : Integer Genero masculino +desarrollan femenino 1..* 1..* 1..* 1..* +desarrolladores 1..* 1..* Ingeniero_Informatico +utiliza 1..* 1..* nombre : String apellido : String Software +conoce dni : String id_software : Integer 1..* 1..* edad : Integer 1..* 1..* sexo : Genero UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
115 ejercicio context Libro inv:self.autores ->forAll (a | self.ediciones->exists (e | e.pais = a.pais) ) Autor nombre : String apellidos : String pais : String Editorial nombre_editorial : String +autores 1..* 1..* direccion : String +es_editado_por pais : String +escribio 1 1 1..* 1..* +edito Libro titulo : String 1..* 1..* isbn : String cant_de_paginas : Integer 1 1 +ediciones Edición +corresponde_a fecha_de_edicion : Fecha 1..* 1..* cant_de_ejemplares : Integer pais : String UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
116 Ejemplo de operaciones size y existsHotel Habitación direccion : String +habitación numero_habitación : Integer nombre : String numero_piso : Integer * * numero_de_camas : Integer +habitación 0..1 0..1 +habitación 1 1 * * +huespedes +servicio Huesped * * Servicio nombre : String piso_numero : Integer edad : Integer habitación_numero : Integer sexo : String usos : Integer context Habitación inv: self.huespedes ->size() <= numero_de_camas or ( huespedes->size() = numero_de_camas + 1 and huespedes->exists(h: Huesped | h.edad <= 4) ) utiliza(h : huespedes) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
117 ejercicio context baño::utiliza(h : Huesped) pre:if habitación->notEmpty() then habitacion.huespedes->includes(h) else h.habitacion.numero_piso = self.piso_numero endif post: usos = +1 Hotel Habitación direccion : String +habitación numero_habitación : Integer nombre : String numero_piso : Integer * * numero_de_camas : Integer +habitación +habitación 1 1 0..1 0..1 * * +huespedes +baño Huesped * * Baño nombre : String piso_numero : Integer edad : Integer habitación_numero : Integer sexo : String usos : Integer utiliza(h : huespedes) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
118 Algunas claves para la especificación de expresiones OCLUCM 2005
119 Determinar adecuadamente el contextosi el invariante restringe el valor de un atributo de una clase, la clase que contiene el atributo es un candidato clave. Si el invariante restringe los valores de atributos de más de una clase, las clases que contienen cualquiera de los atributos restringidos son candidatas claves. Cualquier invariante debería navegar el número más pequeño posible de asociaciones. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
120 Acoplamiento de objetosCualquier navegación que atraviesa el modelo de clase crea acoplamiento entre los objetos involucrados. Al utilizar navegaciones largas hace que los detalles de objetos distantes sean conocidos por el objeto desde el cual comienza la navegación. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
121 Acoplamiento de objetosSi es posible, es recomendable limitar el conocimiento del objeto a su entorno directo, que son las propiedades de su tipo. El acoplamiento se debe reducir ! Por lo tanto hay que tratar de evitar navegaciones complejas! Cuan distantes están los objetos asociados a la instancia contextual? 7 5 modelo 3 2 Expresión OCL c5 c7 c2 c1 c3 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
122 Cohesión de objetos Es importante aumentar la cohesión de objetos. Es posible determinar cuán cohesionados están dos métodos de una clase a partir de las propiedades (atributos, asociaciones y métodos) que estos refieren. Utilizan mismos atributos, mismas variables definidas a partir de expresiones <
123 3. Completando diagramas UMLUCM 2005
124 Completando diagramas de claseUCM 2005
125 Completando diagramas de claseTipos de expresiones Invariantes Pre/post-condiciones De consulta Valores iniciales Valores derivados Otros Ejemplos Restricciones or Restricciones subset Multiplicidad opcional Multiplicidad dinámica En general, restricciones semánticas entre la instancia y sus objetos asociados Navegaciones, colecciones UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
126 Multiplicidad dinámica<
127 Restricción {subset} Context Flight1 piloto 1..* vuelos Vuelo Persona tripulación 1..* azafatas {subset} Context Flight inv: self.tripulacion -> includes(self.piloto) inv: self.tripulacion -> includesAll(self.azafatas) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
128 Restricciones {or} UCM 2005 lider_proyecto 0..1 0..1 gerencia Personamiembroproyecto 0..1 0..1 pertenece Una de las potenciales asociaciones puede ser instanciada a la vez por un único objeto. Debe existir al menos una clase en común entre las asoc. conectadas por {or}. context Person inv: gerencia->isEmpty() or pertenece->isEmpty() context Proyecto inv: lider_proyecto->isEmpty() or miembroProyecto->isEmpty() Dos asociaciones que están vinculadas por una restriccion {or} deben tener al menos una clase en común UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
129 Ciclos en modelos de clasePersona Casa Casa casas dueño DNI: Integer Salario: Money valor: Money seguro 0..* 1 obtHipoteca(sum: Money; seguridad: Casa) 1 stock 1 responsable context Persona inv: self.hipotecas.seguro.dueño->forAll(dueño: Persona | dueño = self) 0..* 0..* Hipoteca hipotecas Principal: Money pagoMensual: Money hipotecas Muchos modelos de clase reejan ciclos en el sentido que uno puede comenzar navegando a partir de una instancia a traves de varias asociaciones, y retornar a una instancia de la misma clase. En el diagrama de clases, esto se muestra como un ciclo de clases y asociaciones. Muchas veces, estos ciclos son motivo de ambiguedades. En el ejemplo 4.1 se muestra un diagrama de clase con un ciclo. En este modelo una persona (Person) es dueña de una casa (House), la cual se paga a partir de una hipoteca (Mortgage). La hipoteca toma como prenda de seguridad la casa (House) de la cual es dueña la persona (Person). El modelo aunque parece ser correcto es impreciso. El modelo permite que una persona tenga una hipoteca, cuya hipoteca tome como prenda de seguridad una casa de la cual es dueño otra persona. Esto, claramente no es la intensión del modelo. Podemos establecer facilmente el invariante que necesitamos a partir de la siguiente expresión: context Persona inv: self.hipotecas.seguridad.dueño->forAll(dueño: Persona | dueño = self) Diacomienzo: Dat DiaFin: Date context Persona inv: self.hipotecas.seguridad.dueño->forAll(dueño: Persona | dueño = self) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
130 Multiplicidad opcionalPersona Casa Casa casas dueño DNI: Integer Salario: Money valor: Money seguro 0..* 1 obtHipoteca(sum: Money; seguridad: Casa) 1 stock 1 responsable context Persona inv: self.hipotecas.seguro.dueño->forAll(dueño: Persona | dueño = self) 0..* 0..* Hipoteca hipotecas Principal: Money pagoMensual: Money hipotecas Una multiplicidad opcional de una asociacion en un diagrama de clases es a veces una especicacion parcial de lo que realmente se pretende modelar. A veces la opcionalidad es libre; esto es, en algunas circunstancias puede haber uno o ningun objeto asociado. Muchas veces, una asociacion opcional no es realmente libre. Si un objeto asociado puede (o debe) estar presente depende del estado de los objetos involucrados. Por ejemplo en la gura 4.1 la asociacion opcional no es completamente libre. Si una persona tiene un prestamo, el o ella debe tener una casa. Esta restriccion puede ser especicada por el siguiente invariante: context Person inv optionality: mortgages->notEmpty() implies houses->notEmpty() En general, cuando una multiplicidad opcional esta presente en un diagrama de clase, es posible utilizar un invariante OCL para describir precisamente las circunstancias bajo las cuales la asociacion opcional puede ser vacía o no. Diacomienzo: Dat DiaFin: Date context Persona inv: self.hipotecas->exists() implies self.casas->notEmpty() UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
131 Completando diagramas de estadosUCM 2005
132 Un sistema simple de control de procesos...Botella mitapa mibotella mibotella Tapa capacidad:Integer contenido: Integer 0..1 0..1 0..1 0..* stock envasando(e:Envasador) tapar() stock Linea Sellador 1 1 Cap(b: Botella) nuevabotella() mover(b:Botella) laLinea 1 laLinea 1 elEnvasador Envasador capacidad:Integer contenido: Integer Un sistema simple de control de procesos... miEnvasador 0..1 envasar(b:Botella) parar() UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
133 Completando diagr. de estados? Tipo contextual ? Instancia Diag. de estados para Filler stop()/theLine.move(myBottle) filling stopped [ self.contents > b.capacity ] fill(b) / b.filling( self ) Un guardia es una condición en la transición en un diagrama de estados. Un guardia a veces se incluye en el diagrama de estados en sí mismo. En este caso se escribe entre corchetes ([ y ]) luego del evento que dispara la transición. La figura incluye un guardia en la transición desde el estado stopped al estado filling. En este caso, el objeto Filler cambia de estado sólo si contiene suficiente líquido. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
134 Completando diagr. de estadosDiag. de estados para Filler stop()/theLine.move(myBottle) filling stopped [ self.contents > b.capacity ] fill(b) / b.filling( self ) Una acción en un diagrama de estados representa un llamado a una operación. Las acciones pueden estar acopladas a transiciones o estados en un diagrama de estados. Por ejemplo, la acción theline.move(b) tiene como target el objeto Line vinculado a la instancia contextual de Filler UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
135 Completando diag. de estadosparcialmenteLLena /do:monitorearContenido() envasando(e:Envasador) vacia when(contenido = capacidad) / miEnvasador.stop() llena cap() Evento de cambio tapada context Botella inv: (self.oclInState(tapada) or self.oclInState(llena)) implies contenido = capacidad inv: self.oclInState(vacía) implies contenido = 0 inv: self.oclInState(parcialmenteLLena) implies miEnvasador->notEmpty() UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
136 Completando diagramas de estadosPodemos expresar a partir de expresiones OCL: guardas targets explícitos de acciones Acciones valores de parámetros actuales eventos de cambios restricciones en estados context Botella inv: self.oclInState(tapada) or self.oclInState(llena) implies contenido = capacidad inv: self.oclInState(tapada) implies miTapa->notEmpty() inv: self.oclInState(parcialmenteLLena) implies miEnvasador->notEmpty() UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
137 Restricciones en diagramas de secuencial: line e: envasador b: botella envasar(b) envasando(e) stop() mover(b) l.elEnvasador->includes(e) and l.stock->includes(b) and b.miEnvasador->includes(e) [contenido > capacidad ] /stop() UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
138 Complementando diagramas de componentes<
139 La especificación de expresiones OCL en Modelos UML/OCL combinados Día 4UCM 2005
140 5. El modelo Royal & Loyal UCM 2005
141 R&L UCM 2005 Mg. Reynoso Luis (UNC, UCLM) Customer LoyaltyProgramname : String title : String +programs name : String 0..* 0..* +participants isMale : Boolean R&L +programs dateOfBirth : Date 1..* 1..* enroll(c : Customer) 0..* 0..* / age : Integer getServices() : Set(Services) age() : Integer +program 1 1 Membership +owner 1 1 0..* 0..* +partners 1..* 1..* ProgramPartners +cards +card numOfCustomers : Integer 0..* 0..* name : String +currentLevel CustomerCard +levels 1..* 1..* 1 1 valid : Boolean 1 1 validFrom : Date +partners ServiceLevel goodThru : Date name : String color : Color 1 1 / printedName : String +delivered +account Services 0..* +level 1 1 LoyaltyAccount 0..* +card points : Integer Service number : Integer condition : Boolean pointsEarned : Integer 0..1 0..1 earn(i : Integer) pointsBurned : Integer +available burn(i : Integer) description : String isEmpty() : Boolean serviceNr : Integer Services +account 1 1 calcPoints() : Integer +transactions +transactions 0..* 0..* +generatedBy 1 1 0..* 0..* Color Transaction silver +transactions points : Integer gold date : Date 0..* 0..* amount : Real Date now : Date program() : LoyaltyProgram isBefore(t : Date) : Boolean isAfter(t : Date) : Boolean fromYMD(t : Date) : Date opname2() Burning Earning UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
142 Clases de R&L R&L es un sistema que administra programas de lealtad.Customer LoyaltyProgram name : String title : String +programs name : String 0..* 0..* +participants isMale : Boolean +programs dateOfBirth : Date 1..* 1..* enroll(c : Customer) 0..* 0..* / age : Integer getServices() : Set(Services) age() : Integer Membership +partners 1..* 1..* ProgramPartners numOfCustomers : Integer name : String R&L es un sistema que administra programas de lealtad. Programas de Lealtad (LoyaltyProgram): Contiene los programas de lealtad. Socios del Programa (ProgramPartners): Representa a las compañías que ofrece a sus clientes ser miembros de un programa de lealtad. Los clientes que pertenecen a un programa de lealtad pueden aprovechar los servicios que ofrece cualquier compañía participante del programa al cual pertenece el cliente. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
143 Clases de R&L Todo cliente de un socio de programa puede pertenecer a un programa de lealtad completando un formulario y obteniendo una tarjeta de membresía. La tarjeta de membresía, representada por la clase CustomerCard, se emite a una persona. La mayoría de los programas permite a sus clientes obtener puntos. Cada socio de programa decide de que forma se acumulan puntos y cuantos puntos deben ser acumulados por una compra (servicios de los socios del programa). Los puntos pueden ser utilizados para obtener servicios específicos de uno de los socios del programa. Para que un cliente acumule puntos, toda membresía puede estar asociada con una cuenta de lealtad. Existen transacciones para obtener puntos y para gastar puntos. Existen distintos niveles de servicio en cada programa de lealtad. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
144 Valores iniciales Una cuenta de lealtad esta siempre inicializada con 0 puntos context LoyaltyAccount::points init: 0 Toda tarjeta de cliente será válida al momento de ser emitida context CustomerCard::valid init: true UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
145 Valores Derivados El atributo derivado printedName de CustomerCard se determina a partir del nombre y título del dueño de la tarjeta. context CustomerCard::printedName derive: owner.title.concat(' ').concat(owner.name) Customer LoyaltyProgram name : String title : String name : String 0..* 0..* +participants isMale : Boolean +programs dateOfBirth : Date enroll(c : Customer) 0..* 0..* / age : Integer getServices() : Set(Services) age() : Integer Membership +owner 1 1 +cards +card 0..* 0..* CustomerCard valid : Boolean validFrom : Date goodThru : Date color : Color / printedName : String +card UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
146 Operación de consulta La clase LoyaltyProgram tiene una operación de consulta denominada getServices(), el cual retorna todos los servicios ofrecidos por todos los Socios del Programa (ProgramPartners) en ese programa. LoyaltyProgram::getServices(): Set(Service) body: partners.deliveredServices->asSet() LoyaltyProgram +programs name : String 1..* 1..* enroll(c : Customer) getServices() : Set(Services) +program 1 1 +partners 1..* 1..* ProgramPartners numOfCustomers : Integer name : String +levels 1 1..* 1..* +partners 1 ServiceLevel name : String +delivered Services 0..* +level 0..* Service condition : Boolean pointsEarned : Integer 0..1 0..1 pointsBurned : Integer +available description : String serviceNr : Integer Services calcPoints() : Integer +generatedBy 1 1 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
147 Operación de consulta context LoyaltyProgram::getServices(pp: ProgramPartner): Set(Service) body: if partners-> includes (pp) then pp.deliveredServices else Set{} endif LoyaltyProgram +programs name : String 1..* 1..* enroll(c : Customer) getServices(pp:ProgramPartner) : Set(Services) +program 1 1 +partners 1..* 1..* ProgramPartners numOfCustomers : Integer name : String +levels 1 1..* 1..* +partners 1 ServiceLevel name : String +delivered Services 0..* +level 0..* Service condition : Boolean pointsEarned : Integer 0..1 0..1 pointsBurned : Integer +available description : String serviceNr : Integer Services calcPoints() : Integer +generatedBy 1 1 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
148 Definiendo nuevos atributos y operacionesUn nuevo atributo turnover en la clase LoyaltyAccount que represente las suma de las transacciones en la cuenta context LoyaltyAccount def: turnover : Real = transactions.amount->sum() +account LoyaltyAccount points : Integer number : Integer earn(i : Integer) burn(i : Integer) isEmpty() : Boolean +account 1 1 +transactions 0..* 0..* Transaction points : Integer date : Date 0..* 0..* amount : Real program() : LoyaltyProgram Burning Earning UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
149 Definiendo nuevos atributos y operacionesLoyaltyProgram Una nueva operación que retorne el conjunto de todos los servicios ofrecidos por un determinado nivel en un programa de lealtad context LoyaltyProgram def: getServicesByLevel(levelName: String): Set(Service) = levels->select( name = levelName).availableServices ->asSet() +programs name : String 1..* 1..* enroll(c : Customer) getServices() : Set(Services) +program 1 1 +partners 1..* 1..* ProgramPartners numOfCustomers : Integer name : String +levels 1 1..* 1..* +partners 1 ServiceLevel name : String +delivered Services 0..* +level 0..* Service condition : Boolean pointsEarned : Integer 0..1 0..1 pointsBurned : Integer +available description : String serviceNr : Integer Services calcPoints() : Integer +generatedBy 1 1 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
150 Invariantes en atributosTodo cliente que entra en un programa de lealtad sea mayor de edad context Customer inv ofAge : age >= 18 Customer name : String title : String isMale : Boolean dateOfBirth : Date / age : Integer age() : Integer UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
151 Invariantes en objetos asociadosTodo cliente que entra en un programa de lealtad sea mayor de edad context CustomerCard inv ofAge : owner.age >= 18 Customer name : String title : String isMale : Boolean dateOfBirth : Date / age : Integer age() : Integer +owner 1 1 +cards 0..* 0..* CustomerCard valid : Boolean validFrom : Date goodThru : Date color : Color / printedName : String +card UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
152 Invariantes (el tipo del atributo es una clase)Cuando un atributo no es un tipo estándar, tal como Boolean o Integer, pero su tipo es una clase en sí misma, es posible utilizar los atributos u operaciones de consulta definidas en tal clase para escribir el invariante. context CustomerCard inv checkDates: validFrom.isBefore(goodThru) Customer name : String title : String isMale : Boolean dateOfBirth : Date 0..* 0..* / age : Integer age() : Integer +owner 1 1 +cards Date 0..* 0..* now : Date CustomerCard isBefore(t : Date) : Boolean valid : Boolean isAfter(t : Date) : Boolean validFrom : Date fromYMD(t : Date) : Date goodThru : Date opname2() color : Color / printedName : String +card UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
153 Clases de asociación El nivel de servicio de cada membresía debe ser un nivel de servicio conocido por el programa de lealtad al cual corresponde la membresía context LoyaltyProgram inv knownServiceLevel: levels->includesAll(Membership.currentLevel) LoyaltyProgram Customer +programs name : String 0..* 0..* +participants name : String +programs enroll(c : Customer) title : String 1..* 1..* 0..* 0..* getServices() : Set(Services) isMale : Boolean dateOfBirth : Date +program / age : Integer 1 1 Membership 0..* 0..* age() : Integer +partners 1..* 1..* ProgramPartners numOfCustomers : Integer name : String +currentLevel +levels 1..* 1..* 1 1 ServiceLevel name : String UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
154 enumeraciones Un tipo enumerado puede ser utilizado, por ejemplo, como el tipo de un atributo de una clase en un modelo UML. El color de una tarjeta debe ser igual al nivel de servicio de la membresía context Membership inv levelAndColor: currentLevel.name = 'Silver' implies card.color = Color::silver and currentLevel.name = 'Gold' implies card.color = Color::gold Customer LoyaltyProgram name : String title : String name : String 0..* 0..* +participants isMale : Boolean +programs dateOfBirth : Date enroll(c : Customer) 0..* 0..* / age : Integer getServices() : Set(Services) age() : Integer +program 1 1 Membership 0..* 0..* +owner 1 1 +cards +card 0..* 0..* CustomerCard +currentLevel +levels 1..* 1..* 1 1 valid : Boolean validFrom : Date ServiceLevel goodThru : Date Color name : String color : Color silver / printedName : String gold +level 1 1 +card UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
155 Ejemplo de operación size()sería razonable requerir que un programa de lealtad ofrezca al menos un servicio a sus clientes. context LoyaltyProgram inv minServices: partners.deliveredServices->size() >= 1 LoyaltyProgram +programs name : String 1..* 1..* enroll(c : Customer) getServices() : Set(Services) +program 1 1 +partners 1..* 1..* ProgramPartners numOfCustomers : Integer name : String +levels 1 1..* 1..* +partners 1 ServiceLevel name : String +delivered Services 0..* +level 0..* Service condition : Boolean pointsEarned : Integer 0..1 0..1 pointsBurned : Integer +available description : String serviceNr : Integer Services calcPoints() : Integer +generatedBy 1 1 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
156 Ejemplo de operación select()El modelo R&L requiere que el número de tarjetas válidas para todo cliente debe ser igual al número de programas en los cuales el cliente participa context Customer inv sizeAgree: programs->size() = cards->select( valid = true ) -> size() Customer LoyaltyProgram name : String title : String name : String 0..* 0..* +participants isMale : Boolean +programs dateOfBirth : Date 1..* enroll(c : Customer) 0..* 0..* / age : Integer getServices() : Set(Services) age() : Integer Membership +owner 1 1 +cards +card 0..* 0..* CustomerCard valid : Boolean validFrom : Date goodThru : Date color : Color / printedName : String UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
157 Ej. Forall e isEmpty UCM 2005 Si todos los servicios delprograma de lealtad no acreditan, ni debitan puntos entonces las membresías del programa no deberían tener una cuenta de lealtad asociada context LoyaltyProgram inv noAccounts: partners.deliveredServices->forAll( pointsEarned = 0 and pointsBurned = 0 ) implies Membership.account-> isEmpty() LoyaltyProgram Customer +programs name : String name : String 0..* 0..* +participants title : String +programs 1..* 1..* enroll(c : Customer) 0..* 0..* isMale : Boolean getServices() : Set(Services) dateOfBirth : Date / age : Integer +program 1 1 Membership age() : Integer 0..* 0..* +partners 1..* 1..* ProgramPartners numOfCustomers : Integer name : String +currentLevel +levels 1 1..* 1..* 1 1 +partners 1 ServiceLevel name : String 0..1 1 +delivered +account Services +level 1 1 0..* LoyaltyAccount 0..* points : Integer Service number : Integer condition : Boolean pointsEarned : Integer 0..1 0..1 earn(i : Integer) pointsBurned : Integer +available burn(i : Integer) description : String isEmpty() : Boolean serviceNr : Integer Services calcPoints() : Integer +generatedBy UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
158 Set y bag Consideremos el atributo numofCustomers de la clase ProgramPartners. Queremos establecer que este atributo contiene el número de clientes que participan en uno o más programas de lealtad ofrecidos por este socio de programa. context ProgramPartner inv nrOfParticipants: mumOfCustomers = programs.participants->size() inv nrOfParticipants: mumOfCustomers = programs.participants->asSet()->size() LoyaltyProgram Customer +programs name : String +participants name : String 0..* 0..* title : String +programs 1..* 1..* enroll(c : Customer) 0..* 0..* isMale : Boolean getServices() : Set(Services) dateOfBirth : Date / age : Integer Membership age() : Integer +partners 1..* 1..* ProgramPartners numOfCustomers : Integer name : String UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
159 orderedSets Cuando se navega una asociación marcada con {ordered}, la colección resultante es de tipo OrderedSet En el contexto de LoyaltyProgram, la expresión levels resulta en un conjunto ordenado. Podríamos establecer que el primer elemento de este conjunto se debe denominar Silver: context LoyaltyProgram inv firstLevel: levels->first().name = 'Silver' LoyaltyProgram name : String enroll(c : Customer) getServices() : Set(Services) +program 1 1 +levels {ordered} 1..* 1..* ServiceLevel name : String +level 1 1 UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
160 Pre y postcondiciones la clase LoyaltyAccount tiene una operación denominada isEmpty. Cuando el número de puntos en la cuenta es cero, la operación retorna verdadero. La postcondición establece esto en forma precisa context LoyaltyAccount::isEmpty():Boolean pre: - - none post: result = ( points = 0 ) 1 LoyaltyAccount points : Integer number : Integer earn(i : Integer) burn(i : Integer) isEmpty() : Boolean UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
161 Ej de herencia los socios del programa quieren limitar elProgramPartners numOfCustomers : Integer name : String los socios del programa quieren limitar el número de puntos que ellos ofrecen; ellos tienen un conjunto máximo de puntos que pueden ser obtenidos utilizando sus servicios. 1 +partners 1 +delivered Services 0..* Service condition : Boolean pointsEarned : Integer pointsBurned : Integer description : String serviceNr : Integer calcPoints() : Integer context ProgramPartner inv totalPoints: deliveredServices.transactions.points->sum() < 10000 +generatedBy 1 1 0..* +transactions points : Integer date : Date amount : Real program() : LoyaltyProgram Burning Earning UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
162 Ej de herencia Para establecer la diferencia entre transaccionesProgramPartners numOfCustomers : Integer name : String Para establecer la diferencia entre transacciones Burning y Earning, utilizaremos la operación estándar oclIsTypeOf. 1 +partners 1 +delivered Services 0..* context Person self.oclIsTypeOf(Person) - –true Self.oclIsTypeOf(Company) - - false Service condition : Boolean pointsEarned : Integer pointsBurned : Integer description : String serviceNr : Integer calcPoints() : Integer +generatedBy 1 1 context ProgramPartner inv totalPoints: deliveredServices.transactions ->select( v: Transaction | v.oclIsTypeOf(Earning) ).points->sum() < 10000 0..* +transactions points : Integer date : Date amount : Real program() : LoyaltyProgram Burning Earning UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
163 3. Descripción de la Implementación de las expresiones OCLUCM 2005
164 Implementando OCL en JavaLos modelos UML/OCL especifican como el sistema debería estar estructurado y que debería hacer el sistema pero no como debería ser implementado. Para mostrar como construír código desde expresiones OCL, en primer instancia debemos implementar los elementos del modelo definidos en un diagrama. La implementación de expresiones OCL que hacen referencia a cualquier propiedad debe ser coherente con el acceso a tales propiedades. Además, como regla del proceso de transformación los fragmentos de código de las expresiones OCL deben ser utilizadas de acuerdo a sus roles en el modelo . Los fragmentos de código deben estar ubicados en la implementación de tal forma que ellos alcancen su propósito. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
165 Pasos básicos El orden de los pasos durante el proceso de implementación es el siguiente: (p1) Definir la implementación de los elementos del modelo UML (p2) Definir la implementación de la librería estándar OCL (p3) Definir la implementación de las expresiones OCL (p4) Ubicar correctamente los fragmentos de código que implementan las expresiones OCL en el código de los elementos del modelo. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
166 La implementación de los elementos del modeloUCM 2005
167 (p1) clases p.1.1. clases se transforman en clases Javapublic class Tarjeta { ....} Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
168 (p1) atributos p.1.2. Cada atributo (privado, protegido, publico) de una clase se transforma en un miembro de clase, privado, con operaciones get y set en la clase Java. La visibilidad de las operaciones es equivalente a la visibilidad del atributo. Si el atributo es read-only, la operación set se omite. AttributeType1 getAttributeName1() void setAttributeName1 (AttributeType1 newValue) UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
169 (p1) atributos public class Tarjeta { Fecha mValidoDesdepublic void setValidoDesde(Fecha f) {mValidoDesde = f;}; public Fecha getValidoDesde() {return mValidoDesde}; Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha Fecha <
170 (p1) asociaciones p.1.3. Cada Extremo de asociación en el modelo se transforma en un miembro de clase, privado, con operaciones get y set en la clase Java. La visibilidad de las operaciones es equivalente a la visibilidad del extremo en el modelo. Si la multiplicidad es mayor a uno, el tipo del miembro de clase es la implementación Java de Set o de OrderedSet, dependiendo si la asociación esta etiquetada con {ordered} o no. public class Tarjeta { Cliente titular; HashSet mMovs Movimiento mImporte: Real mConcepto: String mFecha: Fecha 0..* mMovs Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero 1 mtitular = new HashSet() ; context Tarjeta::mMovs init: Set{} 0..* mtarjetas Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
171 (p1) asociaciones cont. UCM 2005 public class Tarjeta {Movimiento mImporte: Real mConcepto: String mFecha: Fecha public class Tarjeta { Cliente titular; HashSet mMovs; public void setTitular(Titular t) { titular = t; } public Titular getTitular(Titular t) { return titular; } public void agregarMovimiento(Movimiento m) { mMovs.add(m); } public HashSet getmMovs() { return mMovs} 0..* mMovs Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero 1 mtitular 0..* mtarjetas Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
172 (p1) otros eltos. del modelop.1.4. Cada tipo enumerado en el modelo se transforma en una clase Java, conteniendo miembros de clase pública estáticos, para cada literal de la enumeración. p.1.5. Cada interfaz del modelo se transforma en una interfaz Java p.1.6. Cada estado de un diagrama de estado para una clase se transforma en un miembro de clase de tipo booleano. Se agregan restricciones para verificar que la clase esta en un solo estado. Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha Fecha <
173 Implementación de la librería standard de OCLUCM 2005
174 (p2) impl. una librería standardMapeo de tipos básicos de OCL a Java. OCL type Java Type Integer int Real real String String Boolean boolean UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
175 (p2) impl. una librería standardMapeo de tipos colección de OCL a Java. OCL collection Type Java Type Set HashSet Sequence, Bag, OrderedSet ArrayList Existen dos tipos de operación de colección aquellas que iteran sobre cada elemento de la colección para realizar una operación (exists, select, collect) y otras que son mas simples como union, size. A las primeras se las denomina iteradores de colección. No existen operaciones equivalentes en Java para todas las operaciones de colección de OCL ! UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
176 (p2) impl. Una librería standardPor ejemplo dada la siguiente expresión donde mMovs es un set mMovs->select(importe > 100) esta puede ser transformada en el siguiente código Java: Iterator it = mMovs.iterator(); Set result = new HashSet(); While (it.hasNext()) { Movimiento elem = ( Movimiento ) it.next() ; if ( elem.importe > 100 ) { result.add(elem) ; }} return result; Movimiento mImporte: Real mConcepto: String mFecha: Fecha 0..* mMovs Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
177 Implementando las expresiones OCLUCM 2005
178 (p3) accediendo a propiedadesEl acceso a propiedades (atributos ó extremos de asociación) depende del mapeo de la propiedad UML a Java. self.attribute es transformado a this.getAttribute(); self.associationEnd navegación this.getAssociationEnd(); operationCall UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
179 (p3) orden de evaluaciónself.titular.tipo >= 0 or self.titular->isEmpty() (this.getTitular().getTipo() >= 0 ) || (this.getTitular() == null) Error de java.lang.nullPointerException por hacer referencia a un objeto que no existe Cliente mNombre: String mApellidos: String mEdad: Integer tipo: Integer 0...1 mtitular 0..* mtarjetas Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
180 (p3) reglas de derivacióncontext Tarjeta::mNombreTitular derive: self.mNombreTitular= mTitular.mNombre.concat(“ “).concat(mTitular.mApellidos) Opción A. Implementar una operación... string getNombreImpreso() { return getTitular().getNombre() + “ “ + getTitular.getApellidos(); } Opcion B. Implementar un atributo, sin embargo necesitamos un observer. Los objetos en los cuales depende la regla de derivación deben notificar a este atributo cuando se modifiquen En ambos casos nunca tienen una operación pública set. Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero 1 mtitular mtarjetas 0..* Tarjeta /mNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
181 (p4) ubicando los fragmentos de las expresiones en la impl(p4) ubicando los fragmentos de las expresiones en la impl. de los eltos del modelo UCM 2005
182 (p4) expresiones invarianteEscribimos una operación con resultado booleano. Y luego incluimos otra operación que llame a todas operaciones que implementan invariantes. context Tarjeta inv fechasValidas: self.mValidoDesde.estaAntes(mValidoHasta) Implementar una operación... boolean invfechasValidas() { return mValidoDesde.estaAntes(mValidoHasta) } Tarjeta MNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha Fecha <
183 (p4) expresiones invariantescontext Tarjeta inv: titular.mEdad > = 18 Implementar una operación... boolean invEdadCorrecta() { return getTitular().getmEdad() >= 18; } boolean chequearTodosLosInv () { return invfechasValidas() & invEdadCorrecta() && .... } Cliente mNombre: String mApellidos: String mEdad: Integer Sexo: Genero 1 mtitular mtarjetas 0..* Tarjeta MNombreTitular: String mValidoDesde: Fecha mValidoHasta: Fecha UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
184 (p5) pre y postcondicionescontext Cliente::agregarTarjeta ( t : Tarjeta) pre: not mtarjetas->includes(t) post: mtarjetas = ->including(t) Void agregarTarjeta(Tarjeta t) { assert( ! mtarjetas.contains(t) ) ; tarjetas_old = new ArrayList(mtarjetas); // ... //
185 2’. Profundizando conceptosUCM 2005
186 Propiedad: operacionesQue sucede si la operación tiene parámetros? OCL tiene en cuenta si los parametros de una operación son par. de entrada (in), de salida (out) o de entrada/salida (in/out). Por ejemplo: aDocente.ingreso(aFecha) Si la operación no tiene parametros de salida o entrada/ salida, el resultado del llamado a la operación es el valor del tipo de retorno de la operación. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
187 Propiedad: operacionesSi la operación tiene parámetros de salida o entrada/salida, el resultado de esta operación es una tupla consistiendo de los parámetros de salida, entrada/Salida y resultado. context Docente::ingreso (d: Date, ticket: Integer) : Integer post: result = Tuple {ticket = , result = } param. de entrada param. de salida UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
188 Propiedad: operacionesCuando la operación no tiene parámetros de salida o entrada/salida el tipo de result, es el tipo de retorno de la operación. context Docente::ingresoA(d:Fecha) : Integer post: result = age * 10000 Cuando una operación tiene parámetros de salida o entrada/salida, el tipo retornado es una tupla. context Docente::ingreso (d: Fecha, ticket: Integer) : Integer post: result = Tuple {ticket = , result = } UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
189 Propiedad: operacionesparam. de entrada param. de salida Ejemplo: la operación ingreso podría tener un parámetro de salida ticket, y el resultado de la invocación a la operación es de tipo Tupla(ticket: Integer, result: Integer). Ej de acceso a los parámetros: aDocente.ingreso(aFecha).ticket = 300 and aDocente.ingreso(aFecha).result = 500 Note que los parámetros de salida no necesitan incluirse en el llamado a la operación, mientras que los parámetros de entrada o entrada/Salida sí. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
190 Definir pre y postcondiciones para las interfaces del componenteOrderEntry Order crear() validarDetalles() agregarLineaOrden() Definir pre y postcondiciones para las interfaces del componente UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
191 6. Algunas Conclusiones UCM 2005
192 Conclusiones OCL permite expresar, de forma más precisa, el conocimiento acerca del sistema que se desea modelar. Sus expresiones declaran restricciones semánticas de los elementos del modelo. Los modelos que son especificados con una combinación de los lenguajes UML y OCL son denominados modelos UML/OCL combinados, o simplemente modelos UML/OCL. Los modelos UML/OCL son fundamentales para la construcción de Modelos Independientes de la Plataforma (PIM), y nos permiten obtener modelos precisos y completos con un alto nivel de madurez (MML). La vinculación entre un elemento del modelo y una expresión OCL esta determinada por el contexto de la expresión. El concepto del contexto involucra la diferenciación entre tipo contextual e instancia contextual. En un expresión OCL es posible acceder a propiedades de la instancia contextual (atributos, métodos y asociaciones), como así también de objetos asociados con la instancia contextual. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
193 Conclusiones Es posible complementar diagramas de clase con expresiones OCL especificando reglas de derivación, valores iniciales, el cuerpo de operaciones de consulta, invariantes, precondiciones y postcondiciones. Las expresiones OCL también pueden ser útiles para especificar ciclos, especificar multiplicidad dinámica u opcional, restricciones or y subset, etc. El diagrama de estados puede ser complementado con la especificación precisa de expresiones OCL para los guardas, targets explícitos de acciones, valores de parámetros actuales y eventos de cambios. La semántica de otros diagramas, como el de componentes y el de interacción, pueden aumentar su precisión semántica a partir de la especificación de OCL. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
194 Conclusiones OCL nos permite manipular colecciones de datos. Las colecciones que provee OCL son tipos predefinidos. Ellos son: Set, OrderedSet, Sequence y Bag. Es posible utilizar un numeroso conjunto de operaciones de colección. Aunque es posible especificar colecciones a partir de literales la forma más común de hacerlo es a partir de navegaciones. Las navegaciones nos permiten definir relaciones y restricciones entre la instancia contextual y sus objetos asociados. Tales definiciones deben ser especificadas con cuidado debido a que la navegación crea acoplamiento entre objetos. UCM 2005 Mg. Reynoso Luis (UNC, UCLM)
195 7. Acreditación UCM 2005