Você está na página 1de 26

UNAMA – Universidade da Amazônia

BCC – Bacharelado em Ciência da Computação

Análise e Projeto de Sistemas

OCL
Revisão e Exercícios

Cláudio Roberto Martins


claudiomartins2000@gmail.com
claudiomartins@unama.br

Objetivos da aula
 Revisão de conceitos sobre OCL
 OCL (Object Constraint Language) é um
linguagem criada para fornecer uma precisão
maior na especificação da UML
 OCL é uma linguagem textual para definição de
restrições em modelos.
 Ela é baseada em teoria de conjuntos e lógica de
predicados.
 Exercícios sobre OCL

2
OCL - Contexto
 Apesar do poder de expressão da UML, há
propriedades e restrições de softwares que
são muito complexas ou impossíveis de
serem expressadas em um diagrama
adequadamente por meio de uma
representação exclusivamente iconográfica.
 Mesmo os mecanismos de extensão da UML
– estereótipos (stereotypes), valores
rotulados (tagged values) e restrições
(constraints) pré-definidas – podem ser
insuficientes nesse sentido.
3

Como usar a OCL


 Por exemplo, seja o diagrama de classes de uma
aplicação fictícia representado na Figura:

Como um projetista de software poderia representar no


diagrama, que o número máximo de passageiros (papel
passengers) em um vôo (classe Flight) é limitado pela
capacidade do avião respectivo (classe Airplane, atributo
numberOfSeats)? 4
Como usar a OCL?
Como um projetista de software poderia representar no
diagrama, que o número máximo de passageiros (papel
passengers) em um vôo (classe Flight) é limitado pela
capacidade do avião respectivo (classe Airplane, atributo
numberOfSeats)?

 OBS:
 Usar multiplicidades não é suficiente para
representar essa regra:
a multiplicidade ‘0..*’ da associação entre as
classes Flight e Person, próximo à Person, não
é capaz de refletir essa restrição, dado que o
número de lugares dos aviões pode variar para
cada avião.
5

Solução em OCL.
Como um projetista de software poderia representar no
diagrama, que o número máximo de passageiros (papel
passengers) em um vôo (classe Flight) é limitado pela
capacidade do avião respectivo (classe Airplane, atributo
numberOfSeats)?

 Em OCL:
 self.passengers → size() <= self.plane.numberOfSeats

6
OCL - considerações
 Em expressões OCL é possível a navegação entre
as classes de um modelo UML, a partir de uma
classe-base, que fornece o contexto da expressão.
 para acessar um atributo ou operação, navega-se pelas
associações utilizando o operador “.”;
 Para acessar propriedades de uma coleção – que pode
ser definida pelas instâncias de uma classe, ou pelas
instâncias ligadas (por associação no modelo) a uma

dada instância de uma classe –, utiliza-se o operador →

Explicando OCL
self.passengers → size() <= self.plane.numberOfSeats
 O contexto de navegação é uma instância de Voo (Fight).
 Navega-se do contexto (self) até o alvo da associação (papel
passengers);
 como sua multiplicidade é ‘*’, esse sentido da associação aponta para
uma coleção de elementos (neste caso, um conjunto);
 para acessar uma das propriedades dessa coleção, utiliza-se o operador
“→”.
 A operação executada (size()) retorna o número de elementos
dentro da coleção, na forma de um inteiro (tipo OCL Integer).
 Para a avaliação do lado direito, navega-se do contexto (self)
em direção ao alvo da outra associação (papel plane);
 como sua multiplicidade é ‘1’, esse sentido da associação aponta para
um único elemento (operador “.”), cujo atributo pode ser recuperado
(numberOfSeats), retornando-se um inteiro.
 Por fim, efetua-se a comparação entre os inteiros obtidos em
ambos os lados da expressão. 8
OCL
Object Constraint Language

definições e
conceitos envolvidos

OCL
 OCL é uma notação da UML utilizada para
definir restrições sobre objetos.

 Permite especificar restrições para:


 O valor inicial de um atributo ou associação
 Uma regra de derivação para um atributo ou associação
 Uma instância, uma condição ou um valor para um parâmetro num
diagrama dinâmico
 Etc…

10
OCL - Características
 expressões especificadas em OCL não têm qualquer
efeito colateral, ou seja:
• não causam mudança no estado do objeto
• não causam modificações nos modelos
• não alteram o fluxo de controle

 OCL é fortemente tipada:


• toda expressão tem um tipo
• termos usados na expressão têm de ser usados de acordo com seu tipo
 – ex.: não se pode usar valor inteiro onde se espera um tipo string

 OCL é uma linguagem para especificação, não de programação

 OCL é formal:
• sintaxe bem definida
• semântica precisa, sem ambigüidades

 OCL também pode ser usada para navegar através das associações 11

OCL - Tipos de restrições


 “Invariant” (inv) – uma restrição que se
deve verificar sempre no sistema
 “Precondition” (pre) – uma restrição que
deve ser verdadeira para que uma
operação seja executada
 “Postcondition” (post) - uma restrição que
deve ser verdadeira no final da execução
de uma operação
 “Guard”- uma restrição que deve ser
verdadeira antes de uma transição de
estado 12
OCL - Contexto
 Contexto (context) é o elemento ao qual uma
restrição é associada
• invariante: o contexto é a classe.
• Guarda: o contexto é uma transição do modelo de estado

 A restrição pode ser associada ao contexto de


várias formas:
 Utilizar anotação (notas) em UML

 Descrever na forma de texto:


– uso da palavra reservada context
– uso da palavra reservada self
13

OCL: Invariante
 Invariante é uma condição associada a uma
classe (ou tipo ou associação, ...)
 Deve ser satisfeita a cada instante
 O contexto é definido por um objeto o qual
• pode ser referenciado por self
• pode ser nomeado explicitamente
 A invariante pode ter um identificador

14
OCL: Exemplos de invariantes

Cliente
context Cliente idade: Integer
inv: idade > = 18 and self.idade < 100 casado: Boolean

15

Exemplo de invariante com uma classe

context Transaction inv: points >= 0


16
Invariantes sobre associações

 invariantes de atributos
conectados através de associações:
 referência: objeto.papel
 o valor da expressão pode ser:
 1 objeto, se a multiplicidade da associação é 0..1 ou 1
– ex.: self.gerente (é do tipo Empregado)
 1 coleção de objetos, se a multiplicidade > 1 (*)
– ex.: self.subordinado ( é do tipo conjunto {Empregado} )

17

Pré e pós condições


– condições (ou predicados) associadas a uma
operação
– as pré condições devem ser satisfeitas antes da
execução da operação
– as pós condições devem ser satisfeitas após a
execução da operação
– self pode ser usada para designar o objeto cuja operação
foi chamada
– result pode ser usada para designar o resultado
– @pre permite fazer referência ao valor de um operando
antes da execução da operação

18
Exemplos de pré e pós condições

context Pessoa :: faz_aniversario ( ) Pessoa


post: idade = idade@pre + 1 idade: Integer

faz_aniversario()

context Calculadora :: divisão_inteira (x:Integer, y: Integer)


pre regraDivisor: y ≠ 0 Calculadora
post: result = x / y
regraDivisor: Boolean

divisão_inteira (x:Integer, y: Integer)


19

Ourtros exemplos de expressões e restrições


Conta
id : Integer
saldo: Real = 0 Tipos de valores:
Integer, Real, String, Boolean
deposito(valor : Real)
levantamento(valor : Real)
daSaldo() : Real

context Conta::levantamento (valor : Real)


pre: valor <= saldo
Operações:
post: saldo = saldo@pre – valor
= < > <> <= >= + - * / mod() div()
max() min() round() abs()
context Conta::daSaldo() : Real and or xor not implies
post: result = saldo if_then_else_endif …

20
OCL: Guarda
 Guarda é condição que deve ser satisfeita para que
uma transição do modelo de estados (Statecharts)
ocorra.
 pré condição para a execução da transição
 Representar a restrição da guarda entre { e }

21

Tipos de dados em OCL


– tipos básicos: Integer, Real, Boolean, String
– tipos enumerados (enum)
– tipos provenientes da UML: classes,
associações, generalizações
– tipos compostos (coleções): Set, Bag,
Sequence

22
Expressões em OCL
– constante
– identificador
– self
– expr op expr
– exprobj.propriedadeobj (parâmetros)
– exprcoleção.propriedadecoleção (parâmetros)
– pacote :: pacote :: elemento
– if condição then expr else expr endif
– let variável : tipo in expr
Obs.: propriedade em OCL pode ser: atributo, operação,
método, extremidade de associação
23

Sobre expressões
 Toda expressão tem um tipo de dado e um valor
 Constantes e identificadores podem ser usados em expressões
 ex.: 12
nome
salário
 Uma expressão é referente a um elemento (contexto)

 O uso do ponto ( . ) permite o acesso a uma propriedade (atributo ou


operação) de um objeto
 ex.: self.salário - 100
self.calculaImposto(2003)

 O operador → (->) permite o acesso a uma propriedade de uma coleção


de objetos
 ex.: self.dependentes->size()
self.dependentes->isEmpty()

 O operador :: permite o acesso a elemento de um pacote


 ex.: seja B subclasse de A
self.A :: p1 -- acesso a propriedade p1 definida em A
self.B :: p1 -- acesso a propriedade p1 definida em B
24
Tipos e operações numéricas
 Inteiros (Integer)
– valores: 1, -5, 24345
– operações: +, -, *, div, mod, abs, max, min

 Reais (Real)
– valores: 1.5, 1.3456
– operações: +, -, *, /, floor, round, max, min

25

Tipos e operações lógicas


 Valor lógico (Boolean)
– valores: true, false
– operações: not, and, or, xor, implies, if-then-else-endif
– obs.:
• true or x é sempre verdadeiro, mesmo se x é indefinido
• false and x é sempre falso, mesmo se x é indefinido
 exemplos:
(idade < 20 implies desconto = 25) and
(idade >= 20 implies desconto = 15)

if idade < 20 then desconto = 25 else desconto = 15 endif

desconto = (if idade < 20 then 25 else 15 endif)

26
Tipos e operações com String
 Cadeia de caracteres (String)
– valores delimitados por ‘ ’
Ex: “uma sentença”

– operações:
 cadeia.size( )
 cadeia1.concat(cadeia2)

 cadeia1.substring(posição1, posição2)

 cadeia.toUpper( )

 cadeia.toLower( )

27

Tipos enumerados (enum)


 Tipos enumerados (enum)
 definição:
• enum {segunda, terça, quarta, quinta, sexta}
 utilização (utiliza # para recuperar o elemento):
• #quarta
 operações: -, = , <>

28
Tipos e operações com Coleções
 Em OCL pode-se ter 3 tipos de coleção:
 conjunto (set): sem repetição, desordenado
 ex.: set {1, 6, 90, 2, 0}

 “saco” (bag): com repetição, desordenado


 ex.: bag {203, 5, 40, 5, 300, 5}

 seqüência (sequence): com repetição, ordenada


 ex.: sequence {5, 5, 5, 40, 203, 300}

29

Considerações sobre coleções


 Os conjuntos são usados em UML:
– como extensões de classe, de associações
– como extremidade (endpoint) de uma associação

 As seqüências são usadas em UML:


– em associações com a restrição {ordered}

 Os “sacos” resultam da navegação em OCL:


– resultado da operação collect()
– útil para operações como sum()
empregado -> collect(salario).sum()

30
Operações sobre coleções
 Operações básicas:
 union(), intersection(), ...

 Operações de filtragem:
 – seleção e eliminação de acordo com uma condição:
 select(), filter()

 Imagem de uma função:


 collect()

 Quantificadores:
 forAll (), exists()

 Determinação de unicidade:
 isUnique() 31

Operações sobre coleções


 Cardinalidade coleção -> size()
 Número de ocorrências coleção -> count(elem)
 Pertence coleção -> includes(elem)
 Não pertence coleção -> excludes(elem)
 Inclusão col1 -> includesAll(col2)
 Checa se vazio coleção -> isEmpty()
 Checa se não vazio coleção -> notEmpty()
 Soma de elementos coleção -> sum()

32
Coleção: filtragem
 Seleção de elementos que satisfazem a uma
condição: coleção -> select(cond)
 ex.:
self.empregado -> select (idade>55 and sexo = #masculino)

enum{masculino,
enum{masculino, feminino}

 Eliminação de elementos que satisfazem a


uma condição: coleção -> reject(cond)
 ex.: self.aluno -> reject( cr < 7)

 Outra sintaxe:
 self.aluno -> reject (p:Pessoa | p.cidade_origem <> ‘Campinas’)

33

Coleção: imagem
 Corresponde à imagem de um função em
matemática: coleção -> collect (expr)
– a expressão é avaliada para cada elemento da coleção
– o retorno da avaliação é um “saco” com os resultados
 Ex.:
 self.empregados -> collect (idade) ► Bag{22, 37, 25, 22, 44, 52}
 self.empregados -> collect (idade) -> asSet() ► obtém o conjunto
 self.empregados -> collect (salário) -> sum()

 pode-se escrever de forma simplificada:

 self.empregados -> collect (idade) ↔ self.empregados.idade

34
Coleção: Quantificadores
 Pode-se usar os quantificadores: ∀ e ∃

 coleção -> forAll(cond)


 retorna verdade se a cond é satisfeita por todos os elementos da
coleção

 coleção -> exists(cond)


 retorna verdade se a cond é satisfeita por pelo menos um elemento da
coleção

 Ex.:
self.empregados -> forAll (idade < 55)

self.empregados -> exists (sexo = #feminino and idade > 50)

100 + if self.pessoa -> forAll (idade < 18) then 50


else self.pessoa -> select (idade >= 18) -> size() * 5 endif

self.empregados -> exists ( p: Pessoa | p.sobrenome = ‘Martins’)


35

Coleção: determinação de unicidade


 Retorna verdade se para cada elemento da
coleção a expressão retorna um valor
diferente:
 coleção -> isUnique (expr)
 Ex.:
self.alunos -> isUnique (matricula)

 útil para definir a noção de chave (identificador único)

36
Operações relativas ao diagrama de classes
 OCL oferece várias operações sobre o
diagrama de classes:
 acesso a atributos e métodos
• acesso a um atributo: objeto.atributo
– ex.: self.anodeProdução
self.idade
 acesso a método: objeto.método(expr1, expr2, ...)
 ex.: self.calcula_media(turma00)

 navegação pelas associações


 acesso a tipos e supertipos
 acesso às instâncias de uma classe
37

Navegação através de uma associação


 A partir de um objeto (contexto) é possível o
acesso a objetos que lhe são associados:
objeto.papel
– se cardinalidade 1 ou 0..1: o resultado é um
objeto
– senão o resultado pode ser um conjunto (Set) ou
uma seqüência (sequence) se associação tem
restrição {ordered}
– se não tem papel em uma associação pode-se
usar o nome da classe destino com a primeira
letra em caixa baixa (minúscula)
38
Exemplos de navegação através de uma
associação

 Pessoa
self.marido -- é do tipo Pessoa
self.empregador -- é do tipo Set (Empresa)
self.marido -> notEmpty() implies self.marido.sexo = #masc
not ( (self.mulher -> size() = 1 and (self.marido -> size() = 1) )

39

Navegação para uma associação


 Se a associação é uma classe, pode-se ter
acesso a ela através de um objeto:
objeto.nome_da_associação
o nome da associação deve iniciar com minúscula
 o resultado é exatamente 1 objeto, instância da
classe referente à associação
 ex.:
Pessoa
self.emprego -> collect(salario) -> sum()
resultado é convertido em um objeto único
(singleton)

40
Navegação para uma associação
 Se a associação (classe) é reflexiva, pode-se
indicar o papel para evitar ambigüidade:
objeto.nome_da_associação [papel]

Pessoa:
self.casamento [mulher].local

41

Navegação a partir de uma associação


 Pode-se navegar a partir da associação
(classe) para os objetos que ela relaciona:
nome_da_associação.papel
 o resultado da navegação será sempre 1 único
objeto (que pode no entanto ser convertido em
singleton)
 Exemplos:
 Emprego
self.empregador
self.empregado

42
Navegação através de associação qualificada
 Associações qualificadas usam 1 ou + atributos para
selecionar objetos na outra ponta da associação
 Para navegar através dela, pode-se indicar um valor para o(s)
atributo(s) usado(s) como qualificador(es): objeto.papel [valor]

Banco:
self.cliente -- Set(Pessoa)
self.cliente [4001155] -- 1 objeto Pessoa com nro de conta dado
43

Navegação em associações qualificadas

Conta
id : Integer
saldo: Real = 0
dono
conta Cliente
id
deposito(valor : Real) * 1
levantamento(valor : Real)
daSaldo() : Real

cliente.conta [4321]

Ou

cliente.conta [id = 4321]

44
“Navegação” em associações qualificadas

Conta

id : Integer
saldo: Real = 0 conta dono
Cliente
* 1
deposito(valor : Real)
levantamento(valor : Real)
daSaldo() : Real
Expressão incorreta

Expressão correta
cliente.conta.saldo = 0

cliente.conta -> select (id=1234).saldo = 0

45

Exercícios resolvidos

46
Q1
 O sistema em questão trata de uma loja virtual, tipo “carrinho de compras”,
para venda de produtos.
 Qual a expressão OCL que representa a restrição:
 “um novo item de produto foi adicionado ao carrinho de compras”?

RESPOSTA:

self.carrinhoCompras → including (ItemProduto.new())

ou

itemProduto = ItemProduto.new()
self.addToCarrinhoCompras(itemProduto)
// considerando que “carrinhoCompras” é uma associação temporária
no sistema.
47

Q2
 qual a expressão OCL que representa a restrição:
 “foi destruído um item de produto do carrinho de
compras, cujo nome do produto = prodC”?
 Obs: “nome do produto” é o atributo “nome” de ItemProduto

RESPOSTA
→select(nome=prodC)
itemProduto = self.carrinhoCompras→

self. carrinhoCompras →remove(itemProduto)


itemProduto.destroy()

 ou
self. carrinhoCompras → excluding (nome=prodC) 48
Q3
 O valor do “itemProduto” foi alterado para
R$ 10,00.

 RESPOSTA:

self.itemProduto.valor = 10.0

49

Q4
 Qual das expressões OCL abaixo melhor representa a
seguinte pós-condição: “o salário de todos os
funcionários que ganham menos de R$ 1000,00 foi
reajustado em 10%” ?:
a) self.funcionários → select (f | f.salario@pre < 1000 implies
f.salario@pre = f.salario * 1.1)
b) self.funcionários → forAll (f | f.salario@pre < 1000 implies
f.salario@pre = f.salario * 1.1)
c) self.funcionários → collect (f | f.salario@pre < 1000 implies
f.salario = f.salario * 1.1)
d) self.funcionários → collect (f | f.salario < 1000 implies
f.salario@pre = f.salario@pre * 1.1)
e) self.funcionários → forAll (f | f.salario@pre < 1000 implies
f.salario = f.salario@pre * 1.1)

50
Q6 cliente

 Escreva a sentença OCL para a seguinte pré-


condição da operação abaixo:
Classe Videolocadora
operação: identificaCliente(nomeCliente:String)
pré-condição:
Existe um Cliente cujo nome é igual a nomeCliente.
RESPOSTA

self. cliente → exists (nome = nomeCliente)

51

Você também pode gostar