La herramienta de modelado USE -1- Ingeniería del Software I La herramienta de modelado USE 1° cuatrimestre de 2007 Introducción ............................................................................................................................................................2 La aplicación USE...................................................................................................................................................2 Sintaxis del modelo conceptual ..............................................................................................................................3 Componentes del entorno USE ..............................................................................................................................8 Algunos comandos válidos de la consola.............................................................................................................14 Respecto al uso del diagrama de secuencias .......................................................................................................16 Diferencias entre el lenguaje OCL de USE y el OCL stándard ........................................................................18 Generators .............................................................................................................................................................21 Un ejemplo.............................................................................................................................................................21 Apéndice A: Comandos de la consola..................................................................................................................23 Apéndice B: Gramática de USE...........................................................................................................................24 Bibliografía............................................................................................................................................................26 La herramienta de modelado USE -2- Introducción El lenguaje de modelado unificado (UML) permite definir un modelo no implementativo (descriptivo) basado en objetos y clases de la solución a establecer. Este modelo sirve para comprender la naturaleza del problema en su forma conceptual sin caer en características de implementación, propios de modelos posteriores. Esto es lo que conocemos como modelo conceptual. Representa una abstracción respecto a los objetos del mundo y sus interrelaciones, al definir las características centrales de cada uno de ellos (su estructura y su comportamiento). Sin embargo, bajo algunas circunstancias no expresadas estructuralmente en el modelo conceptual, los objetos deberán cumplir ciertas condiciones no expresables en el modelo conceptual. Estas condiciones deberán describirse en un lenguaje formal. El lenguaje formal definido por UML para establecer restricciones dentro del modelo conceptual se llama OCL. El lenguaje OCL también se utiliza para definir el comportamiento abstracto de los objetos representados. La aplicación USE USE es una herramienta creada por la Universidad de Bremen para definir modelos conceptuales con sus restricciones expresadas en lenguaje OCL. Es una aplicación multiplataforma que se implementa sobre una máquina virtual Java 2 (para poder ejecutarla, será necesario tener instalado en el equipo JDK 1.4.2 o superior). Las versión de USE presentada aquí es la 2.3.1. Funciones: - Definición del modelo conceptual con sus componentes (enumerados, clases, atributos, asociaciones -incluyendo a composiciones y agregaciones-, responsabilidades -comunes y derivadas-, clases de asociación y herencia). - Utilización de OCL para definición de invariantes del modelo y definiciones de responsabilidades. - Creación de objetos pertenecientes a clases propias del modelo conceptual. - Verificación de invariantes del modelo completo en función de los objetos creados. - Evaluación de expresiones OCL en general. - Visualización de un “diagrama de secuencias sincrónico” en función de las acciones realizadas por el usuario en relación a la creación/modificación de objetos. Desventajas: - El modelo conceptual definido dentro de USE no admite atributos derivados ni dominios. - El lenguaje OCL de USE en algunos casos se utiliza dentro de la estructura sintáctica de la definición del modelo conceptual propia de USE (no separa el modelo conceptual propiamente dicho de las definiciones de OCL). - El lenguaje OCL de USE está limitado (algunas definiciones del OCL standard no se encuentran implementadas). La herramienta de modelado USE -3- - USE implementa un dialecto de OCL (en algunos casos el standard del lenguaje OCL no se sigue). - USE ofrece demasiadas libertades para construir modelos conceptuales, al permitir que a las clases de asociación se le apliquen los mismos tratamientos que a las clases comunes. Un ejemplo de esto ocurre al permitir que una clase de asociación sea la clase superiora respecto a una relación de herencia (o en forma similar, al permitir que una clase de asociación pueda ser abstracta). Esto puede llevar a construir modelos conceptuales confusos. - No queda muy clara la utilidad del “diagrama de secuencias” cuando nos estamos refiriendo al modelo conceptual. - El modelo resulta cada vez más difícil de expresarlo gráficamente en la vista del modelo a medida que se agregan componentes en el mismo. Esto ocurre porque el tamaño de la vista está limitado a su ventana, y por más de que el tamaño de ésta se pueda ampliar, está limitada al panel agrupador de vistas. El problema central es que esta vista no posee barras de navegación horizontales o verticales que permitan navegar por un gráfico más grande que la vista. - De manera similar al caso anterior, lo mismo ocurre con la vista del modelo de objetos, que tampoco posee barras de navegación. - Ante algunas situaciones, se pueden observar que la aplicación lanza excepciones propias del lenguaje Java en la consola de comandos. Sintaxis del modelo conceptual El documento de USE que contiene la especificación del modelo conceptual con las definiciones escritas en lenguaje OCL se denomina especificación, y se almacena en archivos de texto de extensión .use. Para describir los componentes sintácticos, se utilizó la siguiente nomenclatura: - Texto en negrita para expresar texto literal. - Texto en cursiva para expresar texto variable (suele ser un identificador o algún tipo de expresión sintáctica). - Texto delimitado entre corchetes (caracteres [ y ]) para indicar que ese texto es optativo. - Textos varios con caracteres pipe usados de separadores entre ellos (caracter |) y delimitados todos entre paréntesis (caracteres ( y )) para indicar la presencia de uno y sólo uno de los textos. - Uso de puntos suspensivos (caracteres ...) entre dos componentes sintácticos análogos para indicar la repetición indefinida de uno o más de esos componentes sintácticos. - En muchos casos se usa el caracter coma (caracter ,) como separador de componentes análogos. En el caso que exista sólo uno de estos componentes, este caracter coma no deberá expresarse. - En muchos casos se usan los caracteres en subíndice para indicar referencias a un mismo item sintáctico que pueden repetirse en distintas partes del texto (a través del La herramienta de modelado USE -4- mismo subíndice se hace referencia en distintas partes del texto al mismo item sintáctico). La estructura general de una especificación es la siguiente: model nombreEspecificación componentes del modelo conceptual [constraints definiciones de OCL ] corresponde a un identificador que será el nombre que tendrá esa especificación (no tiene que ver con el nombre del archivo donde se almacena la especificación). nombreEspecificación Los componentes de la especificación en la parte del modelo conceptual solamente (componentes del modelo conceptual en el diagrama anterior) son los siguientes: - Enumerados: enum idEnumerado {idCteEnum1, ..., idCteEnumn} El identificador idEnumerado indica el identificador-nombre que tendrá ese enumerado. Los identificadores idCteEnum1 a idCteEnumn son identificadores que representarán las constantes del enumerado. Las constantes de los enumerados deberán comenzar con mayúscula. - Clases: [abstract] class idClase [< idClase1, ..., idClaser] [attributes idAtrib1: expTipo1[;] ... idAtribn: expTipon[;]] [operations idOp1([par11: expTipo11, ..., par1k: expTipo1k])[: expTipoSal1 [= exp1]] [(pre|post) [idInvariante11]: exp11Bool ... La herramienta de modelado USE -5- (pre|post) [idInvariante1q]: exp1qBool][;] ... idOps([pars1: expTipos1, ..., parsp: expTiposp])[: expTipoSals [= exps]] [(pre|post) [idInvariantes1]: exps1Bool ... (pre|post) [idInvariantesx]: expsxBool][;]] [constraints inv idInvariante1: exp1Bool ... inv idInvariantem: expmBool] end El calificador abstract indica si la clase es abstracta (no se pueden crear objetos propios). El identificador idClase corresponde al nombre de la clase (su primera letra debe ser en mayúscula). Cada identificador idClasei corresponde al nombre de cada clase superiora jerárquica bajo la relación de herencia (en caso de existencia de la misma). La eventual existencia de más de una clase superiora indica que se puede expresar la existencia de herencia múltiple. Si bien se permite la existencia de herencia múltiple, no permite la existencia de múltiples discriminadores en las relaciones de herencia para la misma clase superiora, al igual que tampoco permite la existencia de modificadores de la relación de herencia respecto al solapamiento y la completitud (disjoint-joint, complete-incomplete). Luego de la cláusula attributes se especifican los atributos comunes de la clase. Cada identificador de la forma idAtribi corresponde al nombre del atributo i-ésimo de la clase (su primera letra debe ser en minúscula). Cada expresión de tipo de la forma expTipoi corresponde a la expresión de tipo asociada al atributo i-ésimo de la clase. Luego de la cláusula operations se especifican las responsabilidades comunes y derivadas de la clase (su primera letra debe ser en minúscula). Cada identificador de la forma idOpi corresponde al nombre de la operación i-ésima de la clase. Cada identificador de la forma parij corresponde al nombre del parámetro formal j-ésimo de la operación i-ésima. Cada expresión de tipo de la forma expTipoij corresponde a la expresión de tipo asociada al parámetro formal parij. Cada identificador de la forma expTipoSali corresponde a la expresión de tipo asociada a la expresión retornada del resultado de la operación i-ésima de la clase (si la operación es derivada -ésta retorna algún valor-). En el caso de no especificarse, se asume que la operación i-ésima de la clase, al no retornar nada, tiene un efecto colateral. Cada expresión de la forma expi corresponde a la expresión OCL retornada como resultado de la operación i-ésima de la clase -de tipo expTipoSali- (si ésta retorna algún valor). En el caso de especificarse, se asume que la operación i-ésima de la clase, al retornar una expresión, no tiene efectos colaterales, con lo que se concluye que es una operación derivada (responsabilidad derivada o query). Se pueden definir las precondiciones y postcondiciones de la operación i-ésima de la clase expresándolas en condiciones (que son expresiones OCL) correspondientes a cada una de las La herramienta de modelado USE -6- expresiones expijBool. En el caso de definirlas, se asumirá que la operación tiene efectos colaterales. Estas no se podrán definir en el caso que se haya indicado la expresión resultante expi, y viceversa. Luego de la cláusula constraints se especifican las restricciones de la clase. Se pueden establecer restricciones propias de la clase, que son invariantes de OCL aplicados al contexto de la clase. Para mayor claridad, ver más adelante la parte de invariantes de OCL. Los nombres de las clases, al igual que los tipos (tanto básicos como estructurados) y los nombres de invariantes, deben tener su primera letra en mayúscula. Los nombres de los atributos, al igual que los parámetros formales, deben tener su primera letra en minúscula. Los nombres de tipos de dato pueden ser nombres de clase, tipos predefinidos (tanto básicos como estructurados sobre otro tipo de dato) o enumerados. - Asociaciones: (association|aggregation|composition) idAsoc between idClase1[mult1] [role idRol1] [ordered][;] ... idClasen[multn] [role idRoln] [ordered][;] end Corresponde a una asociación (o sus casos particulares de agregación o composición) n-aria, con n=2 si es una asociación binaria, n=3 si es una asociación ternaria, y así sucesivamente- con información en cada uno de sus n extremos. Cada una se encuentra precedida por la cláusula association (si es asociación), aggregation (si es agregación) o composition (si es composición). En el diagrama de clases se podrá visualizar un rombo blanco en el primer rol indicado si es una agregación, o un rombo negro en el primer rol indicado si es una composición. El identificador de la forma idAsoc corresponde al nombre de la asociación. El identificador de la forma idClasei corresponde a la clase con que se relaciona el extremo iésimo. El identificador de la forma multi corresponde a la multiplicidad del extremo i-ésimo. Distintos casos de multiplicidades son los siguientes: mult1,..., multz número número..* * número1..número2 (unión de casos de multiplicidades -mult1 a multz-) (exactamente número instancias) (número instancias o más) (idéntico a 0..*) (desde número1 instancias hasta número2 instancias) El identificador de la forma idRoli corresponde al nombre del rol del extremo i-ésimo. El calificador ordered en un rol indica que en el caso de retornar un conjunto de objetos al usar ese rol, este conjunto de objetos retornados tendrá un valor posicional. Si la asociación es agregación o composición, en el gráfico aparecerá un rombo blanco o negro respectivamente, asociado al primer rol indicado. La herramienta de modelado USE -7- Los nombres de las asociaciones deben tener su primera letra en mayúscula. Los nombres de los roles deben tener su primera letra en minúscula. - Clases de asociación: [abstract] associationclass idClaseAsoc [< idClase1, ..., idClaser] [(aggregation|composition)] between idClase1[mult1] [role idRol1] [ordered][;] ... idClasen[multn] [role idRoln] [ordered][;] [attributes idAtrib1: expTipo1[;] ... idAtribt: expTipot[;]] [operations idOp1([par11: expTipo11, ..., par1k: expTipo1k])[: expTipoSal1 [= exp1]] [(pre|post) [idInvariante11]: exp11Bool ... (pre|post) [idInvariante1q]: exp1qBool][;] ... idOps([pars1: expTipos1, ..., parsp: expTiposp])[: expTipoSals [= exps]] [(pre|post) [idInvariantes1]: exps1Bool ... (pre|post) [idInvariantesx]: expsxBool][;]] [constraints inv [idInvariante1]: exp1Bool ... inv [idInvariantem]: expmBool] end Contiene todos los componentes propios de las clases y las asociaciones. Las clases de asociación tienen el mismo “status” que las clases comunes, con lo cual podrán tener atributos propios, como así también (otras) asociaciones, operaciones, y hasta relaciones de herencia con otras clases. La asociación propia de la clase de asociación no debe definirse además como asociación suelta. Se puede indicar también que la asociación implícita puede ser una agregación o composición. Como en el caso de las clases, también se pueden definir restricciones (invariantes OCL) dentro del contexto de la clase de asociación. Los nombres de las clases de asociación deben tener su primera letra en mayúscula en la definición, pero en el uso como parte de una expresión OCL, deben comenzar con minúscula. Los componentes de la especificación en la parte de las definiciones de OCL solamente (definiciones de OCL en el diagrama inicial) son los siguientes: La herramienta de modelado USE -8- - Invariantes: context idClase inv [idInvariante1]: exp1Bool ... inv [idInvariantem]: expmBool Los identificadores de la forma idInvariantei corresponden al nombre de cada uno de los invariantes del mismo contexto. Las expresiones de la forma expiBool corresponden a cada una de las condiciones (que son expresiones OCL) que deberán cumplirse para satisfacer ese invariante. Esta construcción es análoga a la existente en las clases y clases de asociaciones en sus cláusulas constraints. - Operaciones no derivadas (pre/postcondiciones): context idClase::idOpi([pari1: expTipoi1, ..., parik: expTipoik])[: expTipoSali] (pre|post) [idInvariantei1]: expi1Bool ... (pre|post) [idInvarianteiq]: expiqBool Define las precondiciones y postcondiciones de la operación idOpi de la clase idClase expresándolas en condiciones (que son expresiones OCL) correspondientes a cada una de las expresiones expijBool. A estas operaciones que se les definen precondiciones y postcondiciones USE asume que poseen efectos colaterales, y no se les especificó una expresión de retorno en las clases o clases de asociación donde fueron definidas. En ambos sectores de la especificación se pueden expresar comentarios. Cada comentario indicado tiene alcance desde cualquier parte de una línea comenzando por los caracteres -hasta el final de ella. - Comentarios: [Otros textos] -- Texto del comentario Componentes del entorno USE La herramienta USE se encuentra dentro de un archivo de extensión .zip o .tar.gz existente en la página Web de la herramienta. Este archivo deberá ser descomprimido en una carpeta del sistema operativo, manteniendo la estructura interna de carpetas. Para el sistema operativo Windows, la ejecución de la aplicación se realizará ejecutando el programa batch use-2.3.1\bin\use.bat. Esto abrirá una ventana de consola con un prompt donde La herramienta de modelado USE -9- el usuario escribe comandos de la consola USE. En la ventana de la consola, al inicio se podrá observar la siguiente leyenda: use version 2.3.1, Copyright (C) 1999-2006 University of Bremen use> _ Inmediatamente después de mostrar la consola con esta leyenda, aparece una ventana gráfica con la aplicación. Los comandos escritos en la consola tienen efecto en la ventana gráfica. Los componentes de la ventana gráfica son: Panel donde se ve el árbol de la especificación cargada. El nodo superior es una carpeta que tiene como nombre el nombre de la especificación (nombreEspecificación). Tiene cuatro subnodos que también son carpetas que son: (clases y clases de asociación de la especificación) (asociaciones, agregaciones y composiciones de la especificación) Invariants (invariantes de la especificación, descriptos en OCL) Pre-/Postconditions (definiciones de operaciones de la especificación “con efectos colaterales” en OCL a través de sus precondiciones y postcondiciones). Classes Associations La herramienta de modelado USE - 10 - Cada una de estas cuatro carpetas contiene como nodos cada uno de sus componentes definidos en la especificación. Cada uno de estos componentes se puede seleccionar. Panel donde se muestra la definición del último item seleccionado en el panel que no sea una carpeta (puede ser una clase, asociación, invariante o pre-/postcondición -según la nomenclatura de USE-). Panel donde se muestran las vistas relacionadas con la especificación. Cada vista es un gráfico que muestra componentes estáticos (su estructura) o dinámicos (información de los objetos definidos). Cada vista muestra un gráfico distinto. Panel de texto con información de log de las últimas operaciones realizadas (resultados de carga de especificaciones -correctas o incorrectas-, de actualización de objetos de la especificación, de revisión de consistencia, etc). Muestra información similar a la que muestra la consola de comandos al usar comandos análogos a los efectuados bajo la interfaz gráfica. Opciones de menú: Se indican aquí las opciones más representativas del entorno gráfico, agrupadas por menú: - Menú File: Opción Open specification... (Ctrl-O, botón ) Carga un archivo de especificación (que contiene el modelo conceptual -clases y asociaciones- y definiciones OCL -invariantes y pre/post-condiciones). El archivo de especificación tiene extensión .use. Si el modelo fuera erróneo se observarán los errores en el panel de log; si fuera correcto, en el panel de la especificación se verá ésta cargada con sus componentes. Opción Save script (.cmd)... (imagen ) Graba un archivo script con todos los comandos ejecutados por el usuario relacionados con la dinámica del modelo -estados de los objetos- en el mismo orden en que fueron efectuados (tanto desde la consola como desde la interfaz gráfica). Este archivo grabado poseerá extensión .cmd. El objetivo de esta grabación es luego poder cargar estos comandos, y reproducir la historia de los estados de los objetos de la especificación. Opción Save protocol... (imagen ) La herramienta de modelado USE - 11 - Graba un archivo de texto con todos los comandos ejecutados por el usuario desde la consola, y aquellos comandos ejecutados por el usuario desde la interfaz gráfica relacionados con los estados de los objetos, en el mismo orden en que fueron efectuados. Este archivo grabado poseerá extensión .protocol. El objetivo de esta grabación es dejar asentado un log de operaciones para luego ser verificado ante la existencia de algún problema. El contenido de protocolo (no como el script) no se limpia cuando se carga una nueva especificación. Opción Print diagram... (primer botón ) Imprime la vista seleccionada de la especificación, si corresponde a la vista del diagrama de clases (Class diagram) o a la del diagrama de objetos (Object diagram). Opción Print View... (segundo botón ) Imprime la vista seleccionada del modelo, si corresponde a la vista del diagrama de secuencias (Sequence diagram). Opción Exit Finaliza la ejecución de la interfaz gráfica, aunque la ejecución de la consola de comandos persiste. - Menú State: Opción Create Object... (F7) Crea un objeto de una clase idClase y le asigna un identificador idObjeto dado por el usuario. Al objeto recientemente creado no se le asignan valores a sus atributos ni a sus pseudoatributos. Todos los atributos del objeto tendrán valor Undefined al momento de la creación. Opción Evaluate OCL expression... (F8, botón ) Evalúa una expresión OCL (puede incluir como subexpresiones a “constantesobjeto” idObjeto) y retorna el resultado de su evaluación con su tipo de datos asociado. La expresión OCL a evaluar no debe contener subexpresiones que al evaluarse provoquen efectos colaterales -tengan definidas pre o postcondiciones-. En el caso de retornar “constantes-objeto” idObjeto, éstas se visualizarán precedidas por un caracter '@'. Las constantes de enumerados deberán escribirse (y también se visualizarán) precedidas por el caracter '#' (esto es realmente diferente de OCL standard, ya que allí las constantes enumeradas se describen como el La herramienta de modelado USE - 12 - nombre del tipo enumerado, luego los caracteres '::' y finalmente el nombre de la constante). Opción Check structure now... (F9) Revisa si todas las restricciones del modelo conceptual se cumplen (excluyendo a los invariantes de OCL). Puede fallar la revisión sobre el modelo propiamente dicho porque tanto los contenidos de los atributos de los objetos como de los pseudoatributos de ellos no se asignan en el momento de su creación. Los resultados podrán observarse en el panel de log. Opción Reset Limpia el contenido de comandos cargados, pero mantiene la especificación. - Menú View: Opción Create view → Object count (botón ) Muestra la cantidad de objetos creados por cada clase o clase de asociación (las identificadas como idClase y idClaseAsoc). Opción Create view → Link count (botón ) Muestra la cantidad de instancias de asociaciones creadas por cada asociación (las identificadas como idAsoc). Cabe recordar que los pseudoatributos de objetos de clases se crean aparte de los objetos, como instancias de asociaciones. Opción Create view → Class diagram (botón ) Muestra el gráfico del diagrama de clases propio de la especificación. Haciendo click derecho del mouse sobre esta vista, se podrá modificar qué componentes del gráfico visualizar, habilitar/deshabilitar la opción autolayout, y crear/cargar el layout de este gráfico (es un archivo de extensión .clt). En esta vista se permite también acomodar los componentes visibles del gráfico. Notar que los nombres de las clases abstractas aparecen en cursiva. Opción Create view → Object diagram (botón ) Muestra el gráfico del diagrama de objetos propio de la ejecución de comandos efectuados hasta el momento. El él se muestran todos los objetos creados junto con las asociaciones entre ellos. Haciendo click derecho del mouse sobre esta vista, se La herramienta de modelado USE - 13 - podrá modificar qué componentes del gráfico visualizar, habilitar/deshabilitar la opción autolayout, y crear/cargar el layout de este gráfico (es un archivo de extensión .olt). Si se seleccionara un objeto del gráfico, aparecerá una nueva vista de Object properties aplicada a ese objeto (ver más adelante). En esta vista se permite también acomodar los componentes visibles del gráfico. Opción Create view → Class invariants (botón ) Muestra el estado de todos los invariantes de OCL definidos en el modelo si se cumplen o no respecto a todos los objetos creados (verifica sólo las restricciones de invariantes de OCL, y no las del modelo propiamente dicho). En cada renglón se podrá observar cada invariante, con un valor lógico asociado como resultado que puede ser true o false, indicando si ese invariante se cumple o no en función del estado dinámico del modelo reflejado por los objetos. Si se seleccionara un invariante de esta vista, aparecerá una nueva ventana titulada Evaluation browser explicando cómo se llega a ese resultado verdadero o falso en ese invariante. Opción Create view → State evalution (botón ) Muestra la cantidad de objetos creados (en azul) y de instancias de asociaciones (en rojo) en función de la historia (las opciones que permiten cambios de estado de objetos cambian estas cantidades). Opción Create view → Object properties (botón ) Permite asignar/modificar los valores asociados a los atributos de un objeto dado. No permite asignar/modificar los valores de sus pseudoatributos. Opción Create view → Class extent (botón ) Permite visualizar los estados de todos los objetos creados de una clase dada. Opción Create view → Sequence diagram (botón ) Permite visualizar un “diagrama de secuencias” donde se reflejan todos los comandos ejecutados por el usuario (tanto dentro del entorno como desde la consola de comandos) relacionados con cambios de estado del modelo (operaciones asociadas a algún tipo de cambio en sus objetos). Haciendo click derecho del mouse sobre esta vista, se podrá modificar qué comandos visualizar en el diagrama y varias propiedades de su visualización. La herramienta de modelado USE - 14 - Opción Create view → Call stack (botón ) Permite visualizar la pila de objetos con sus “mensajes pendientes de resultado” (indica que cada objeto “receptor” de esa pila le debe la “respuesta” de su operación asociada -con sus parámetros- a su objeto llamador, que es el inferior inmediato en esa pila). En la cabeza de esta pila siempre figura el objeto emisor actual y su último mensaje recibido por el objeto anterior (invocación a una operación propia), lo que reflejaría la última operación activada con su objeto receptor. Si la pila fuera vacía, el objeto emisor actual es el usuario, que no posee operaciones propias. Estos objetos que deben la respuesta a su objeto llamador pueden observarse en el diagrama de secuencias. Los mensajes para los cuales se deben respuestas se pueden asocian tanto a operaciones con efectos colaterales (con pre/postcondiciones) como a operaciones sin efectos colataterales. Opción Create view → Command list (botón ) Permite visualizar todos los comandos ejecutados por el usuario (tanto dentro del entorno como desde la consola de comandos) relacionados con cambios de estado del modelo (operaciones asociadas a algún tipo de cambio en sus objetos) en el mismo orden en que se efectuaron. Algunos comandos válidos de la consola !create idObjeto1, ..., idObjeton: idClase Crea uno o más objetos de la clase idClase, y le asigna a cada uno identificadores idObjeto1 a idObjeton respectivamente. Todos los atributos de los objetos creados tendrán valor Undefined al momento de la creación. No permite crear objetos cuyo nuevo identificador asignado (idObjetoi) esté siendo usado por otro objeto existente. (Análoga a la opción de menú Create Object...). !create idObjeto: idClaseAsoc between (idObjeto1, ..., idObjeton) Crea un objeto de la clase de asociación idClaseAsoc, y le asigna un identificador idObjeto, que sea mapea a la instancia de la asociación vinculada representada por la n-upla (idObjeto1, ..., idObjeton) pertenciente a la n-upla de clases (idClase1, ..., idClasen) establecidas en el mismo orden en que figuran en la definición de la clase de asociación idClaseAsoc, si es que esa instancia no fue creada antes). No permite crear el objeto si su nuevo identificador asignado idObjeto está siendo usado por otro objeto existente. (No tiene equivalente en la interfaz gráfica). La herramienta de modelado USE - 15 - idObjeto.idAtrib := exp !set Asigna/modifica el valor del atributo idAtrib del objeto idObjeto por la expresión exp. No permite que idAtrib sea un pseudoatributo. (No tiene equivalente en la interfaz gráfica directamente, aunque su funcionalidad está embebida en la opción de menú Object properties). !insert (idObjeto1, ..., idObjeton) into idAsoc Crea una instancia de la asociación n-aria idAsoc conformada por la n-upla (idObjeto1, ..., idObjeton) pertenciente a la n-upla de clases (idClase1, ..., idClasen) establecidas en el mismo orden en que figuran en la definición de la asociación idAsoc, si es que esa instancia no fue creada antes. Se puede utilizar también para crear “objetos anónimos” de una supuesta clase de asociación vinculada a esa asociación idAsoc -si es que la clase de asociación existiera-. (No tiene equivalente en la interfaz gráfica). !delete (idObjeto1, ..., idObjeton) from idAsoc Elimina la instancia de la asociación n-aria idAsoc conformada por la n-upla (idObjeto1, ..., idObjeton) pertenciente a la n-upla de clases (idClase1, ..., idClasen) establecidas en el mismo orden en que figuran en la definición de la asociación idAsoc, si es que esa instancia ya fue creada antes. Se puede utilizar también para borrar “objetos anónimos” de una supuesta clase de asociación vinculada a esa asociación idAsoc -si es que la clase de asociación existiera-. (No tiene equivalente en la interfaz gráfica). !destroy idObjeto1, ..., idObjeton Destruye a los objetos cuyos identificadores sean idObjeto1 a idObjeton. A partir de ese momento, esos objetos quedan inusables. Elimina “implícitamente” (sin avisar al usuario) las instancias de asociaciones donde participan los objetos destruídos. (No tiene equivalente en la interfaz gráfica). check Revisa si todas las restricciones del modelo se cumplen (tanto las del modelo propiamente dicho como las de los invariantes de OCL). (No tiene un equivalente directo en la interfaz gráfica, aunque sería una generalización de la opción de menú Check structure now -revisa sólo modelo conceptual- y de la vista Class invariants -revisa sólo invariantes de OCL-). ? exp Evalúa la expresión OCL exp, si es que no contiene subexpresiones que al evaluarse provoquen efectos colaterales -tengan definidas pre o postcondiciones-. La herramienta de modelado USE - 16 - (Análoga a la opción de menú Evaluate OCL expression...). open nombreArchivo Carga un archivo de especificación (si nombreArchivo tiene extensión .use), o carga un archivo script con todos los comandos ejecutados por el usuario relacionados con la dinámica del modelo (si nombreArchivo tiene extensión .cmd). (Análoga a la opción de menú Open specification... en el primer caso, pero sin equivalente en la interfaz gráfica en el segundo). reset Limpia el contenido de comandos cargados, pero mantiene la especificación. (Análoga a la opción de menú Reset). help [comando] Muestra una descripción general de todos comandos válidos con sus parámetros. En el caso de especificarse el comando dado comando, muestra una descripción más detallada del mismo. (No tiene equivalente en la interfaz gráfica). q quit exit Abandona la aplicación en su totalidad. (Similar a la opción de menú Exit, aunque abandona toda la aplicación -cierra tanto la ventana de consola de comandos, como la de la interfaz gráfica-). Respecto al uso del diagrama de secuencias El diagrama de secuencias refleja el pasaje de mensajes efectuados entre los objetos del modelo dinámico de la especificación, propio de la ejecución de los comandos efectuados por el usuario. Cada mensaje generado en el diagrama de secuencias es enviado por un objeto emisor, que en el momento del inicio de la ejecución en el diagrama es el usuario (el objeto “hombre palito”). Cada uno de los comandos ejecutados -relacionados con cambios de estado de los objetos de la especificación- genera disparos en el diagrama de secuencias. Estos son: !create idObjeto1, ..., idObjeton: idClase Por cada objeto i a crear, el objeto emisor envía un mensaje de creación create a la clase idClase, creando el objeto correspondiente idObjetoi. El control es devuelto al objeto emisor. La herramienta de modelado USE - 17 - !create idObjeto: idClaseAsoc between (idObjeto1, ..., idObjeton) No realiza cambios sobre el diagrama. Probablemente sea un error de USE. !set idObjeto.idAtrib := exp El objeto emisor envía un mensaje set idAtrib := exp al objeto idObjeto. El objeto receptor idObjeto no realiza envío de mensajes a otros objetos si la evaluación de exp contiene invocaciones a otros mensajes. La expresión exp no debe contener subexpresiones que provoquen efectos colaterales. El control es devuelto al objeto emisor. !insert (idObjeto1, ..., idObjeton) into idAsoc El objeto emisor envía un mensaje insert(@idObjeto1, ..., @idObjeton) a la “clase” idAsoc, creando el “objeto n-upla” (idObjeto1, ..., idObjeton). Luego a cada objeto integrante de la n-upla idObjetoi, esa “clase” idAsoc envía un mensaje inserted as idRoli. El control es devuelto finalmente al objeto emisor. !delete (idObjeto1, ..., idObjeton) from idAsoc El objeto emisor envía un mensaje de destrucción delete(@idObjeto1, ..., @idObjeton) al “objeto n-upla” (idObjeto1, ..., idObjeton), destruyéndolo. El control es devuelto al objeto emisor. !destroy idObjeto1, ..., idObjeton Por cada objeto i a destruir, el objeto emisor envía un mensaje de destrucción destroy al objeto idObjetoi, destruyéndolo. El control es devuelto al objeto emisor. !openter expObjeto idOp([exp1, ..., expn]) El objeto emisor envía un mensaje idOp([exp1, ..., expn]) al objeto-expresión expObjeto, pasando a ser el objeto resultante de la evaluación de este último como el nuevo objeto emisor y apilando al objeto resultante receptor en la pila de “objetos receptores anteriores”. La pila de objetos receptores anteriores con sus mensajes enviados en instancias anteriores de este comando !openter se puede ver con la opción de menú Call stack. Este comando !openter puede implicar la aplicación de una operación con efectos colaterales, y más especialmente, con precondiciones (si la operación idOp las tuvieran). En el caso de ocurrir esto último, se realiza una verificación de consistencia por si las precondiciones de la responsabilidad aplicada se cumplen. En el caso que no se cumplan, se podrá observar el mensaje de error. !opexit [exp] La herramienta de modelado USE - 18 - El objeto emisor retorna como resultado a la expresión exp (si se indicara) del mensaje recibido por él enviado por el “objeto emisor anterior” (en la cabeza de la pila de la vista Call stack figura el objeto emisor junto con el mensaje recibido por él enviado por el objeto emisor anterior), desapilando al emisor actual con su operación finalizada y estableciendo como nuevo emisor actual al inmediato anterior, continuando con su operación asociada allí indicada. Este mensaje de retorno al llamador se expresa en el diagrama como una línea de puntos, con el valor retornado exp, si se indicara. Este comando !opexit puede determinar la finalización de la ejecución de una operación (la que existía en la pila con su objeto receptor antes del desapilamiento) que posea efectos colaterales, con lo cual puede implicar un cambio de estado del objeto desapilado respecto al momento de la recepción del mensaje (en el momento de su !openter correspondiente). Por eso, realiza una verificación de consistencia por si las postcondiciones de la operación aplicada (desapilada) se cumplen. Si no se cumplieran, la línea de puntos de retorno del mensaje aparecerá en el diagrama en rojo. Diferencias entre el lenguaje OCL de USE y el OCL stándard - El lenguaje OCL propio de USE no permite utilizar expresiones OCL cuyo tipo asociado (o parte de él, si es un tipo estructurado) sea una variable de tipos. En concreto no están permitidas las siguientes expresiones OCL: OCL standard: OCL standard: OCL standard: Set {} Bag {} Sequence {} porque los tipos de datos asociados a estas expresiones serían Set(T), Bag(T) y Sequence(T) respectivamente, con T una variable de tipos. En el lenguaje OCL de USE no se pueden usar variables de tipo, con lo que en los casos anteriores, el tipo T debe ser especializado. Como reemplazo de las anteriores se usan las siguientes expresiones correspondientes (por ejemplo, especializando el tipo variable T en Integer): OCL propio de USE: OCL propio de USE: OCL propio de USE: oclEmpty(Set(Integer)) oclEmpty(Bag(Integer)) oclEmpty(Sequence(Integer)) Esta sería la forma de escribir colecciones vacías: OCL propio de USE: oclEmpty(cteOCLType) La herramienta de modelado USE - 19 - donde la constante cteOCLType representa una constante de tipo OCLType (inexistente en OCL de USE) que es el nombre de un tipo de datos de colección especializado (que no contenga ninguna subexpresión que sea una variable de tipos). - El lenguaje OCL propio de USE no implementa los métodos de conversión de colecciones sin valor posicional a colecciones con valor posicional. Serían los siguientes: Set(T)->asSequence(): Sequence(T) Bag(T)->asSequence(): Sequence(T) El motivo es que estos métodos son “no determinísticos” porque no existe ningún criterio para establecer órdenes posicionales en la colección resultante a partir de una colección sin ordenamiento posicional. - El lenguaje OCL propio de USE renombra el siguiente método de OCL standard: OCLAny.OCLisUndefined(): Boolean como una constante “indefinida” del tipo de datos que se requiera, que se comparará con otras expresiones usando la igualdad: oclUndefined(cteOCLType): T donde la constante cteOCLType representa una constante de tipo OCLType (como ya mencionamos, inexistente en OCL de USE) que es el nombre de un tipo de datos válido, y que es el “equivalente” al tipo retornado T. Ejemplo (aquí edad representa la edad de una persona, de tipo Integer): OCL standard: OCL propio de USE: edad.OCLisUndefined() edad = oclUndefined(Integer) - El lenguaje OCL propio de USE obliga a expresar las constantes idCteEnum de tipo enumerado idEnumerado de una forma distinta: OCL standard: OCL propio de USE: idEnumerado::idCteEnum #idCteEnum Con esto, se da a entender que no pueden existir distintas constantes enumeradas de distintos tipos enumerados con el mismo identificador. - El lenguaje OCL propio de USE obliga a no escribir los paréntesis finales de la operación de clase .allInstances(): OCL standard: OCL propio de USE: idClase.allInstances() idClase.allInstances La herramienta de modelado USE - 20 - - El lenguaje OCL propio de USE trata de una forma distinta a los pseudoatributos con multiplicidades 0..1 que el lenguaje OCL puro. Si psatrib fuera un pseudoatributo de la clase A de multiplicidad 0..1 sobre la clase B, y a fuera una expresión de tipo A, la expresión a.psatrib no devolverá una expresión de tipo Set(B), sino una expresión de tipo B. Los resultados de su evaluación serán los siguientes: Caso 1) a.psatrib = Set{b} (tamaño 1) OCL standard: OCL propio de USE: Set{b} b (de tipo Set(B)) (de tipo B) Caso 2) a.psatrib = Set{} (tamaño 0) OCL standard: OCL propio de USE: Set{} oclUndefined(B) (de tipo Set(B)) (de tipo B) Esto ocurre sólo con este caso particular de multiplicidad. Para el resto de los casos de multiplicidad “múltiple”, siempre retornará una expresión de tipo Set(B), como OCL standard. - El lenguaje OCL propio de USE no implementa: - El tipo de datos OrderedSet(T) con sus operaciones. Asume que la versión “ordered” del tipo Set(T) es Sequence(T). - El tipo de datos OCLState con su operación .OCLinState(estado), aplicados a objetos para verificar si el objeto se encuentra en el estado estado (expresión de tipo OCLState) según los statecharts aplicados a su clase correspondiente. - Otros tipos de definiciones (cláusulas init -valores iniciales de atributos en la creación de objetos- y def -definiciones auxiliares-). - El modelo de tuplas para representar efectos colaterales en parámetros de responsabilidades, para el caso de las postcondiciones. Sin embargo el tipo Tuple con sus operaciones de proyección sí se encuentra implementado, al igual que los sufijos @pre luego de atributos y pseudoatributos en las postcondiciones, y la operación .oclIsNew(), muy utilizada dentro del contexto de efectos colaterales. - El tipo de datos OCLType (el tipo de datos de las expresiones de tipo) y las operaciones de metaclase. - Mensajes (messages). La herramienta de modelado USE - 21 - Generators USE define también un lenguaje propio basado en procedimientos para poder realizar procedimientos de secuencias estructuradas de comandos a impactar en el estado global del modelo. A este lenguaje procedural se lo conoce como ASSL (A Snapshot Sequence Language). Los procedimientos ASSL se suelen guardar en archivos aparte (comúnmente archivos de texto de extensión .assl), y se pueden ejecutar desde la consola de comandos (ver los comandos de generators de la consola). Por un tema de complejidad, los generators no serán tratados aquí. Un ejemplo Se expresa aquí un ejemplo de especificación (un archivo de especificación ejemplo.use). Más abajo se podrá observar la aplicación USE con esta especificación cargada, mostrando su vista de Class diagram con un layout elegante). Se quiere representar información de alumnos. Los alumnos se caracterizan por tener un número de libreta (que debe ser un número positivo), un nombre, un tipo (que puede ser regular, libre o asociado) y un año de inscripción. Los alumnos pueden ser acelerados o normales. Los alumnos normales se caracterizan por cursar en sólo una de las sedes, aunque esta sede puede cambiarse en cualquier momento. Los alumnos acelerados no cursan en ninguna sede concreta (sólo asisten por Internet), y poseen una cantidad de años de tolerancia para aprobar todas las materias. Para que un alumno pueda aprobar una materia, primero tiene que haberse anotado en esa materia (no importa registrar esa fecha) y luego haber rendido un examen de esa materia, con una nota de aprobación (mayor o igual a 4). En el caso de no aprobar el examen puede presentarse posteriormente sucesivamente hasta aprobarlo. No importa reflejar la historia de exámenes de un alumno por materia (sólo importa conocer el último). Los exámenes son individuales, y su año de evaluación debe ser posterior al de la inscripción del alumno. Los alumnos no pueden dar nuevos exámenes de una materia que ya hayan aprobado con anterioridad. En cualquier momento se quiere saber si un alumno está recibido (si aprobó todas las materias existentes). Este es el contenido de la especificación: model Alumnos enum TipoDeAlumno {Regular, Libre, Invitado} abstract class Alumno attributes libreta: Integer La herramienta de modelado USE - 22 nombre: String tipo: TipoDeAlumno anioInscrip: Integer operations recibido(): Boolean = self.evaluadoEn = Materia.allInstances and self.examen->forAll(e | e.nota >= 4) rendir(n: Integer, m: Materia, a: Integer) end class AlumnoAcelerado < Alumno attributes anioTope: Integer end class AlumnoNormal < Alumno operations cambioSede(s: Sede) end class Sede attributes nombre: String end association AAC between AlumnoNormal[0..*] role cursantes Sede[1] role cursaEn end class Materia attributes nombre: String end association IAM between Alumno[0..*] role inscriptos Materia[0..*] role anotadoEn end associationclass Examen between Alumno[0..*] role examinados Materia[0..*] role evaluadoEn attributes nota: Integer anioNota: Integer end constraints --Libreta de los alumnos debe tener un número positivo context Alumno inv LibretaNumPos: self.libreta > 0 --Los alumnos con examen deben estar anotados en la materia de ese examen context Examen inv AlConExInscr: self.examinados.anotadoEn->includes(self.evaluadoEn) --Todos los examenes de un alumno deben ser posteriores al año de su inscripción context Examen inv NotaPostInscr: self.anioNota < self.examinados.anioInscrip --Los alumnos acelerados no pueden tener examenes posteriores a su año de inscripción más --su cantidad de años tope context AlumnoAcelerado inv AlAceleradoEnFecha: self.examen->forAll(e | e.anioNota <= self.anioInscrip + self.anioTope) --Responsabilidad 'cambioSede' context AlumnoNormal::cambioSede(s: Sede) pre: Sede.allInstances->includes(s) post: self.cursaEn = s --Responsabilidad 'rendir' context Alumno::rendir(n: Integer, m: Materia, a: Integer) La herramienta de modelado USE - 23 pre: (self.anotadoEn->includes(m)) and (self.anioInscrip <= a) and not(self.examen->exists(e | (e.evaluadoEn = m) and ((e.nota >= 4) or (e.anioNota > a)))) post: let na = self.examen->select(e | e.evaluadoEn = m) in na->size() = 1 and na->forAll(e | e.nota = n and e.anioNota = a) --end model Luego de cargar la especificación y de visualizar la vista de Class diagram con un layout elegante, la aplicación se podrá ver de la siguiente forma: Apéndice A: Comandos de la consola Este es el resultado de la ejecución del comando help de la consola. Para obtener en mayor detalle la descripción de un determinado comando, escriba el nombre del comando luego de help. ============================General commands============================ help [!CMD] Print available commands ==========================Evaluation commands=========================== ? EXPR Compiles and evaluates EXPR ?? EXPR Compiles and evaluates EXPR (verbose) : EXPR Compiles EXPR and shows its static type \ Enter OCL-Expressions over multiple lines ======================State manipulation commands======================= ! CMD Executes state manipulation command La herramienta de modelado USE - 24 - !create <id-list> : <class> [between (<id-list>)] Creates objects !destroy <id-list> Destroys objects !insert (<id-list>) into <assoc> Insert link into association !delete (<id-list>) from <assoc> Delete link from association !set <obj-id>.<attr-id> := <expr> Set attribute value of object !openter <obj-expr> <name> ([<expr-list>]) Enters object operation !opexit [<result-expr>] Exits least recently entered operation check [-v] [-d] [ -a | inv-list ] Checks integrity constraints step on Activates single-step mode ===============================File input=============================== open [-q] FILE Reads information from FILE read FILE Deprecated. Reads commands from FILE readq FILE Deprecated. Reads commands quietly from FILE reset Reset system to empty state q, quit, exit Exit USE undo Undo last state manipulation command ==========================Information commands========================== info SUBCOMMAND Print info info class NAME Print info about class info model Print info about loaded model info state Print info about current system state info opstack Print currently active operations info prog Print internal program infos info vars Prints information about global variables ===========================Generator commands=========================== gen unload [invnames] Unloads added class invariants gen loaded Prints loaded class invariants gen flags [invnames] [+d|-d] [+n|-n] Switch invariant evaluation flags gen start [options] FILE PROCNAME([params]) Search valid system state gen result Prints results of last generator search gen result inv Prints statistics of last generator search gen result accept Accept result of last generator search Apéndice B: Gramática de USE Comandos de consola cmdList cmd cmdStmt cmdStmt cmdStmt cmdStmt cmdStmt cmdStmt cmdStmt cmdStmt cmdStmt cmdStmt createCmd createAssignCmd createInsertCmd destroyCmd insertCmd ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= deleteCmd ::= setCmd opEnterCmd opExitCmd letCmd ::= ::= ::= ::= Generators cmd { cmd } cmdStmt [ ";" ] createCmd createAssignCmd createInsertCmd destroyCmd insertCmd deleteCmd setCmd opEnterCmd opExitCmd letCmd "create" idList ":" simpleType "assign" idList ":=" "create" simpleType "create" id ":" simpleType "between" "(" "destroy" expression { "," expression } "insert" "(" expression "," expression { "into" id "delete" "(" expression "," expression { "from" id "set" expression ":=" expression "openter" expression id "(" [ expression "opexit" [ expression ] "let" id [ ":" type ] "=" expression idList ")" "," expression } ")" "," expression } ")" { "," expression } ] ")" La herramienta de modelado USE - 25 - invariantListOnly procedureListOnly procedure variableDeclarationList instructionList instruction instruction instruction instruction instruction instruction variableAssignment attributeAssignment loop valueInstruction valueInstruction atomicInstruction instructionParameter instructionParameter instrParameterIdent oclExpression ifThenElse procedureCallOnly ::= { invariant } ::= (procedure)* ::= "procedure" id "(" variableDeclarationList ")" ("var" variableDeclarationList ";")? "begin" instructionList "end" ";" ::= (variableDeclaration ("," variableDeclaration)* )? ::= ( instruction ";" )* ::= variableAssignment ::= attributeAssignment ::= loop ::= atomicInstruction ::= ifThenElse (Aún no implementado) ::= cut ::= id ":=" valueInstruction ::= oclExpression DOT id ":=" valueInstruction ::= "for" variableDeclaration "in" oclExpression "begin" instructionList "end" ::= atomicInstruction ::= oclExpression ::= id "(" ( instructionParameter (","instructionParameter)* )? ")" ::= oclExpression ::= instrParameterIdent ::= id ::= "[" expression "]" ::= "if" oclExpression "then" "begin" instructionList "end" ("else" "begin" instructionList "end")? ";" ::= id "(" ( expression ( "," expression )* )? ")" OCL idList variableDeclaration expressionOnly expression ::= ::= ::= ::= conditionalImpliesExpression conditionalOrExpression conditionalXOrExpression conditionalAndExpression equalityExpression relationalExpression ::= ::= ::= ::= ::= ::= additiveExpression multiplicativeExpression unaryExpression unaryExpression postfixExpression primaryExpression primaryExpression primaryExpression primaryExpression propertyCall propertyCall propertyCall propertyCall queryExpression ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= iterateExpression ::= operationExpression ::= typeExpression elemVarsDeclaration variableInitialization ifExpression literal literal literal literal literal literal ::= ::= ::= ::= ::= ::= ::= ::= ::= ::= id { "," id } id ":" type conditionalImpliesExpression { "let" id [ : type ] "=" expression "in" } conditionalImpliesExpression conditionalOrExpression { "implies" conditionalOrExpression } conditionalXOrExpression { "or" conditionalXOrExpression } conditionalAndExpression { "xor" conditionalAndExpression } equalityExpression { "and" equalityExpression } relationalExpression { ("=" | "<>") relationalExpression } additiveExpression { ("<" | ">" | "<=" | ">=") additiveExpression } multiplicativeExpression { ("+" | "-") multiplicativeExpression } unaryExpression { ("*" | "/" | "div") unaryExpression } ( "not" | "-" | "+" ) unaryExpression postfixExpression primaryExpression { ( "." | "->" ) propertyCall } literal (propertyCall contiene variables) propertyCall "(" expression ")" ifExpression queryExpression iterateExpression operationExpression typeExpression ("select" | "reject" | "collect" | "exists" | "forAll" | "isUnique" | "sortedBy" ) "(" [ elemVarsDeclaration "|" ] expression ")" "iterate" "(" elemVarsDeclaration ";" variableInitialization "|" expression ")" id ( ("[" id "]") | ( [ "@" "pre" ] [ "(" [ expression { "," expression } ] ")" ] ) ) ("oclAsType" | "oclIsKindOf" | "oclIsTypeOf") "(" type ")" idList [ ":" type ] id ":" type "=" expression "if" expression "then" expression "else" expression "endif" "true" "false" INT REAL STRING "#" id La herramienta de modelado USE - 26 literal literal literal literal collectionLiteral ::= ::= ::= ::= ::= collectionItem emptyCollectionLiteral undefinedLiteral tupleLiteral tupleItem type type type simpleType ::= ::= ::= ::= ::= ::= ::= ::= ::= collectionType tupleType tuplePart ::= ::= ::= collectionLiteral emptyCollectionLiteral undefinedLiteral tupleLiteral ( "Set" | "Sequence" | "Bag" ) "{" collectionItem { "," collectionItem } "}" expression [ ".." expression ] "oclEmpty" "(" collectionType ")" "oclUndefined" "(" type ")" "Tuple" "{" tupleItem { "," tupleItem } "}" id ":" expression simpleType collectionType tupleType (Un simpleType puede ser un tipo básico -Boolean, id Integer, Real, String-, un tipo enumerado, un tipo-clase u OclAny) ( "Collection" | "Set" | "Sequence" | "Bag" ) "(" type ")" "Tuple" "(" tuplePart { "," tuplePart } ")" id ":" type Especificaciones de USE Model enumTypeDefinition generalClassDefinition classDefinition Specialization Attributes Operations Constraints associationClassDefinition attributeDefinition operationDefinition associationDefinition associationEnd multiplicity multiplicityRange multiplicitySpec multiplicitySpec constraintDefinition constraintDefinition invariant invariantContext invariantClause prePost prePostContext prePostClause ::= "model" id { enumTypeDefinition } { classDefinition | associationDefinition | "constraints" { invariant | prePost } } ::= "enum" id "{" idList "}" [ ";" ] ::= [ "abstract" ] { classDefinition | associationClassDefinition } ::= [ "abstract" ] "class" id [ specialization ] [ attributes ] [ operations ] [ constraints ] "end" ::= "<" idList ::= "attributes" { attributeDefinition } ::= "operations" { operationDefinition } ::= "constraints" { invariantClause } ::= [ "abstract" ] "associationClass" id [ specialization ] [ attributes ] [ operations ] [ constraints ] [( "aggregation" | "composition" )] "between" associationEnd { associationEnd }+ "end" ::= id ":" type [ ";" ] ::= id paramList [ ":" type [ "=" expression ] ] { prePostClause } [ ";" ] ::= ( "association" | "aggregation" | "composition" ) id "between" associationEnd associationEnd { associationEnd } "end" ::= id "[" multiplicity "]" [ "role" id ] [ "ordered" ] [ ";" ] ::= multiplicityRange { "," multiplicityRange } ::= multiplicitySpec [ ".." multiplicitySpec ] ::= "*" ::= INT ::= invariant ::= prePost ::= invariantContext invariantClause { invariantClause } ::= "context" [ id ":" ] simpleType ::= "inv" [ id ] ":" expression ::= prePostContext prePostClause { prePostClause } ::= "context" id "::" id paramList [ ":" type ] ::= ("pre" | "post") [ id ] ":" expression Bibliografía - The Unified Modeling Language user guide (G. Booch, J. Rumbaugh, I. Jacobson) (1999) Addison-Wesley. La herramienta de modelado USE - 27 - - UML 2.0 OCL specification (documento de la OMG publicado en Internet en “http://www.omg.org/docs/ptc/03-10-14.pdf”). - A UML-based specification environment (sitio en Internet principal de la herramienta USE, ubicado en “http://www.db.informatik.uni-bremen.de/projects/USE/”). - ASSL A Snapshot Sequence Language (documento “http://www.db.informatik.uni-bremen.de/projects/USE/assl.ps”). ubicado en