OCL - Object Constraint
Language
Extratos do livro: Object Constraint Language
de Wermer&Kleppe
Modelagem de SI 1
2013/2
Prof. Eber
Object Constraint Language (OCL)
• “Add-on” da Unified Modeling Language (UML)
• Toda expressão OCL usa tipos definidos em um diagrama de
classes da UML.
– uso da OCL implica na aceitação de alguns padrões da UML.
• A constraint is a restriction on one or more values of (partof) an
object-oriented model or system.
• Versão corrente: OCL 2.0
– formalmente definida em Object Constraint Language Specification
(www.omg.org) .
Modelos e restrições
Classes
Atributos
Operações
Papéis
context Flight
inv: passengers->size() <= plane.numberOfSeats
Modelos e Restrições
•
•
•
•
•
R1-Uma pessoa (person)
somente pode obter uma
hipoteca (mortgage) contra
uma casa (house) de sua
propriedade.
R2-A data de inicio de uma
hipoteca deve ser anterior a
sua data final.
R3-Um número de seguro
social deve ser atribuído a
apenas uma pessoa.
R4-Uma nova hipoteca deve
ser concedida somente a
pessoas com rendimento
suficiente para paga-la.
R5-Uma nova hipoteca deve
ser concedida somente se o
valor da revenda da casa for
suficiente para cobrir a
hipoteca.
Modelos e Restrições
•
R1-Uma pessoa (person)
somente pode obter uma
hipoteca (mortgage) contra
uma casa (house) de sua
propriedade.
•
context Mortgage
inv: borrower = security.owner
Modelos e Restrições
•
R2-A data de inicio de uma
hipoteca deve ser anterior a
sua data final.
•
context Mortgage
inv: startDate < endDate
Modelos e Restrições
•
R3-Um número de seguro social
deve ser atribuído a apenas uma
pessoa.
context Person
inv: Person.allInstances() -> isUnique (socSecNr)
Modelos e Restrições
•
R4-Uma nova hipoteca deve ser
concedida somente a pessoas com
rendimento suficiente para paga-la.
context Person::getMortgage(sum : Money, security : House)
pre: self.mortgages->collect(monthlyPayment)->sum()
<=
self.salary * 0.30
Modelos e Restrições
•
R5-Uma nova hipoteca deve ser
concedida somente se o valor da
revenda da casa for suficiente para
cobrir a hipoteca.
context Person::getMortgage(sum : Money, security : House)
pre: security.value >= security.mortgages->collect(principal)->sum()
The Royal&Loyal
Company
The Royal&Loyal
Company
Royal&Loyal (1)
• Modelo conceitual de uma empresa fictícia chamada Royal and
Loyal (R&L).
• R&L opera programas de fidelidade para empresas que oferecem
bônus a seus clientes.
• Os bônus tomam a forma de pontos ou milhas, mas outros tipos de
bonificações são possíveis tais como: tarifas reduzidas, melhor
carro, melhor serviço de viagem etc.
• Qualquer coisa que uma empresa deseje oferecer pode se tornar
um serviço oferecido num programa de fidelidade.
Royal&Loyal (2)
•
A classe central do modelo é LoyaltyProgram. Um sistema que administre
somente um único programa de fidelidade conterá uma única instancia
desta classe. R&L terá muitas.
•
A empresa que oferece a seus clientes a adesão a um programa de
fidelidade é chamada programPartner. Mais de uma empresa pode
participar de um mesmo programa.
•
•
•
Objetos da classe Customer representam as pessoas que entraram em um
loyaltyProgram. customers que participam do programa podem se
beneficiar dos serviços providos por qualquer uma das empresas
participantes.
Todo customer de um programPartner pode entrar num programa de
fidelidade preenchendo um formulário e obtendo um customerCard. Cada
customerCard é atribuído a somente uma pessoa.
Royal&Loyal (3)
• Uso do customercard não é verificado de forma que ele pode ser
usado por toda uma família.
• A maioria dos programas de fidelidade permite que clientes
acumulem points. Cada programPartner decide quando e quantos
points de bônus são ganhos (earned) em cada compra
(transaction).
• Earned points podem ser usados para “comprar'' serviços (services)
específicos de um dos programPartners.
• Para contabilizar os pontos ganhos por cada customer, toda
associação a um programa deve ser associada a uma
loyaltyAccount.
The Royal&Loyal
Company
Valores iniciais e Regras de derivação
• context LoyaltyAccount::points
init: 0
• context CustomerCard::valid
init: true
• context CustomerCard::printedName
derive: owner.title.concat(‘ ‘).concat(owner.name)
• Estas construções NÃO fazem parte do OCL-USE.
• Como vc. faria esta especificação no USE?
The Royal&Loyal
Company
Consultas (queries)
• operação getServices da classe LoyaltyProgram: retorna
todos os serviços oferecidos por todos os partners no
programa
• context LoyaltyProgram
• operations
• getServices(): Set(Service) =
• partners->collect(deliveredServices)->asSet()
• OBS.:
• Partners.deliveredServices é um bag
• Operador ->asSet: converte bag para set
• “parodiando” em SQL:
• getServices()  select distinct (deliveredServices) from partners
Consulta parametrizada
operação getServices da classe LoyaltyProgram:
retorna os serviços oferecidos por
um partner no programa
context LoyaltyProgram
operations
getServices(pp: ProgramPartner) : Set(Service)=
if partners->includes(pp) then pp.deliveredServices
else Set{}
endif.
Atributos derivados
• atributo derivado turnover de LoyaltyAccount:
soma dos atributos amount das transações da
conta.
• USE não tem esta construção
• Deve ser especificado no USE como uma
função;
context LoyaltyAccount
def: turnover : Real = transactions.amount->sum()
USE:
context LoyaltyAccount
operations
turnover():Real=transactions->collect(amount)->sum()
Invariantes
• Invariante é uma restrição que deve ser avaliada como
verdadeira durante toda a vida do objeto.
• Invariantes representam regras aplicáveis a objetos do
mundo real.
• Algumas regras de negócio podem ser expressas como
invariantes.
Exemplos de invariantes
(A) Sobre valores de atributos
context Customer
inv ofAge: age >= 18
(B) Sobre tipos não-primitivos
context CustomerCard
inv checkDates: validFrom.isBefore(goodThru)
Notas
(i) validFrom e goodThru são do tipo Date (fora da OCL)
(ii) isBefore é um método do tipo Date
(A) Sobre classes associadas
context CustomerCard
inv ofAge: owner.age >= 18
Invariantes com referência a
classes associativas (1)
context LoyaltyProgram
inv knownServiceLevel:levels->includesAll(Membership.currentLevel)
Notas
(i)Usa a classe
Membership para
estabelecer que o nível de
serviço de cada
associação deve ser um
serviço conhecido do
programa de fidelidade
para a qual o invariante se
aplica.
Invariantes com referência a
classes associativas (1)
o nível de serviço de cada
membership deve ser
conhecido do respectivo
programa de fidelidade
context LoyaltyProgram
inv knownServiceLevel:levels->includesAll(Membership.currentLevel)
Invariantes com referência a
classes associativas (2)
o cartão da membership é um dos cartões
do respectivo customer
context Membership
inv correctCard: participants->collect(cards)->includes(self.card)
Operações em Coleções (collections)
• associações cujas cardinalidades sejam
maiores do que 1 relacionam um objeto a uma
coleção de objetos.
• sempre que a navegação resultar numa coleção
de objetos, pode-se usar uma operação de
coleção. Para indicar o uso de uma operação de
coleção usa-se uma seta (->) entre o nome do
papel e a operação.
Tipos de Coleção
• Set (não há repetição, nem ordem de
elementos).
• Bag (pode haver repetição, mas não
existe ordem dos elementos).
• Sequence (pode haver repetição,
elementos em sequência – bag
ordenado).
• OrderedSet (não há repetição, elementos
em sequência – set ordenado).
Sets, Bags, OrderedSets e Sequences
context ProgramPartner
inv nrOfParticipants: numberOfCustomers =
programs->collect(participants)->size()
context ProgramPartner
inv nrOfParticipants: numberOfCustomers =
Programs->collect(participants)->asSet()->size()
Notas:
(i)-Bag: elementos podem aparecer mais de uma vez
(ii)-Ordered set (conjunto ordenado)
(iii)-Sequence= ordered bag (bag ordenado)
Sets, Bags, OrderedSets e Sequences
context ProgramPartner
inv nrOfParticipants: numberOfCustomers =
programs.participants->size()
context ProgramPartner
inv nrOfParticipants: numberOfCustomers =
programs.participants->asSet()->size()
Operações em Coleções
Operation
Description
count( object )
The number of occurrences of the object in the collection
excludes( object )
True if the object is not an element of the collection
excludesAll( collection)
True if all elements of the parameter collection are not present in the current collection
includes( object )
True if the object is an element of the collection
includesAll( collection)
True if all elements of the parameter collection are present in the current collection
isEmpty()
True if the collection contains no elements
notEmpty()
True if the collection contains one or more elements
size()
The number of elements in the collection
sum()
The addition of all elements in the collection. The elements must be of a type supporting addition.
Iteradores
Operações que são aplicáveis a todos os membros de uma collection
Iteradores mais utilizados:
Select (<bool expr>): <collection>
Forall (<bool expr>): true
Collect (<expr>):<collection
select
Para todo customer: número de seus cartões válidos deve ser igual ao
número de programas dos quais participa
context Customer
inv sizesAgree:
programs->size() /* number of programs for customer*/
=
cards->select( valid = true )->size()
/* number of valid cards*/
Notas
(i)-select recebe uma expressão OCL como parâmetro.
(ii)-retorna um subconjunto da coleção ao qual é aplicado contendo
somente elementos para os quais a expressão é verdadeira.
The Royal&Loyal
Company
forall
se nenhum dos serviços oferecidos por um programa credita ou debita pontos
em LoyaltyAccount, então as respectivas instâncias são inúteis e não devem estar
presentes
context LoyaltyProgram
inv noAccounts:
Partners->collect(deliveredServices)-> forAll(
pointsEarned = 0 and pointsBurned = 0 )
implies
Membership.account->isEmpty()
Notas:
(i)-forAll recebe uma expressão OCL como
parâmetro.
(ii)-retorna verdadeiro se a expressão for
avaliada como verdadeira para todos
elementos da coleção
collect
No contexto LoyaltyProgram
partners->collect(
numberOfCustomers) ) )
pode ser escrito de forma abreviada
como:
partners.numberOfCustomers
Notas:
(i)-forma uma nova collection contendo os valores da expressão aplicada a
cada um dos objetos da coleção.
(ii)-Normalmente usado de forma abreviada pelo operador dot(.)
Pré e pós condições de operações
context LoyaltyAccount::isEmpty(): Boolean
pre : -- none
post: result = (points = 0)
context Service::upgradePointsEarned(amount: Integer)
Pre: -- amount>0
post: pointsEarned = pointsEarned@pre() + amount
Notas:
(i)-Pré e pós condições: especificam o efeito de uma operação sem
especificar o algoritmo.
(ii)-Aplicável também a: métodos de classe, atividades e estados.
(iii)-Operador @pre<attr>, representa o valor do atributo <attr> antes da
operação.Só pode ser usado em nas cláusulas post.
Referências
[1] Warmer, J., Kleppe, A.: The Object
Constraint Language. Precise Modeling
with UML. Addison-Wesley, 1999
[2] Warmer, J., Kleppe, A.: The Object
Constraint Language Second Edition.
Getting Your Models Ready For MDA.
Addison-Wesley, 2003
[3] OMG UML specification, www.omg.org
Exercícios
1-Invariantes: cliente pode participar no máximo em N programas
2-O número máximo de pontos cedidos por um partner em um programa de fidelidade
deve ser menor que 10.000
2-Consultas
2.1-quantidade de pontos ganhos por um cliente em todos os programas onde ele
participa
2.2-idem ao 2.1 para quantidade de pontos consumidos
2.3-total de vendas de um partner em todos os programas onde participa
2.4-cliente com o maior número de pontos ganhos em um dado programa de
fidelidade
2.5- número total de cartões emitidos por um programa de fidelidade
Download

Slides OCL 1