OCL (Object Constraint Language) Juan Casas Cuevas Mercedes Arenas Fernández Facultad de Informática - Universidad Politécnica de Valencia RESUMEN ..........................................................................................................................2 1.- INTRODUCCIÓN ............................................................................................................2 2.- ÁLGEBRA RELACIONAL .............................................................................................. 4 3.- DIAGRAMA DE CLASES DE EJEMPLO ........................................................................ 4 3.1. CONEXIÓN CON EL METAMODELO UML ......................................................................... 6 3.1.1. SELF........................................................................................................................ 6 3.1.2. ESPECIFICAR EL CONTEXTO UML ................................................................................ 6 3.1.3. INVARIANTES ........................................................................................................... 6 3.1.4. PRE- Y POSTCONDICIONES ..........................................................................................7 3.2.- OPERADORES .............................................................................................................7 3.2.1. LA EXPRESIÓN LET .....................................................................................................7 3.2.2. CONCORDANCIA DE TIPOS ......................................................................................... 8 3.2.3. RETIPADO O CASTING ............................................................................................... 8 3.2.4. REGLAS DE PRECEDENCIA .......................................................................................... 8 3.3. PROPIEDADES ............................................................................................................ 9 3.3.1. ATRIBUTOS.............................................................................................................. 9 3.3.2. OPERACIONES ......................................................................................................... 9 3.3.3. COMBINACIÓN DE PROPIEDADES ................................................................................ 9 3.3.4. ACCESO A LAS PROPIEDADES QUE SOBREESCRIBEN SUPERTIPOS ..................................... 9 3.3.5. PROPIEDADES PREDEFINIDAS EN TODOS LOS OBJETOS .................................................. 10 3.3.6. CARACTERÍSTICAS DE LAS PROPIAS CLASES ................................................................. 10 3.3.7. COLECCIONES ..........................................................................................................11 3.3.8. VALORES PREVIOS EN LAS POSTCONDICIONES .............................................................. 11 3.4. OPERACIONES SOBRE COLECCIONES ............................................................................. 12 3.4.1. OPERACIONES SELECT Y REJECT ................................................................................ 12 3.4.2. OPERACIÓN COLLECT .............................................................................................. 12 3.4.3. OPERACIÓN FORALL ............................................................................................... 13 3.4.4. OPERACIÓN EXISTS ................................................................................................. 13 4.- EL PAQUETE ESTÁNDAR OCL ................................................................................... 13 5.- GRAMÁTICA ............................................................................................................... 14 6.- CONCLUSIONES ......................................................................................................... 14 7.- REFERENCIAS ............................................................................................................. 15 1 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Resumen El objetivo de este trabajo es conocer un lenguaje de restricciones de objetos: Object Constraint Language (OCL), que forma parte del UML 1.1. Es un conjunto de notaciones precisas de lenguaje textual para expresar restricciones que no pueden ser expresadas en la notación de diagramas estándar usada en UML. La semántica de OCL se aplica sobre la base de la construcción de herramientas CASE que soportan comprobaciones de integridad sobre todos los modelos UML, no sólo sobre los componentes expresados en OCL. Este documento proporciona la semántica de OCL, al mismo tiempo que proporciona una semántica para clases, asociaciones, atributos y estados. 1.- Introducción UML (Unified Modeling Language, lenguaje de modelización unificado) es un lenguaje para especificar, construir, visualizar y documentar los objetos de un sistema intensivo de software. Un diagrama UML, como puede ser un diagrama de clases, normalmente no está lo suficientemente refinado y, por tanto, no refleja todos los aspectos relevantes de una especificación. Existe, entre otras cosas, la necesidad de describir restricciones adicionales sobre los objetos en el modelo. La práctica demuestra que esto siempre se traduce en ambigüedades. Con el objetivo de escribir restricciones no ambiguas, se han desarrollado lenguajes pseudo-formales. La desventaja de los lenguajes formales tradicionales es que se suelen usar por personas con un amplio conocimiento matemático, pero dificulta su utilización para personas de negocios o analistas de sistemas. OCL (Object Constraint Language, lenguaje de restricciones de objetos) es un nuevo lenguaje notacional un subconjunto del UML estándar industrial, que permite a los desarrolladores de software escribir restricciones sobre modelos de objetos (pre y postcondiciones, guardas, invariantes, valores derivados, restricciones sobre operaciones, etc.). Estas restricciones son particularmente útiles, en la medida en que permiten a los desarrolladores crear un amplio conjunto de reglas que rigen el aspecto de un objeto individual. OCL tiene las características de un lenguaje de expresiones, un lenguaje de modelos y un lenguaje formal: Lenguaje de expresiones OCL es un lenguaje de expresiones puro. Una expresión OCL garantiza que quedará sin efecto. Esto no puede cambiar nada en el modelo. Esto significa que un estado del sistema nunca cambiará debido a una expresión OCL, incluso una expresión OCL podría usarse para describir tal cambio de estado (p.e. en una postcondición).Todos los valores de todos los objectos, incluidos los enlaces, no 2 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia cambiarán. En cualquier momento en que se evalúa una expresión OCL, simplemente devuelve un valor. Lenguaje de modelos OCL es un lenguaje de modelos y no un lenguaje de programación. No se puede escribir un programa lógico o un flujo de control en OCL. Especialmente, no se puede invocar procesos o activar operaciones no de consulta en OCL. Debido a que OCL es en primer lugar un lenguaje de modelos, no se puede asegurar que todo sea directamente ejecutable. Como lenguaje de modelos, todos los aspectos de implementación están fuera de alcance y no pueden expresarse en OCL. Cada expresión OCL es conceptualmente atómica. El estado de los objetos en el sistema no pueden cambiar durante la evaluación. Lenguaje formal OCL es un lenguaje formal donde todos los constructores tienen un significado formal definido. La especificación de OCL es parte de la especificación de UML. OCL no tiene la intención de reemplazar los lenguajes formales existentes. Los lenguajes formales tradicionales se usaban por personas con conocimientos matemáticos, pero dificulta su uso para la mitad de empresas y modeladores de sistemas. OCL ha sido desarrollado para llenar este hueco. Puesto que en un proyecto hay mucha gente involucrada (usuario, expertos, personas que después se deberán encargar de su mantenimiento, etc.) los modelos deben ser entendidos por una amplia y variada audiencia. OCL es fácil de aprender y usar por los desarrolladores sin amplios conocimientos matemáticos. OCL tiene ciertas características que permiten a los desarrolladores adoptarlo a su ritmo y sólo donde lo necesiten. Hace accesibles las especificaciones formales con un trasfondo matemático limitado. Otro aspecto importante es que OCL no es un lenguaje completo en sí mismo. Muchos lenguajes formales mandan (o al menos se supone) que la especificación completa se escriba en el mismo lenguaje. Con OCL, no se necesita, incluso se tiene la posibilidad de escribir las especificaciones completas en OCL. La intención de OCL es la de utilizarlo en combinación con los modelos visuales UML. Muchos aspectos de modelaje pueden expresarse mucho mejor usando diagramas visuales y OCL no intenta reemplazarlos por sus propios mecanismos. Por el contrario, toma la información expresada en los modelos visuales y permite al desarrollador acceder a esta información en las expresiones OCL. OCL es un lenguaje tipado, por lo que cada expresión OCL tiene un tipo. Para ser bien formada, una expresión debe concordar con los tipos de las reglas del 3 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia lenguaje. Por ejemplo, no puede compararse un Integer con un String. Cada clasificador definido en un modelo UML representa un tipo distinto en OCL. Además, OCL incluye un conjunto de tipos adicionales predefinidos. En el apartado siguiente (Álgebra relacional) se clasifica el lenguaje OCL dentro de los lenguajes de consulta. Más tarde, lo que se intentará es dar unas nociones teóricas básicas sobre OCL y sirviéndonos de la ayuda de un diagrama de clases, ofreceremos algunos ejemplos prácticos. A continuación, hablaremos del paquete estándar que cada modelo UML que usa OCL contiene y de la gramática UML. Por último, expondremos algunas conclusiones y aportaremos referencias en las que se puede encontrar información más detallada sobre el tema en cuestión. 2.- Álgebra relacional Los lenguajes de consulta se dividen en dos grandes grupos: Lenguajes algebraicos Estos lenguajes realizan las consultas aplicando operadores especiales a las relaciones. Lenguajes de cálculo de predicados En estos lenguajes las consultas describen un conjunto de tuplas deseado especificando un predicado que las tuplas deben satisfacer. Las consultas en OCL se definen, por una parte, como un conjunto de elementos que satisfacen una expresión restrictiva, y por otra, se pueden aplicar operadores especiales para interactuar con las relaciones. Por tanto, OCL sigue un modelo mixto. 3.- Diagrama de clases de ejemplo El siguiente diagrama se usa como base para ejemplos posteriores. Bank AccountNumber:Int eger 0..1 4 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia 5 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia 3.1. Conexión con el metamodelo UML 3.1.1. Self Cada expresión OCL se escribe en el contexto de una instancia de un tipo específico. En una expresión OCL, la palabra reservada self se usa para referirse a la instancia contextual. Por ejemplo, si el contexto es Company, entonces self se refiere a una instancia de Company. 3.1.2. Especificar el contexto UML El contexto de una expresión OCL en un modelo UML puede especificarse mediante una declaración de pseudo-contexto al inicio de una expresión OCL. Si la restricción se muestra en un diagrama, con el estereotipo correspondiente y las líneas de guiones largos para conectarlos con su elemento contextual, no hay necesidad de una declaración de contexto explícita en el test de las restricciones. La declaración de contexto es opcional. 3.1.3. Invariantes Una expresión OCL puede ser parte de un invariante el cual es una restricción estereotipada como <<invariante>>. Una expresión OCL es un invariante del tipo y debe ser cierta para todas las instancias de ese tipo en cualquier momento. (Hay que destacar que todas las expresiones OCL que expresan invariantes son de tipo Boolean). Por ejemplo, si en el contexto de la compañía del diagrama anterior, la siguiente expresión especificara un invariante que el número de empleado debiera exceder siempre a los 50: context Company inv enoughEmployees: Self.numberofEmployees > 50 donde self es una instancia del tipo Company. (Puede verse a self como el objeto desde donde se empieza la expresión). Este invariante permanece para todas las instancias de tipo Company. La etiqueta inv: declara la restricción para que sea un <<invariante>>. Opcionalmente, el nombre de la restricción puede escribirse tras la palabra clave inv, permitiendo que la restricción pueda ser referenciada mediante el nombre. 6 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia 3.1.4. Pre- y postcondiciones La expresión OCL puede ser parte de una pre- o postcondición, que se corresponden con los estereotipos <<precondicion>> y <<postcondicion>>, respectivamente, de la restricción asociada con una operación o método. La instancia contextual self es entonces una instancia del tipo que pertenece a la operación o método como una característica. La declaración de contexto en OCL utiliza la palabra clave context, seguido del tipo y la declaración de la operación. El estereotipo de restricción se muestra mediante las etiquetas 'pre:' y 'post:' antes de las pre- y postcondiciones reales. context Typename::operationName(param1:Type1, ...):ReturnType pre parameterOk: param1>... post resultOk: result=... Puede usarse la palabra self en la expresión refiriéndose al objeto sobre el que la operación fue llamada. Opcionalmente, el nombre de la pre- o postcondición puede escribirse tras las palabras claves pre o post. En el diagrama ejemplo podemos escribir: context Typename::OperationName(param1:Type1,...):ReturnType post: result = 5000 3.2.- Operadores OCL incluye las siguientes funciones aritméticas y agregadas: Tipo de operandos Real Integer Boolean String Enumeration Operaciones =, +, -, *, /, abs, floor, max, min, <, >, <=, >= =, +, -, *, /, abs, div, mod, max, min =, or, xor, and, not, implies, if-then-else =, size, concat, toUpper, toLower, substring =, <> 3.2.1. La expresión let A veces una subexpresión se usa varias veces en una restricción. La expresión let permite definir una variable que puede usarse en la restricción. context Person inv: let income : Integer =self.job.salary sum in if isUnemployed then income < 100 else 7 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia income >=100 endif 3.2.2. Concordancia de tipos Una expresión OCL en la que los tipos no concuerdan es una expresión invalida. Ésta contiene un tipo de error de concordancia. Un tipo type1 concuerda con un tipo type2 cuando una instancia de type1 puede ser sustituida en cualquier lugar donde se espera una instancia de type2. Las reglas de concordancia de tipos en los diagramas de clases son simples: Cada tipo concuerda con cada uno de sus supertipos. La concordancia de tipos es transitiva: si type1 concuerda con type2, y type2 concuerda con type3, entonces type1 concuerda con type3. Tipo Set(T) Sequence(T) Bag(T) Integer Concuerda con / Es un subtipo de Collection(T) Collection(T) Collection(T) Real 3.2.3. Retipado o Casting Cuando es cierto que el tipo real del objeto es el subtipo, el objeto puede ser retipado usando la operación oclAsType(OclType). Esta operación tiene efecto en el mismo objeto, pero el tipo conocido es el argumento OclType. Cuando se tiene un objeto object de tipo Type1 y Type2 es otro tipo, se puede escribir: Object.oclAsType(Type2) --- Evalua al objeto con el tipo Type2 Un objeto puede ser sólo retipado a uno de sus subtipos; por tanto, en el ejemplo, Type2 debe ser un subtipo de Type1. 3.2.4. Reglas de precedencia El orden de precedencia de las operaciones, de mayor a menor prioridad, en OCL es: @pre punto y operaciones flecha: '.' y '->' operadores unitarios 'not' y menos '-' '*' y '/' '+' y el operador binario '-' 'if-then-else-endif' 8 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia '<','>','<=','>=' '=','<>' 'and','or', y 'xor' 'implies' Los paréntesis '(' y ')' pueden usarse para variar la precedencia. 3.3. Propiedades 3.3.1. Atributos Por ejemplo, la edad de una persona se escribe como: context Person inv: self.age>0 El valor de la subexpresión self.age es el del atributo age en una instancia, en concreto, de Person identificada por self. El tipo de esta subexpresión es el tipo del atributo age. 3.3.2. Operaciones Las operaciones pueden tener parámetros. Por ejemplo, un objeto Person tiene un ingreso expresado como una función de la fecha: context Person::income (d:Date):Integer post: result = age*1000 3.3.3. Combinación de propiedades Las propiedades se pueden combinar para obtener expresiones más complicadas. Una regla importante es que una expresión OCL siempre evalúa a un objeto específico de un tipo en concreto. Tras obtener un resultado, siempre se puede aplicar otra propiedad al resultado para obtener un nuevo valor resultante. Por tanto, cada expresión OCL puede leerse y evaluarse de izquierda a derecha. Por ejemplo, si quisiéramos decir que los casados son mayores de edad: context Person inv: self.wife->notEmpty implies self.wife.age>=18 and self.husband->notEmpty implies self.husband.age>=18 3.3.4. Acceso a las propiedades que sobreescriben supertipos 9 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Las propiedades siempre se redefinen en un tipo, la propiedad de los supertipos puede accederse usando la operación oclAsType(). Siempre que tengamos una clase B como un subtipo de la clase A, y una propiedad p1 tanto de A como de B, podemos escribir: context B inv: self.oclAsType(A).p1 -- accede a la propiedad p1 definida en A self.p1 -- accede a la propiedad p1 definida en B 3.3.5. Propiedades predefinidas en todos los objetos Hay varias propiedades que se aplican a todos los objetos y que están predefinidas en OCL. Estas son: OclIsTypeOf (t : OclType) : Boolean OclIsKingOf (t : OclType) : Boolean OclInState (s : OclState) : Boolean OclisNew : Boolean OclAsType (t : OclType) : instance of OclType El resultado de la operación oclTypeOf es verdad si el tipo de self y t son el mismo. Por ejemplo: context Person inv: self.oclIsTypeOf( Person ) -- es verdad inv: self.oclIsTypeOf( Company ) -- es falso La propiedad oclIsKindOf además determina si t es el tipo directo de uno de los supertipos de un objeto. La operación oclInState devuelve verdad si el objeto está en el estado s. Los valores para s son los nombres de los estados de la máquina de estado s vinculada al clasificador del objeto. Si tenemos un conjunto de estados donde unos están contenidos en otros, los nombres de los estados pueden combinarse usando la notación ::. La operación oclIsNew se evalúa a verdad si, usado en una postcondición, el objeto se crea durante la ejecución de la operación. 3.3.6. Características de las propias clases 10 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Una características predefinida en cada tipo es allInstance, cuyo resultado es el conjunto de todas las instancias del tipo existente en un momento determinado a la hora de evaluar una expresión. Si queremos asegurarnos de que todas las instancias de Person tienen nombres únicos, podríamos escribir: context Person inv: Person.allInstances -> forAll(p1,p2 | p1<>p2 implies p1.name <> p2.name) El uso de allInstances tiene algunos problemas y su uso está desaconsejado en muchos casos. Para los tipos integer, real y string el significado de allInstances está indefinido. Además, la existencia de objetos debe ser considerada en algunos contextos globales, como un sistema o un modelo. Este contexto global debe ser definido, lo que no se hace con OCL. 3.3.7. Colecciones El tipo Collection define un gran número de operaciones predefinidas que permiten al modelador de expresiones OCL manipular colecciones. Las operaciones de colecciones nunca cambian las colecciones originales, sino que guardan el resultado en otra colección. Colección es un supertipo abstracto para todos los tipos de colección en OCL. Cada ocurrencia de un objeto en una colección se llama elemento. Si un objeto aparece por segunda vez en una colección, hay dos elementos. Algunas propiedades se pueden definir con el subtipo, el cual significa que hay una post condición adicional o un valor de retorno especial. La definición de algunas propiedades comunes es diferente para cada subtipo. OCL distingue tres tipos diferentes de colecciones: Set, Sequence y Bag. Set es un conjunto matemático. No contiene elementos duplicados. Bag es como un conjunto, que puede contener duplicados. Sequence es como un Bag en el que los elementos están ordenados. Para definir una colección, los elementos se encierran entre llaves y están separados por comas. El tipo de la colección se escribe antes de las llaves, como por ejemplo: Set {1, 2, 5, 88 } Sequence {'mono', 'nuez'} Bag{1, 3, 4, 3, 5} 3.3.8. Valores previos en las postcondiciones 11 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia El valor de una propiedad en una postcondición es el valor tras completar la operación. Para referirse al valor de la propiedad al comienzo de la operación, se tiene que añadir tras el nombre de la propiedad la palabra clave '@pre': context Person::birthdayHappens() post: age = age@pre + 1 La propiedad age se refiere a la propiedad de la instancia de Person sobre la que se ejecuta la operación. La propiedad age@pre se refiefe al valor de la misma propiedad, pero al inicio de la operación. Si la propiedad tuviera parámetros, el sufijo se añadiría tras el nombre de la propiedad y antes de los parámetros. 3.4. Operaciones sobre colecciones 3.4.1. Operaciones Select y Reject Algunas veces una expresión usa operaciones que devuelven una colección, en la que sólo estamos interesados en un subconjunto en concreto. OCL tiene constructores especiales para especificar una selección de una colección específica (Select y Reject). Select especifica un subconjunto de una colección. El parámetro de la select debe ser una expresión booleana. El resultado es una colección que contiene todos los elementos para los que la expresión booleana se evalúa a cierto. Los dos ejemplos siguientes son idénticos: context Company inv: self.employee -> select (age > 50) -> notEmpty context Company inv: self.employee -> select (p | p.age > 50) -> notEmpty La operación reject es idéntica a la select, pero con la reject podemos obtener un subconjunto de todos los elementos de la colección para los que la expresión se evalúa a falso. 3.4.2. Operación Collect Cuando queremos especificar una colección que se deriva de otra, pero que contiene objetos diferentes de la colección original, podemos usar la operación Collect. La colección resultante es un Bag. Si queremos obtener la fecha de cumpleaños de todos los empleados: Self.employee -> collect (birthDate) Self.employee -> collect (person | person.birthDate) 12 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Self.employee -> collect (person | person.birthDate) Cuando más de un empleado tiene el mismo valor para la fecha de cumpleaños, éste aparecerá más de una vez, por lo que la colección resultante será del mismo tamaño que la original. Si queremos hacer un Set de Bag, usaremos la propiedad asSet de Bag: Self.employee -> collect (birthDate) -> asSet 3.4.3. Operación ForAll Muchas veces se necesita que todos los elementos de una colección cumplan una cierta restricción. La operación forAll permite especificar una expresión booleana que deben cumplir todos los objetos de una colección. Devuelve cierto si todos los elementos de la colección cumplen la restricción y falso en caso contrario. Si queremos saber si todos los nombres de pila de los trabajadores son distintos, podríamos hacerlo de tres formas: self.employee -> forAll (e1, e2 | e1 <> e2 implies e1.forename <> e2.forename) self.employee -> forAll (e1,e2 : Person | e1 <> e2 implies e1.forename <> e2.forename) self.employee -> forAll (e1 | self.employee -> forAll (e2 | e1 <> e2 implies e1.forename <> e2.forename))) 3.4.4. Operación Exists Muchas veces se necesita saber si hay al menos un elemento en una colección que cumple una cierta restricción. Este es el objetivo de la operación exists. Devuelve cierto si se cumple la expresión booleana para algunos de los elementos. Si queremos saber si existe algún empleado que se llame Jack: Self.employee -> exists (forename = 'Jack') Self.employee -> exists (p | p.forename = 'Jack') Self.employee -> exists (p: Person | p.forename = 'Jack') 4.- El paquete estándar OCL Cada modelo UML que usa como lenguaje de restricción OCL contiene un paquete estándar denominado “UML_OCL”. Este paquete es usado por defecto en todos los otros paquetes en el modelo para evaluar expresiones OCL. Este paquete contiene todos los tipos OCL predefinidos y sus características. 13 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia Para extender los tipos predefinidos OCL, un modelador debe definir un paquete separado. El paquete estándar de OCL puede ser importado, y cada tipo OCL puede extenderse con nuevas características. Para especificar que un paquete usó tipos predefinidos OCL de un paquete definido por el usuario en lugar de un paquete estándar, el paquete usado debe definir una dependencia con estereotipo <<Tipo_OCL>> al paquete que define el tipo OCL extendido. Una restricción, en el paquete OCL definido por el usuario, es que como mínimo todos los tipos predefinidos OCL junto con todas sus características deben estar definidos. El paquete de usuario debe ser una extensión correcta del estándar OCL. 5.- Gramática La descripción de gramática usa la sintaxis EBNF , donde ‘I’ significa elección, ‘?’ opcionalidad, y ‘*’ significa cero o más veces, ‘+’ significa una o más veces. En la descripción del nombre, typeName, y string, la sintaxis de los símbolos léxicos se usa el generador de análisis de JavaCC. 6.- Conclusiones OCL no es tan expresivo como el cálculo relacional está incompleto como lenguaje de consulta en el sentido de bases de datos. OCL sólo puede procesar funciones recursivas primitivas y no cualquier función recursiva. En otras palabras, OCL no es equivalente a la máquina de Turing. OCL hace práctica la construcción de modelos más formales. De esta forma es más fácil encontrar los errores en fases más tempranas del proyecto. Fijándolos durante el modelaje es más barato que al final del código. Con el mercado de componentes emergentes, podremos obtener una gran cantidad de componentes desde donde elegirlos. Necesitamos tener disponible un componente para poder seleccionarlo desde su especificación. Una especificación no ambigua con OCL nos permite realizar esta selección. La combinación de UML y OCL mejorará definitivamente el proceso de desarrollo software e incrementará la calidad del software desarrollado. Debido a las ambigüedades, a algunas inconsistencias y a la falta de formalidad de las especificaciones de OCL, algunos autores han sugerido reemplazarlo por otro lenguaje bien formado como el EER. Se espera que nuevas revisiones del UML traigan a la comunidad una nueva versión revisada de OCL o, quizás mejor, una nueva aproximación que facilite la especificación de las propiedades del modelo formalmente. 14 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia 7.- Referencias [1] [2] [3] [4] [5] http://www.software.ibm.com/ad/ocl http://www.boldsoft.com/news/columns/columnJWarmer.htm [More results from www.boldsoft.com] http://www.computer.org/proceedings/tools/0278/02780399abs.htm [More results from www.computer.org] http://www.awl.com/product/0,2627,0201379406,00.html http://www.rational.com/technotes/rose_html/Rose_html/technote_7933.ht ml [6] [7] [8] http://www.cs.ukc.ac.uk/pubs/1998/784/ (computer sciencie) http://www-4.ibm.com/software/ad/standards/ocl-download.html UML Versión 1.3 15 Laboratorio de Sistemas de Información Facultad de Informática Universidad Politécnica de Valencia