Index
Introducció
Història
Companyies al darrera de OCL
On es fa servir el OCL?
Restriccions, constexts i self
Exemple: Un sistema hipotecari
Especificació OCL de les restriccions
Exemple: programes de fidelització
Invariants amb navegació a traves d'extrems d'associació
Invariants que usen navegació desde les classes d'associació
Invariants que usen la navegació a través d'associacions amb multiplicitat múltiple
Index
Navegació en les col·leccions
Els tipus de col·leccions
Operacions de les col·leccions
Característiques de les classes
Propietats predefinides en tots els objectes
Canviant de context
Exemple dels estudiants i les matricules
Navegació de les classes a través de les associacions cícliques
Navegació a través de l'Associació qualificada
Classes i subclasses
Conclusions
4
OCL és un llenguatge formal textual per definir restriccions sobre objectes. (Object Constraint Language)
Llenguatge notacional
Subconjunt de l'UML
Estàndard
S'utilitza en:
model conceptual
model d'operacions
model d'objectius
disseny
navegació de models estructurals.
Introducció
5
Introducció
Per què és necessari un llenguatge formal?
Aconseguir una especificació precisa
Descriure característiques addicionals
Escriure característiques no ambigües
6
Introducció
Per què OCL i no altres llenguatges formals?
No cal una bona formació matemàtica
És un llenguatge formal, fàcil de llegir i escriure
És un llenguatge complet en sí mateix
És un llenguatge tipat, de manera que cada expressió d'OCL té un tipus
7
Introducció
Millor documentació → Constraints afegeixen informació sobre els elements del model i la seva relació amb els models utilitzats en UML. És una forma de documentar un model.
Més precisió → les restriccions OCL tenen una semàntica formal, i, per tant, es poden utilitzar per reduir l'ambigüitat en els models UML.
Comunicació sense malentesos → els models d'UML s'utilitzen per a la comunicació entre els desenvolupadors. L'ús de les restriccions OCL, els modeladors es poden comunicar sense les ambigüitats.
9
Desenvolupat per primera vegada el 1995 amb el nom Ibel per la IBM (International Business Machine) per al modelatge de negoci
IBM el va proposar a OMG per l'anàlisi orientat a objectes i disseny estàndard. Després OCL es va fusionar amb UML 1.1.
OCL va ser utilitzat per definir el UML 1.2.
Història
10
Companyies al darrere de OCL
Microsoft IBM Hewlett-Packard Oracle Sterling Software MCI Systemhouse Entre altres com: Unisys, ICON Computing,
IntelliCorp, i-Logix, ObjecTime, Platinum Technology, Ptech, Taskon, Reich Technologies, Softeam.
11
On es fa servir el OCL?
Per especificar invariants per les clases i tipus Per especificar les pre- i post- condicions dels
diferents mètodes. Com un llenguatge de navegació. Per especificar les restriccions sobre les
operacions. Per testejar els requisits i les especificacions.
12
Restriccions (invariants), contexts i Selfs
A constraint (invariant) és una expressió booleana OCL que és evaluada a cert o a fals.
Cada restricció s'enllaça a un tipus específic (classe, associació de classe, interfície) dintre del model UML
Els objectes de context poden ser denotats amb la paraula clau ‘self’.
El context pot ser especificat com a:
Context <context name> invariant <nom_invariant>? :
<restricció>
13
Exemple: Un sistema hipotecari
La hipoteca d'una casa pertany al propietari de la casa, el qual és el prestatari de la hipoteca.
La data d'inici d'una hipoteca ha de ser abans de la seva data de finalització.
14
Especificació OCL de les restriccions:
1. context Mortgage context Mortgage invariant: self.security.owner = self.borrower invariant: security.owner =
borrower
2. context Mortgage context Mortgage invariant: self.startDate < self.endDate invariant: startDate <
endDate
15
Altres exemples sobre les restriccions
Tots els jugadors han de ser majors d'edat:
El nombre de persones en cada habitació no és superior al nombre de llits en aquesta habitació.
context Player invariant:self.age >=18
context Room invariant:guests -> size <= numberOfBeds
Room room guests Guest
numberOfBeds: Integer*
Playerage: Integer
16
Exemple: programes de fidelització
Problema: - Una empresa s'encarrega dels programes de fidelitat (class
LoyaltyProgram) per les empreses (class ProgramPartner) que ofereixen als seus clients diversos tipus de bons.
- Els extres es donen en forma de punts de bonificació.
- Les empreses ofereixen serveis (class Service).
- Cada client pot entrar al programa de fidelitat mitjançant l'obtenció d'un carnet de soci (class CustomerCard).
- Els objectes de class Customer representen a les persones.
17
Exemple: programes de fidelització - Una CustomerCard o (targeta membre) pertany a una persona, però
es pot fer servir per a tota una família o empresa.
- Els programes de fidelitat permeten als clients estalviar punts de bonificació, amb els quals el client es pot "comprar" serveis del programa dels socis.
- Un compte de fidelitat(LoyaltyAccount) s'emet quan un client pertany
a un programa de fidelitat (class Membership).
- Les transaccions (class Transaction) en els comptes de fidelitat impliquen que hi hagin diferents serveis prestats pels socis del programa de fidelitat i es realitzen amb una única targeta. Hi ha dos tipus de transaccions: Earning (sumen punts) i burning (resten punts).
- La durada dels membres determina diferents nivells dels serveis (class serviceLevel).
18
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
card0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
19
Using OCL in Class Diagrams
LoyaltyAccount
points: Integer
earn(i: Integer)
burn(i: Integer)
isEmpty(): Boolean
{ points >= 0 }
<<postcondition>>points = points@pre - i
class invariant
postcondition for burn operation<<postcondition>>result = (points=0)
<<precondition>>points >= i and i >= 0
precondition for burn operation
<<postcondition>>points = points@pre + i
<<precondition>>i >= 0
20
Invariants en els atributs
Invariants en els atributs:
context Customerinvariant agerestriction: age >= 18
context CustomerCardinvariant correctDates: validFrom.isBefore(goodThru)
El tipus de validFrom i goodThru és Data.isBefore(Date):Boolean és una operació amb Data.
La classe on s'ha de posar la invariant és el context d'aquesta invariant.
21
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
cards0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
22
Invariants amb navegació a traves d'extrems d'associació – Roles (1)
- Navegació sobre les associacions s'usa per referir-se als objectes associats, a partir de l'objecte de context:
context CustomerCardinvariant: owner.age >= 18
owner instància de Customer. owner.age de tipus Integer.
- Nota: CustomerCard no és el context “correcte” per a aquesta restricció, necessitem el Customer.
- Per això fem servir el nom que hi ha a l'extrem de Customer de l'associació entre CustomerCard i Customer, que és owner.
- Preferència: Sempre donar els noms de la funció (age).
23
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
cards0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
24
Invariants amb navegació a traves d'extrems d'associació – Roles (2)
context CustomerCardinvariant printedName:printedName = owner.title.concat(' ').concat(owner.name)
printedName un String. owner instància de Customer. owner.title un String. owner.name un String. String és un tipus reconegut en OCL. concat és una operació de String, amb la
signatura: concat(String): String.
25
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
cards0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
26
Invariants que usen navegació desde les classes d'associació
La navegació desde una classe d'associació cap a l'altra pot utilitzar el nom de la classe d'associació, o el nom de la funció.
L'objecte de context és la instància de classe d'associació - una tupla.
“El propietari de la targeta de membres ha de ser el client en l'afiliació”:context Membershipinvariant correctCard: card.owner = customer
27
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
cards0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
28
Invariants que usen la navegació a través de classes d'associació
La navegació d'una classe a través d'una classe d'associació, utilitza el nom de classe d'associació per obtenir totes les tuples de l'objecte:
“Les targetes de soci d'un client són només les targetes dels clients”
context Customer
invariant correctCard:
cards->includesAll(Membership.card)
La següent restricció és exactament la mateixa que l'anterior:
“El propietari de la targeta de membres ha de ser el client membre”
context Membership
invariant correctCard: card.owner = customer
La segona restricció és millor!
29
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
cards0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
30
Invariants que usen la navegació a través d'associacions amb multiplicitat múltiple
Navegació a través d'associacions amb multiplicitat més gran que 1 produeix un tipus de col·lecció.
Operacions sobre col·leccions:
- s'accedeix mitjançant una fletxa → , seguit pel nom d'operació.
“Una targeta de client (CustomerCard) pertany només a un membre que és el propietari (owner)”
context CustomerCard
invariant correctCard:
owner.Membership->includes(membership)
owner una instància de Customer.
owner.Membership un set d'instàncies de Membership.
membership una instància de Membership.
includes és una operació dels tipus OCL Collection.
31
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
cards0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
32
Navegació en les col·leccions
context Customeraccount produeix un conjunt d'Accounts
context Customer
account.transaction produeix un bag de transactions
Si volem utilitzar això com un conjunt, hem de fer el següent:
account.transaction -> asSet
Customer Account Transaction0..* 0..*
33
Navegació en les col·leccions
“Els socis d'un programa de fidelitat tenen almenys un servei prestat”
context LoyaltyProgram
invariant minServices:
partners.deliveredServices->size() >= 1
“El nombre de programes d'un client és igual al nombre de targetes vàlides que té”
context Customer
invariant sizesAgree:
programs->size() = cards->select(valid=true)->size()
34
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
cards0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
account
35
Navegació en les col·leccions
“Quan un programa de fidelitat (LoyaltyProgram) no ofereix la possibilitat de sumar o restar punts (pointEarned i pointsBurned), els membres del programa no tenen comptes de fidelitat.
És a dir, la taula comptes de fidelitat estarà buida.”
context LoyaltyProgram
invariant noAccounts:
partners.deliveredServices->
forAll(pointsEarned = 0 and pointsBurned = 0)
implies Membership.account->isEmpty()
36
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
programs
owner
cards0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
account
37
Els tipus de col·leccions
Collection és un tipus predefinit
» Hi han operacions definides per les col·leccions
» Mai canvia l'original
Tres tipus diferents
» Set (no hi han duplicats)
» Bag (poden haver duplicats)
» Sequences (una Bag ordenada)
Una expressió OCL afirma un fet sobre tots els objectes de la col·lecció, o estableix un fet sobre la pròpia col·lecció (p.e.: la mida de la col·lecció)
Sintaxi: collection → operació
OCL 38
Operacions de les col·leccions
<collection> iterate(OclExpression)
isEmpty : Boolean
notEmpty : Boolean
size : Integer
συµ : Integer
count(Object) : Integer
forAll(OclExpression) : Boolean
select(OclExpression) : Collection
reject(OclExpression) : Collection
exist(OclExpression) : Boolean
OCL 39
Operacions de les Col·leccions
Exemples:
context Company invariant:
self.employee select (age > 50) notEmpty
self.employee reject (p | p.age <= 50) notEmpty
self.employee forAll (e1, e2 | e1 <> e2 implies e1.forename <> e2.forename)
self.employee exists (p: Person | p.forename = 'Jack')
OCL 40
Operacions de les Col·leccions
<Set> union(Set) : Set
intersection(Set) : Set
count(Object) : Integer
<Bag> intersection(Bag) : Bag
count(Object) : Integer
equal(bag) : Boolean
<Sequence> count(Object) : Integer
at(Integer) : T
first : Integer
41
Característiques de les classes
allInstance es un mètode de les classes que retorna el conjunt de totes les instancies d'aquella classe a l'hora d'avaluar
context Person invariant:
Person.allInstances forAll(p1,p2 | p1<>p2 implies p1.dni <> p2.dni)
42
Propietats predefinides en tots els objectes
OclIsTypeOf (t : OclType) : Boolean
OclIsKingOf (t : OclType) : Boolean
OclInState (s : OclState) : Boolean
OclisNew : Boolean
OclAsType (t : OclType) : instance of OclType
context Person invariant:
self.oclIsTypeOf( Person ) -- cert
self.oclIsTypeOf( Company ) -- fals
OCL 43
Canviant de context
Customer
showName:Stringpoint: Integer
1..*owner card
CustomerCardname:Stringtitle: Stringgolduser: Boolean
age( ):Integerearn(p:Integer)
context CustomerCardinvariant: showName = owner.title.concat(owner.name)
context Customercard forAll (showName = owner.title.concat(owner.name) )
Canvi de context!
OCL 44
Exemple dels estudiants i les matricules
matriculat
matriculatsEstudiant Assignatura
Valoració
Examen Treball
0..*1..*
1..*
1..*
0..*
per l'assignatura
puntua
repValoracio
rebuda per
nom: String codi: Stringcrèdits: Integer
pes: Integer
hores: Integer data: String
OCL 45
Exemple dels estudiants i les matricules
Les assignatures es poden agafar si i només si tenen més de set estudiants matriculats
Les avaluacions per assignatura han de ser 100%
Els estudiants s'han d'inscriure en 120 crèdits cada any
Els estudiants han de prendre un mínim de 90 crèdits de les assignatures troncals (T) cada any
Tots les assignatures han de tenir com a mínim un valor d'avaluació de més de 50%
Els estudiants només poden tenir les avaluacions de les assignatures que s'estan duent a treball
OCL 46
Exemple dels estudiants i les matricules
Les assignatures es poden agafar si i només si tenen més de set estudiants matriculats
− quan aquesta limitació ha de ser imposada?
context Assignatura
invariant: matriculatssize > 7
OCL 47
Exemple dels estudiants i les matricules
Les avaluacions per assignatura han de ser 100%
context Assignatura
invariant:
puntua.pessum( ) = 100
OCL 48
Exemple dels estudiants i les matricules
Els estudiants s'han d'inscriure en 120 crèdits cada any
context Estudiant
invariant: matriculat.crèditssum( ) = 120
OCL 49
Exemple dels estudiants i les matricules
Els estudiants han de prendre un mínim de 90 crèdits de les assignatures troncals (T) cada any
context Estudiant invariant: matriculat select(codi.substring(1,2) = ‘T’).crèdit → sum( ) >= 90
OCL 50
Exemple dels estudiants i les matricules
Tots les assignatures han de tenir com a mínim un valor d'avaluació de més de 50%
context Assignatures invariant:
puntuaexists(pes > 50)
OCL 51
Exemple dels estudiants i les matricules
Els estudiants només poden tenir les avaluacions de les assignatures que s'estan duent a treball
context Estudiant invariant: matriculatincludesAll(repValoracio.perAssignatura)
OCL 52
Navegació de les classes a través de les associacions cícliques
Navegar a traves de les associacions cícliques requereixen funcions per distingir els punts d'associacions:
object.associationClass[role]La puntuació acumulada d'un treballador és positiva:
context Persona invariant: rankingTreballador[cap].scoresum()>0
Cada cap ha de puntuar almenys un 10:
context Persona invariant: rankingTreballador[empleat]exists(puntuacio = 10)
Persona
rankingTreballador
*
*
cap
puntuació
empleat
OCL 53
Navegació a través de l'Associació qualificada
Per navegar a través de les associacions qualificades es necessita un index
object.navigation[qualifierValue, ...] Si n'hi han multiples qualificadors s'han de
separar per comes
Exemplecontext LoyaltyProgram
serviceLevel[1].name = ‘basic’
context LoyaltyProgram
serviceLevelexists(name = ‘basic’)
LoyaltyProgram
enroll(c:Customer)
ServiceLevel
name: String
0..1
levelNumber: Integer
54
LoyaltyProgram
enroll(c:Customer)
Service
condition: BooleanpointsEarned: IntegerpointsBurned: Integerdescription: String
0..*deliveredServices
Membership
LoyaltyAccount
points: Integer
earn(i: Integer)burn(i: Integer)isEmpty(): Boolean
Customer
name: Stringtitle:StringisMale: BooleandateOfBirth: Date
CustomerCard
valid: BooleanvalidFrom: DategoodThru: Datecolor: enum{silver, gold}printedName: String
0..*0..*
age(): Integer
program
owner
card0..*card
ProgramPartner(Empresa)
numberOfCustomers: Integer
partners
1..*
1..*
ServiceLevel
name: String
availableServices
0..*
{ordered} 1..*0..1
0..*
actualLevel
Transaction
points: Integerdate:Date
program(): LoyaltyProgram
0..*transactions
card
transactions0..*transactions
0..*
Burning Earning
Date
$now: Date
isBefore(t:Date): BooleanisAfter(t:Date): Boolean=(t:Date): Boolean
1
1
1
1
1
1
1
1
1
level
generatedBy
partner 1
account
OCL 55
Classes i subclasses
Considerem la següent regla:
context LoyaltyPrograminvariant: partners.deliveredServices.transaction
.pointssum() < 10000
Si la restricció només s'aplica a la subclasse Burning, podem utilitzar l'operació oclType:
context LoyaltyPrograminvariant: partners.deliveredServices.transaction
select(oclType = Burning).pointssum() < 10000
OCL 56
Classes i subclasses
“L'objectiu de la dependència no és la font
context Dependencyinvariant: self.source <> self
És ambigu
- La dependència és tant
un ModelElement com
una classe d'associació
context Dependencyinvariant: self.oclAsType(Dependency).source <> selfinvariant:
self.oclAsType(ModelElement).source isEmpty()
ModelElement
Note Dependency
*
*target
source
57
L'objectiu és conèixer un llenguatge de restriccions d'objectes: OCL, que forma part de l'UML.
És un conjunt de notacions precises de llenguatge textual per expressar restriccions que no poden ser expressades en l'UML.
La semàntica d'OCL s'aplica sobre la base de la construcció d'eines CASE que suporten comprovacions d'integritat sobre tots els models d'UML.
La semàntica d'OCL proporciona una semàntica per a les classes, associacions, atributs i els estats.
Conclusions
58
Amb els diagrames de l'UML no n'hi ha prou!
Volem un llenguatge que ens ajudi amb les especificacions.
Busquem una ampliació enlloc d'un llenguatge completament nou amb la capacitat d'especificació completa.
OCL – omple el buit que falta.
Especifica restriccions
No és l'únic, però és l'únic que està estandarditzat i forma part de l'UML.
Sintaxis intuitiva – com OO llenguatges.
No és un llengutge de programació: No hi ha control de fluxe No hi ha efectes col·laterals.
Conclusions
59
Referències
http://www.omg.org/spec/OCL/2.2/
OCL de Juan Casas, Universidad Politecnica de Valencia
http://www-2.dc.uba.ar/materias/isoft1/teoricas_2009_1/05b-ModeloConceptual_OCL_BN.pdf
http://www.itlalaguna.edu.mx/Academico/Carreras/sistemas/Analisis%20y%20dise%C3%B1o%20orientado%20a%20objetos/OCL.pdf
60
Referències
Exemples amb OCL
https://github.com/eclipse/ocl
Plugin eclipse
http://www.eclipse.org/modeling/mdt/?project=ocl
Linux
http://maude.cs.uiuc.edu/download/
http://maude.sip.ucm.es/itp/ocl/
http://maude.sip.ucm.es/itp/ocl/quick-tutorial.html