BREEAM ES Urbanismo como herramienta para un planeamiento sostenible - Miguel...
OCL en Arquitecturas dirigidas por Modelos
1. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Métodos Avanzados de Desarrollo de Software
Asignatura Optativa de 4º Año
Grado en Informática
Departamento de Sistemas Informáticos
Universidad de Castilla-La Mancha
Métodos avanzados de
desarrollo de software
Tema IV: Object Constraint Language (OCL).
Conceptos básicos orientados a MDA
2. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Índice
• Introducción
• Orígenes y motivación
• OCL y OCLInEcore
• Valores básicos y tipos
• Contexto y Self
• Acceso a Propiedades y
Operaciones
• If then else endif
• Invariantes, pre y post
condiciones
• Atributos / propiedades
derivadas
• Valores iniciales
• Definición de
propiedades y
operaciones
• Colecciones
• Collect, select, reject
• Forall, exists
• Iterate
• Sortedby y Sum
• Sequence, Bag, Set y
OrderedSet
• Expresiones Let
• Tuplas
• Otros usos
3. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Orígenes
• En 1996, la OMG pidió propuestas sobre el Diseño y Análisis
de Objetos
• En 1997, IBM conjuntamente con ObjectTime enviaron una
propuesta que incluía OCL
• OCL fue desarrollado por Jos Warmer como un lenguaje para
el modelado de negocios dentro de IBM
• Es derivado de método Syntropy de Steve Cook y John Daniels
4. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Introducción
• ¿Qué es OCL?
• Es un lenguaje para especificar restricciones sobre objetos en
UML
• Especifica condiciones que deben mantenerse para el sistema
que está siendo modelado
• ¿Por qué?
• UML no está suficientemente refinado para describir todos los
aspectos relevantes de una especificación
• El lenguaje natural lleva a ambigüedades…
• Los lenguajes formales son «muy matemáticos» => no son fáciles
de usar
• Por lo tanto, tenemos OCL para rellenar la brecha
5. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Especificación de OCL
• OCL es un lenguaje puro de especificación; por lo tanto una
expresión en OCL no tiene efectos laterales (secundarios).
Cuando se evalúa una expresión en OCL, simplemente retorna
un valor, no puede cambiar nada del modelo.
• Esto significa que el estado del sistema nunca cambia por
culpa de una evaluación de una expresión OCL, aunque una
expresión OCL puede usarse para especificar un cambio de
estado (por ej., en una post condición)
• OCL no es un lenguaje de programación; no es posible escribir
una programa lógico o controlar el flujo de la información
con OCL
6. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
¿Cómo podemos usar OCL?
• Forma de especificación de invariantes sobre clases y tipos
• Describir pre y post condiciones en Operaciones y Métodos
• Lenguaje de consultas
• Establecer invariantes de tipos sobre Estereotipos
• Describir Guardas
• Especificar (conjuntos) de objetivos para mensajes y acciones
• Especificar restricciones sobre las operaciones
• Especificar reglas de derivación para atributos en cualquier
expresión sobre un modelo UML
7. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
OCL y OCLInEcore
• OCL es un lenguaje estándar cuya especificación la define la
OMG
• Por lo tanto, tiene una sintaxis y semántica determinada.
• Por otro lado, desde una perspectiva práctica, la definición de
modelos se definen en ECORE (que es una dialecto de MOF)
• Para poder escribir restricciones en ECORE se utiliza el
lenguaje OCLInEcore
8. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
OCL
• Las expresiones OCL utilizan 2 conceptos fundamentales:
• self (self)
• Hace referencia a una instancia definida por el contexto
• context (context)
• Hace referencia a un elemento del modelo en el cual está definida la
expresión (por ej. una clase, una propiedad, una operación, etc.)
• OCL permite expresar
• Invariantes
• Pre-condiciones
• Post-condiciones
• Consultas
9. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Valores básicos
Tipo (OCL) Valores
Boolean true, false
Integer 1, -5, 2, 34, 26534,…
Real 1.5, 3.14, …
String ‘To be or not to be’,…
Tipo Operaciones
Integer *,+,-,/, =, abs()
Real *,+,-,/, =, floor()
Boolean and, or, xor, not, implies, if-then-else-endif
String concat(), size(), substring(), >, <, =
10. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Más sobre tipos
Tipo Subtipo de Condición Descripción
Set(T1) Collection(T2) Si T1 es compatible con T2 Sin orden ni repetidos
Sequece(T1) Collection(T2) Si T1 es compatible con T2 Ordenado con repetidos
Bag(T1) Collection(T2) Si T1 es compatible con T2 Sin orden con repetidos
OrderedSet(T1) Collection(T2) Si T1 es compatible con T2 Ordenado sin repetidos
Integer Collection(T2) Si T1 es compatible con T2
Expresión OCL Válido Explicación
1 + 2 * 34 si
1 + ‘motorcycle’ no String no es compatible con Integer
23 * false no Boolean no es compatible con Integer
12 +13.5 si
Válido Explicación
Casting object.oclAsType(Type2) Evalúa object con el tipo Type2
Operador Infijo A + B A.+(B)
Comentarios -- -- Comentario
11. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
El Contexto y Self Toda expresión OCL tiene un contexto
Si el contexto está
asociado a Propiedad
multi-valuada (por ej.
clientes, ventas,
productos, ítems, etc.)
self se refiere a la
colección apuntada por
la relación
Si el contexto está
asociado a una una
Propiedad simple (por ej.
destinatario, libreria,
producto, etc.) self se
refiere a la instancia del
objeto apuntados.
Si el contexto esta
asociado a una Clase (por
ej. Cliente, Factura, etc.)
self se asocia a cada una
de las instancias de la
clase.
12. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
self.libreria
Acceso a propiedades
self.ventas
Acceso a Propiedades y Operaciones
self.nombre
contexto
referencia
Acceso a atributos
self.librosFaltantes()
Acceso a operaciones
self.libreria.librosFaltantes()
Acceso a otros contextos
RECORDAR: self hace referencia al contexto
self.libreria.nombre
13. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
El if then else endif
• En OCL todo es una función
• Por lo tanto, el if es una función
• <expresión boolean> define una expresión que devuelve un
boolean
• <expresión if true> define la expresión que se
evalúa/devuelve si <expresión boolean> es true
• <expresión if false> define la expresión que se
evalúa/devuelve si <expresión boolean> es false
if (self.stock < self.stockMin)
then true
else false
endif
if (<expresión boolean>)
then <expresión if true>
else <expresión if false>
endif
14. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Propiedades definidas en todos los
objetos
• Hay muchas propiedades definidas en todos los objetos
• oclIsTypeOf (t : OclType) : Boolean
• oclIsKindOf (t : OclType) : Boolean
• oclInState (s : OclState) : Boolean
• oclIsNew () : Boolean
• oclAsType (t : OclType) : instance of
OclType
• Ejemplo
context Libro
inv: self.oclIsTypeOf( Libro ) -- is true
inv: self.oclIsKindOf( Libro ) -- is true
inv: self.oclIsTypeOf( Producto ) -- is false
inv: self.oclIsKindOf( Producto ) -- is true
inv: self.oclIsTypeOf( Libreria ) -- is false
inv: self.oclIsKindOf( Libreria ) -- is false
15. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Invariantes
• Un invariante es una condición que siempre se cumple para el
contexto de la instancia de la clase en el que está definida
• El contexto de un invariante asociado a una Clase indica que la
condición en OCL se debe cumplir para todas las instancias de esa
clase
• La sintáis es:
Donde:
• <variable contexto> define la forma que se tiene para referirse al
contexto desde la expresión
• <contexto> define el tipo al cuál está asociado el contexto (ej.
clase)
• <nombre invariante> identifica al invariante
• <expresión OCL> define la condición que debe cumplirse
context <variable contexto> : <contexto>
inv <nombre invariante> : <expresión OCL>
16. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Ejemplo Invariante
• Un invariante en OCL es una expresión es una restricción
estereotipada como un «invariant»
• Por ejemplo: Especifiquemos que el atributo cantidad de una
Item de una Factura debe ser mayor que 0
• Existen varias formas de escribir el invariante:
context i : Item inv ItemCantidadMAQ0: i.cantidad > 0 Contexto explícito
context Item inv ItemCantidadMAQ0: self.cantidad > 0 Contexto anónimo
Contexto implícitoinv ItemCantidadMAQ0: self.cantidad > 0
17. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Pre/Post Condiciones
• Una precondición define una condición que debe cumplirse antes de ejecutar una
operación
• Un postcondición es una condición que debe cumplirse después de haberse ejecutado una
operación
• Como el contexto define la entidad donde se ejecuta la expresión de la condición, en este
caso es una operación.
• Dónde
• <tipo> Nombre de la entidad que contiene la operación (por ej. una clase)
• <nombre operación> define el nombre de la operación dentro del tipo
• <param> define la variable para hacer referencia al parámetro dentro de la expresión
• <tipo param> define el tipo del parámetro
• <tipo retorno> define el tipo del valor de retorno de la operación
• <expresión precondición> define la expresión precondición (pueden referenciarse
los parámetros)
• <expresión postcondición> define la expresión de la postcondición (pueden
referenciarse: los parámetros, los valores anteriores a la ejecución de la operación agregando
el postfijo @pre y al valor de retorno con la variable result
context <tipo> : : <nombre operación> (<param1> : <tipo param>, ... )
: <tipo retorno>
pre <nombre pre> : <expression precondición>
post <nombre post> : <expression postcondición>
18. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Pre/Post condiciones
Ejemplo OCL
• Supongamos que queremos establecer pre y post condiciones en la
operación incStock(cant:Integer) definada en la clase
Producto que tiene por objeto incrementar la variable stock con
la cantidad establecida en el parámetro cant.
• La precondición establece que cant debe ser mayor que 0
• La post-condición establece que el valor de stock debe ser el
valor de esta variable antes de ser ejecutada la operación más el
valor de cant.
context Producto :: incStock (cant : Integer) : void
pre CantidadValida : cant > 0
post StockValido : self.stock@pre + cant = self.stock
Pre / Post nombradas
context Producto :: incStock (cant : Integer) : void
pre : cant > 0
post : self.stock@pre + cant = self.stock
Pre / Post anónimas
19. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Propiedades derivadas
• Una propiedad derivada es un propiedad cuyo valor se calcula a
partir de una expresión definida en función de otros valores
• El contexto, en este caso es la propiedad (asociación o atributo) que
se quiere definir
• Dónde:
• <tipo> Nombre de la entidad que contiene la operación (por ej. una
clase)
• <nombre/rol propiedad> define el nombre de la propiedad dentro
del tipo
• <tipo propiedad> define el tipo del valor de la propiedad
• <expresión calculo> define la expresión precondición (pueden
referenciarse los parámetros)
context <tipo> :: <nombre/rol propiedad> : <tipo propiedad>
derive : <expression cálculo>
20. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Propiedades / Atributos derivados
Ejemplo OCL
• Supongamos que queremos especificar el valor de la
propiedad precio falta de la clase Libro
context Libro:: falta : Boolean
derive: if (self.stock < self.stockMin)
then true
else false
endif
21. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones en OCL
• OCL NO es un lenguaje operacional, sino de especificación
• Sin embargo, además de condiciones (devolver un boolean), podemos
especificar consultas (devolver objetos)
• El contexto de las consultas son las operaciones
• Dónde
• <tipo> Nombre de la entidad que contiene la operación (por ej. una clase)
• <nombre operación> define el nombre de la operación dentro del tipo
• <param> define la variable para hacer referencia al parámetro dentro de la
expresión
• <tipo param> define el tipo del parámetro
• <tipo retorno> define el tipo del valor de retorno de la operación
• <expresión precondición> define la expresión precondición (pueden
referenciarse los parámetros)
context <tipo> :: <nombre operación> (<param> : <tipo param>, ... )
: <tipo retorno>
body : <expresión consulta>
22. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones en OCL
Ejemplo
• Supongamos que queremos especificar la operación
productosFaltantes() : Sequence(Producto)
en la clase Libreria
context Producto :: hayStock(cant:Integer) : Boolean
body : self.stock => cant
23. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Valor inicial de una propiedad
• Una expresión OCL puede ser utilizada para el valor inicial de una
propiedad.
• El contexto, en este caso es la propiedad (asociación o atributo) que se
quiere definir
• Dónde
• <tipo> Nombre de la entidad que contiene la operación (por ej. una clase)
• <nombre/rol propiedad> define el nombre de la operación dentro del tipo
• <tipo propiedad> define el tipo del valor de la propiedad
• <expresión calculo> define la expresión precondición (pueden
referenciarse los parámetros)
context Libreria :: nombre : String
init: ‘DefaultName’
context <tipo> : : <nombre/rol propiedad> : <tipo propiedad>
init: <expression cálculo>
24. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Definición de operaciones y
atributos
• Para poder reusar variables/operaciones en múltiples expresiones
OCL se puede usar el estereotipo «definition».
• Por ejemplo:
-- Atributo con valor por omisión
-- Atributo derivado
-- Operación (notar los ( ) )
context Libreria
def : acronimo: String = ‘LMADS’
context Item
def : totalIva : Integer = self.precio * self.cantidad
context Producto
def : hayEnStock(cant : Integer) : Boolean
= self.stock > cant
25. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Colecciones
• Literales
• Conjuntos
• Set { 1 , 2 , 5 , 88 }
• Set { 'apple,' 'orange,' 'strawberry' }
• Secuencias
• Sequence { 1, 3, 45, 2, 3 }
• Sequence { 'ape,' 'nut' }
• Sequence { 1..(6+4)} -- 1,2,3,4,5,6,7,8,9,10
• Bolsas
• Bag {1, 3, 4, 3, 5 }
• Operaciones
• collection1->union(collection2)
26. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones en Collection
• Uso
• Operaciones
• size(): número de elementos de self
• includes(o: oclAny): devuelve true si o está en self
• excludes(o: oclAny): devuelve true si o no está en self
• count (o: oclAny): devuelve la cantidad de veces que o ocurren en self
• includesAll(c:Collection): devuelve true si todos los objetos de c están en self
• excludesAll(c:Collection): devuelve true si ninguno de los objetos de c están en
self
• isEmpty(): devuelve true si la colección está vacía
• notEmpty(): devuelve true si la colección no está vacía
• sum(): devuelve el valor que representa la suma de todos los elementos en self.
Los elementos deben soportar (+)
• asBag(): devuelve un Bag con los elementos de self
• asSequence(): devuelve una Sequence con los elementos de self
• asSet(): devuelve un Set con los elementos de self
self->operation_name(parameters)
27. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones de Sequence
• union(c:Collection): devuelve una secuencia con los elementos de self seguida
de los de c
• flatten(): devuelve una secuencia con que contiene los hijos de las colecciones
contenidas en self
• append(o:oclAny): devuelve una copia de self con el elemento o al final
• prepend(o:oclAny): devuelve una copia de self con el elemento o al principio
• insertAt(n:Integer, o:oclAny): devuelve una copia de self con el elemento o en la
posición n
• subSequence(lower:Integer, upper:Integer): devuelve la secuencia de elementos
de self comprendida entre lower y upper
• at(n:Integer): devuelve el elemento en n de self
• indexOf(o:oclAny): devuelve el primer índice de o en self
• first(): devuelve el primer elemento de self
• last(): devuelve el último elemento de self
• including(o:oclAny): devuelve una copia de self con el elemento o al final
• excluding(o:oclAny): devuelve una copia de self con todas las ocurrencias de o en
self removidas
28. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones de Set
• union(c:Collection): devuelve un Set compuesto con los y los de c sin
duplicados
• intersection(c:Collection): devuelve un Set con los elementos que
aparecen en self y c
• - (s:Set): devuelve un Set compuesto de los elementos de self que no
están en s
• including(o:oclAny): devuelve una copia de self con el elemento o
• excluding(o:oclAny): devuelve una copia de self sin el elemento o
• symetricDifference(s:Set): devuelve un Set compuesto por los
elementos que están en self o s pero no en ambos
• flatten() no está definido
29. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones de Bag
• union(c:Collection): devuelve un Set compuesto con los y los
de c sin duplicados
• intersection(c:Collection): devuelve un Set con los elementos
que aparecen en self y c
• including(o:oclAny): devuelve una copia de self con el
elemento o
• excluding(o:oclAny): devuelve una copia de self sin el
elemento o
• flatten(): devuelve una secuencia con que contiene los hijos de
las colecciones contenidas en self
30. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones en OrderedSet
• append(o:oclAny): devuelve una copia de self con el elemento o al final, si no está
• prepend(o:oclAny): devuelve una copia de self con el elemento o al principio, si no
está
• insertAt(n:Integer, o:oclAny): devuelve una copia de self con el elemento o en la
posición n, si no está
• subOrderedSet(lower:Integer, upper:Integer): devuelve una subSecuencia de self
desde lowes hasta upper
• at(n:Integer): devuelve el elemento en n de self
• indexOf(o:oclAny): devuelve el primer índice de o en self
• first(): devuelve el primer elemento de self
• last(): devuelve el último elemento de self
• union(c:Collection): devuelve un OrderedSet compuesto de los elementos de self
seguidos de los de c con los duplicados removidos
• flatten(): devuelve on OrderedSet que contiene los hijos de las colecciones
contenidas en self
• including (o:oclAny): devuelve una copia de self con el elemento o añadido al final
de la colección
• excluding (o:oclAny): devuelve una copia de self con el elemento o removido
31. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operación collect
• Especifica una colección derivada de otra colección
• NO es una sub-colección
collection->collect( v : Type | expression-with-v )
collection->collect( v | expression-with-v )
collection->collect( expression )
32. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operación collect
Ejemplo
context Libreria::idFiscalClientes() : Sequence(String)
body : self.clientes->collect( c : Cliente| c.idFiscal)
context Libreria::idFiscalClientes() : Sequence(String)
body : self.clientes->collect( c | c.idFiscal)
context Libreria::idFiscalClientes() : Sequence(String)
body : self.clientes->collect(idFiscal)
context Libreria::idFiscalClientes() : Sequence(String)
body : self.clientes.idFiscal
33. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operaciones select y reject
• Es difícil que un modelo no necesite expresar colecciones
• Las operaciones como select() y reject() se utilizan para crear
nuevas colecciones a partir de colecciones existentes
• select
• reject
collection->reject( v : Type | boolean-expression-with-v )
collection->reject( v | boolean-expression-with-v )
collection->reject( boolean-expression )
collection->select( v : Type | boolean-expression-with-v )
collection->select( v | boolean-expression-with-v )
collection->select( boolean-expression )
34. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Ejemplos de operaciones
select y reject
• Ejemplo con select()
• Devuelve los productos faltantes
• Ejemplo con reject()
• Devuelve los productos faltantes
context Libreria :: productosFaltantes() : Set(Producto)
body: self.productos->select(falta)
context Libreria :: productosFaltantes() : Set(Producto)
body: self.productos->reject(not enFalta)
35. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operación ForAll
• Permite especificar que una condición booleana la satisfacen
todos los elementos de una colección
• Ejemplo: Un producto puede estar como máximo en 1 ítem
por factura
collection->forAll( v : Type | boolean-expression-with-v )
collection->forAll( v | boolean-expression-with-v )
collection->forAll( boolean-expression )
context Factura
inv: self.items -> forAll( i1, i2 : Item | i1 <> i2 implies
i1.producto <> i2.producto)
36. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operación Exists
• Sirve para saber si al menos un elemento de la colección
satisface una condición
• Ejemplo: Todos los ítems de una factura deben tener una
cantidad > 0
collection->exists( v : Type | boolean-expression-with-v )
collection->exists( v | boolean-expression-with-v )
collection->exists( boolean-expression )
context Factura
inv: not self.items->exists(i : Item | i.cantidad = 0)
37. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operación Iterate
• Todas las operaciones que hemos visto pueden escribirse
utilizando esta operación (es más genérica)
• Ejemplo:
• Es equivalente a:
collection->iterate( elem : Type;
acc : Type = <expression> |
expression-with-elem-and-acc )
collection->collect(x : T | x.property)
collection->iterate(x : T; acc : T2 = Bag{} |
acc->including(x.property))
38. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Iterate - Ejemplo
• Ejemplo: Obtener mejor venta
context Libreria :: mejorVenta(): Factura
body : self.ventas->iterate(fv:Factura; mejor:Factura =
self.ventas->first() |
if (fv.total > mejor.total) then fv else mejor endif)
39. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operación SortedBy
• El objetivo de esta operación es ordenar una colección de acuerdo
con un criterio
• Para poder comparar, lo ideal es utilizar expresiones que devuelvan
tipos básicos String o Int.
• Para invertir el orden
• Ejemplo: Ordenar las ventas de mayor a menor
collection->sortedBy(x : T | x.property)
collection->sortedBy(x : T | -x.property)
context Libreria :: ventasPorTotalAsc() : OrderedSet(Factura)
body : self.ventas->sortedBy(f:Factura | f.total)
40. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Operación Sum
• El objetivo de esta operación es sumar una colección de
números (Integer, Real)
• Ejemplo: Calcular el total de las ventas
collection->sum()
context Libreria :: totalVentas() : Integer
body : self.ventas.total->sum()
41. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Expresiones let
• Permiten definir una sub expresión
• Sólo se calculan cuando se definen, por lo tanto son muy útiles cuando
una expresión se necesita más de una vez
• Let permite definir una o más variables que pueden ser usadas en las
restricciones.
• Dónde
• <nombre variable> define el nombre de la variable dentro del alcance
IN
• <tipo variable> define el tipo de la variable dentro del alcance IN
• <tipo propiedad> define el tipo del valor de la propiedad
• <expresión calculo> define la expresión que calcula el valor de la
variable
• <expresión uso> define la expresión de uso de una variable
let <nombre variable> : <tipo variable> = <expression
calculo> in <expresión uso>;
42. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Expresiones let
Ejemplo OCL
• Por ejemplo, queremos obtener los productos que cuestan
mas que el promedio
context Libreria :: productosMasCarosQueElPromedio :
Sequence(Producto)
body: let promedio : Real =
self.productos.precio->sum() / self.productos->size()
in
self.productos->select(precio > promedio);
43. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Tuplas
• Una tupla es una secuencia ordenada con un número limitado de
objetos heterogéneos
• Muy útiles para colecciones de valores intermedios
• Definición dl tipo de una tupla
• Instanciación de una tupla
• Acceso
• Dónde
• <nombre> define una referencia al valor de la tupla
• <tipo> define el tipo del valor
• <valor> establece el valor de la referencia
Tuple ( <nombre> : <tipo>, ......)
Tuple { <nombre> = <valor>, ......}
<tupla>.<nombre>
44. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Tuplas - Ejemplo
context Libreria:: productoMasVendido():Producto
body: let items : Sequence(Item) =
self.ventas.items->flatten() ,
producto_cantidad : Sequence ( Tuple (p : Producto, c
: Integer)) =
self.productos->collect(p : Producto | Tuple{p = p, c
= items->select(producto = p).cantidad->sum())
in
libro_cantidad->sortedBy(- c)->first().p;
45. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Diagrama de clases (Librería)
46. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
OTROS USOS
47. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
OCL
Ejemplo de máquina de estado
48. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
OCL para especificar guardas
• Una guarda es una condición Booleana que puede o no validar
el disparo de la ocurrencia de un evento.
• Por ejemplo
context ExpressionInOcl
inv: not self.guard.transition.getStateMachine()
.context.oclIsUndefined()
and
self.guard.transition.getStateMachine()
.context.oclIsKindOf(Classifier)
and
self.bodyExpression.type.name = ’Boolean’
49. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
OCL para especificar mensajes
• Para especificar que una comunicación ha ocurrido se utiliza
el operador (^) hasSent.
• Observer design pattern
• Por ejemplo:
context Subject::hasChanged()
post: observer^update(12, 14)
50. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
OCL Estándar Library
• Ver Capítulo 11 de la especificación de OCL 2.0
Especialmente las operaciones
sobre las colecciones
51. Prof. Dr. Ricardo TESORIERO – Departamento de Sistemas Informáticos- Universidad de Castilla-La Mancha
[ricardo.tesoriero@uclm.es]
Referencias
1. OCL 2.0 Wikipedia:
http://es.wikipedia.org/wiki/Lenguaje_de_especificaci%C3%
B3n_OCL2.0
2. Especificación de OCL 2.0 de la OMG
http://www.omg.org/spec/OCL/2.0/