UML - OCL
Franklin Ramalho
DSC-UFCG
CIn - UFPE
Roteiro
UML
– Introdução – Diagramas
– Diagrama de classes
OCL
– Introdução
– Invariantes, pré e pós-Condições – Tipos
– Estilos de programação e questões de modelagem
Considerações Finais
Introdução
Empresa de Software de sucesso ↔ desenvolve software de qualidade e atende aos usuários
Modelagem é uma tarefa fundamental nas atividades iniciais do desenvolvimento do software
– Comunicar a estrutura e comportamento desejados para o sistema – Visualizar e controlar a arquitetura do software
– Melhor entendimento do sistema – Gerenciar os riscos
– Etc, ...
É preciso utilizar uma linguagem expressiva, simples e padrão
Introdução
UML é uma linguagem para especificação, visualização, construção e documentação de artefatos de sistemas de software.
– Linguagem padrão adotada e recomendada pela OMG.
Extensível
Apenas uma linguagem
Independente de processo
Amplamente utilizada pelo mercado e pela academia
Inter-disciplinar
Não possui semântica formal bem definida
Abrange modelagem estrutural e comportamental
Sub-dividida em diagramas (9)
Introdução
Parte estrutural
– Diagrama de classes – Diagrama de objetos
– Diagrama de Componentes – Diagrama de Desenvolvimento
Classes, interfaces e relacionamentosObjetos e
relacionamentosComponentes e dependências
Nodos e configurações
Introdução
Parte comportamental
– Diagrama de Colaboração – Diagrama de Seqüência – Diagrama de Casos de Uso – Diagrama de estados
– Diagrama de atividades
Diagramas de Interação:
Objetos, relacionamentos e mensagens
}
Casos de uso, atores e relacionamentos Máquina de estados:Estados, transições, eventos e atividades
}
Diagrama de Classes
É um diagrama que mostra um conjunto de classes, interfaces e relacionamentos.
Responsável por modelar a parte estática do sistema
Uma classe é uma descrição de um conjunto de objetos que compartilham os mesmos atributos, operações, relacionamentos e semântica
Interface é uma coleção de operações que são usadas para especificar um serviço de uma classe
Um relacionamento é uma conexão entre classes.
Pode conter notas, restrições e pacotes
Diagrama de Classes
Rectangle Circle Polygon
display()
Square
Shape origin display() move()
resize() ShapeInterfa
ce display()
move() resize()
Tipo especial de Rectangle que possui os lados de mesmo tamanho
ShapePackage
Diagrama de Classes
Adornos aplicados às classes, atributos e operações:
– Visibilidade – especifica se ela pode ser usada por outros classificadores
• Public (+)
• Protected (#)
• Private (-)
– Escopo – especifica se a propriedade aparece em cada
instância do classificador ou se existe apenas uma instância da característica para todas as instâncias do classificador
• Instance (default)
• Classifier (propriedade sublinhada)
Diagrama de Classes
Outras propriedades:
– Abstract (nome da classe em itálico) – Leaf ‘{leaf}’ após nome da classe – Root ‘{root}’ após nome da classe
Rectangle Circle {leaf} Polygon display()
Square
Shape origin : Point = (0,0) id : Integer {addOnly}
display() move() resize()
ShapeInterfa ce
display() move() resize()
Tipo especial de Rectangle que possui os lados de mesmo tamanho
Diagrama de Classes
Um relacionamento é uma conexão entre classes.
FilmClip name
playOn(c : Channel)
Channel
Generalização – relacionamento entre uma classe geral (super-classe) e uma mais específica (sub-classe)
Dependência – indica que a mudança na especificação de uma classe deve afetar uma outra classe.
Shape
Rectangle Circle Polygon
Square
Diagrama de Classes
Associação é um relacionamento estrutural, que especifica que objetos de uma classe são conectados com objetos de uma outra classe
Associação entre todo-parte é conhecida como agregação
Composição é um tipo especial de agregação que ocorre quando o tempo de vida do todo e da parte são iguais
Company 1
* Department
*
1 1
1..*
1..*
1 Company
Department Company
Person
Diagrama de Classes
Vários adornos aplicados às associações
– Nome, Papéis, Multiplicidade, etc.
Rectangle Circle {leaf} Polygon display()
Square
Shape origin : Point = (0,0) id : Integer {addOnly}
display() move() resize()
ShapeInterfa ce
display() move() resize()
Tipo especial de Rectangle que possui os lados de mesmo tamanho
Realização é um relacionamento entre classificadores onde um especifica um contrato e outro garante cumpri-lo
Person
+employer
0..* 1..*
+employee 1..*
0..* Works for Company
Diagrama de Classe
Uma associação entre duas classes pode possuir propriedades: classes-associação
Person 0..* Works for 1..* Company
+employee +employer
1..*
0..*
Job description dateHired salary
Burning Earning Transaction
points : Integer date : Date program() LoyaltyAccount
points : Integer earn()
burn() isEmpty()
+transactions 0..n0..n
CustomerCard valid : Boolean validFrom : Date goodThru : Date
color : enum{silver, gold}
printedName : String
0..n
+transactions 0..n
+card Service
condition : Boolean pointsEarned : Integer pointsBurned : Integer description : String
0..n +transactions
0..n
Membership
0..1
0..1 +card
Customer name : String title : String ismale : Boolean dateOfBirth : Date age()
+cards 0..n0..n +owner
ProgramPartner
numberOfCustomers : Integer
0..n +deliveredServices 0..n
LoyaltyPr ogram
enroll() 0..n 0..n0..n
+program 1..n 0..n
1..n 1..n
+partners 1..n
ServiceLevel name : String
0..n
+availableServices 0..n
0..n 0..n
+actualLevel
1..n 1..n
Introdução
UML não provê todos aspectos relevantes da especificação do sistema
Linguagem Natural é ambigua
Linguagens formais requerem forte conhecimento matemático
OCL - Linguagem para escrita de restrição sobre
objetos, que pode ser aplicada em um ou mais
valores de um (ou parte de) sistema ou modelo
orientado a objetos.
Introdução
Linguagem formal de fácil escrita e leitura
Não é uma linguagem de programação
Sem efeitos colaterais
Linguagem tipada
Avaliação instântanea
Introdução
Uso de OCL:
– Especificar invariantes
– Descrever pre e pos condições sobre operações e métodos
– Servir como linguagem de navegação
Transaction points : Integer date : Date program() LoyaltyAccount
points : Integer earn()
burn() isEmpty()
+transactions 0..n0..n
CustomerCard valid : Boolean validFrom : Date goodThru : Date
color : enum{silver, gold}
printedName : String
0..n
+transactions 0..n
+card Service
condition : Boolean pointsEarned : Integer pointsBurned : Integer description : String
0..n +transactions
0..n
Membership
0..1
0..1 +card
Customer name : String title : String ismale : Boolean dateOfBirth : Date age()
+cards 0..n0..n +owner
ProgramPartner
numberOfCustomers : Integer
0..n +deliveredServices 0..n
LoyaltyPr ogram
enroll() 0..n 0..n0..n
+program 1..n 0..n
1..n 1..n
+partners 1..n
ServiceLevel name : String
0..n
+availableServices 0..n
0..n 0..n
+actualLevel
1..n 1..n
Invariantes
É uma expressão cujo resultado deve ser verdadeiro para todas as instâncias da classe, tipo ou interface associada
Exemplos:
Context c : Customer inv MinimumAge:
c.age() >= 18 Context Customer inv:
self.age() >= 18
Podem ser representadas através:
–
Nota no modelo UML– Estereótipo <<invariant>>
– Arquivo separado
– Tab específico provido por ferramentas
Invariantes
Exemplo:
Context membership inv:
card.owner = customer
Context CustomerCard inv:
printedName = customer.title.concat (customer.name)
Invariantes
<<invariant>>
Context Customer inv:
self.age() >= 18
Customer name : String title : String
ismale : Boolean dateofBirth : date age()
<<invariant>>
Context Customercard inv:
printedname = customer.title.concat(
customer.name)
CustomerCard valid : Boolean validfrom : Date goodThru : Date printedName : string
Pre e pos-condições
Pré-condição é uma restrição que deve ser verdadeira no inicio da execução da operação.
Pós-condição é uma restrição que deve ser verdadeira no final da execução da operação.
Context Typename::operationName (param1 : Type1, ...) : ReturnType
pre: param1 > ...
post: result = ...
Context LoyaltyAccount::isEmpty() : Boolean pre: -- none
post: result = ( points = 0)
Context LoyaltyProgram::enroll(c : Customer) pre: not customer->includes(c)
post: customer = customer@pre->including(c)
Pre e pos-condições
Podem ser representadas através:
– Nota no modelo UML
– Estereótipos <<precondition>> e <<poscondition>>
– Arquivo separado
– Tab específico provido por ferramentas
LoyaltyProgram enroll()
<<precondition>>
not customer->includ...
<<postcondition>>
customer = customer@pre-...
Tipos e instâncias
Tipos Pré-definidos
– Tipos Básicos
• Integer
• Real
• String
• Boolean
– Tipos Collection
• Set
• Bag
• Sequence
• Collection
Tipos Modelo
– classes, interfaces ou tipos definidos no modelo UML
Tipos Básicos
Boolean
Context Customer inv:
title = (if isMale = true
then ‘Mr.’
else ‘Ms.’
endif)
Context Customer inv:
age() > 21 and age() < 65
Tipos Collection
Collection - supertipo abstrato usado para definir operações comuns entre todos os tipos Collection (Set, Bag e Sequence)
Operações:
– size
– count(object) – includes(object)
– includesAll(collection) – isEmpty
– notEmpty – sum()
– exists(expression) – forAll(expression) – including(object) – excluding(object)
ProgramPartner
numberOfCustomers : Integer
LoyaltyProgram enroll()
ServiceLevel name : String 1..n
+partners 1..n 1..n
1..n
1..n 1..n
Context LoyaltyProgram inv:
serviceLevel->size = 2
ProgramPartner
numberOfCustomers : Integer
LoyaltyProgram enroll()
Service
condition : Boolean pointsEarned : Integer pointsBurned : Integer description : String
ServiceLevel name : String 1..n
+partners 1..n 1..n
1..n
+deliveredServices 0..n
0..n
+availableServices 0..n
0..n
1..n 1..n
Context ServiceLevel inv:
loyaltyProgram.partners ->
includesAll(availableServices.progr
amPartner)
Context LoyaltProgram inv:
partners.deliveredServices->forAll ( pointsEarned = 0 and
pointsBurned = 0) implies membership.loyaltyAccount->isEmpty
ProgramPartner
numberOfCustomers : Integer
LoyaltyProgram enroll()
Service
condition : Boolean pointsEarned : Integer pointsBurned : Integer description : String
ServiceLevel
name : String LoyaltyAccount points : Integer earn()
burn() isEmpty()
Membership 1..n
+partners 1..n 1..n
1..n
+deliveredServices 0..n
0..n
+availableServices 0..n
0..n
+actualLevel
1..n 1..n
0..1 0..1 0..n
0..n
Tipos Collection
Tipo Set
– Subtração (-)
Set{1, 4, 7, 10} – Set {4, 7} = Set {1, 10}
– Diferença simétrica
Set{1, 4, 7, 10}.symmetricDifference(Set{4, 5, 7}) = Set{1, 5, 10}
Tipo Sequence
– first, last, at, append e prepend.
Sequence{1, 4, 7, 10}->first = 1 Sequence{1, 4, 7, 10}->last = 10 Sequence{1, 4, 7, 10}->at(3) = 7
Sequence{1, 4, 7, 10}->append( 15 ) = Sequence{1, 4, 7, 10, 15}
Sequence{1, 4, 7, 10}->prepend( 15 ) = Sequence{15, 1, 4, 7, 10}
Tipos Collection
Context ProgramPartner inv:
numberOfCustomers = loyaltyProgram.customer->size
Context ProgramPartner inv:
numberOfCustomers = loyaltyProgram.customer-
>asSet->size
0..n
Customer name : String title : String
ismale : Boolean dateOfBirth : Date age()
LoyaltyProgram enroll()
ProgramPartner
numberOfCustomers : Integer
+program
0..n 0..n
1..n 0..n +partners 1..n
1..n
1..n
Tipos Collection
Operações de interação
–
select
Context CustomerCard inv:
self.trasactions->select( points > 100 )
LoyaltyAccount points : Integer earn()
burn() isEmpty()
Transaction points : Integer date : Date program()
CustomerCard valid : Boolean validFrom : Date goodThru : Date
color : enum{silver, gold}
printedName : String
+transactions 0..n
+transactions 0..n
0..n
+card
0..n
– reject
–
collect
Context LoyaltyAccount inv:
transaction->collect (points)-> exists (p: Integer | p = 500)
LoyaltyAccount points : Integer earn()
burn() isEmpty()
Transaction points : Integer date : Date program()
CustomerCard valid : Boolean validFrom : Date goodThru : Date
color : enum{silver, gold}
printedName : String
+transactions 0..n
+transactions 0..n
0..n
+card
0..n
Tipos Modelo
Classes (inclusive, classes-associação), tipos e interfaces definidos no modelo UML, são
consideradas classes em OCL.
Estes tipos possuem propriedades:
– Atributos
– Operações e métodos
– Navegações (associações)
– Enumerações (definidas como tipo de algum atributo)
Exemplos: Service, ProgramPartner, Customer, etc.
Enumeration {silver, gold} definida na classe
CustomerCard.
+card
Burning Earning
Customer name : String title : String ismale : Boolean dateOfBirth : Date
LoyaltyAccount points : Integer earn()
burn() isEmpty()
CustomerCard valid : Boolean validFrom : Date goodThru : Date
color : enum{silver, gold}
printedName : String +cards 0..n0..n +owner
Transaction points : Integer date : Date program() +transactions 0..n0..n
0..n
+transactions 0..n
Service
condition : Boolean pointsEarned : Integer pointsBurned : Integer description : String
0..n +transactions
0..n
Membership
0..1 0..1 ProgramPartner
numberOfCustomers : Integer
0..n +deliveredServices 0..n
ServiceLevel name : String
0..n
+availableServices 0..n
0..n 0..n
+actualLevel LoyaltyPr
ogram
enroll() 0..n 0..n0..n
+program 1..n 0..n
1..n 1..n
+partners 1..n
1..n 1..n
+card
Tipos Modelo
Navegações são tratadas como atributos cujos tipos são tipos modelo ou collections
– Se a multiplicidade é no máximo 1, o tipo é modelo Context CustomerCard inv:
self.owner.age() > 18
– Se a multiplicidade > 1, o tipo é collection Context Customer inv:
self.cards->size = 1
Tipos Modelo
Navegação em classes-associação
Context Membership inv:
program.serviceLevel->includes (actualLevel)
Context LoyaltyProgram inv:
serviceLevel->includesAll
( membership.actualLevel)
Estilos para especificação OCL
Escolha correta do objeto Context
0..1
Company Person
0..n 0..n
+employers 0..n +employees
0..n 0..1
0..1
wife 0..1 +husband
Context Person inv:
wife.employers->intersection (self.employers)->isEmpty and
husband.employers->intersection (self.employers)->isEmpty Context Company inv:
employees.wife->intersection(self.employees)->isEmpty
Estilos para especificação OCL
Dividir uma restrição em várias
Context ProgramPartner inv:
partners.deliveredServices->forAll(pointsEarnerd = 0)
and membership.card->forAll(goodThru = Date.fromYMD(200.1.1)) and customer->forAll(age() > 55)
Context ProgramPartner inv:
partners.deliveredServices->forAll(pointsEarnerd = 0)
Context ProgramPartner inv:
membership.card->forAll(goodThru = Date.fromYMD(200.1.1))
Context ProgramPartner inv:
customer->forAll(age() > 55)
Estilos para especificação OCL
Context Membership inv:
program.partners.deliveredServices->forAll(pointsEarned = 0) implies LoyaltyAccount->isEmpty
LoyaltyProgram
<<oclAttribute>> isSaving : Boolean
Context LoyaltyProgram inv:
isSaving = partners.deliveredServices->forAll(pointsEarned = 0)
Context Membership inv:
program.isSaving implies LoyaltyAccount->isEmpty
Evitar expressões de navegação complexa
Adicionar atributos ou operações extras
Questões de modelagem com OCL
Adicionar detalhes ao modelo versus adicionar restrições
Guitar GuitarString
0..n 0..1
+strings 0..n 0..1
Electric
Guitar MetalString
0..1 0..1
+strings 0..1 0..1
ClassicGuitar PlasticString
0..n 0..1
+strings 0..n 0..1
Guitar GuitarString 0..n
0..1
+strings 0..n 0..1
Electric
Guitar MetalString
ClassicGuitar PlasticString
Context ClassicGuitar inv:
strings->forAll(oclType = PlasticString)
Context ElectricGuitar inv:
strings->forAll(oclType = MetalString)
+strings
0..1 0..n
0..1 0..n
GuitarString
type : enum{plastic, metal}
Guitar
type : enum{electric, classic}
Context Guitar inv:
type = #classic implies strings->forAll(type = #plastic)
Context Guitar inv:
type = #electric implies strings->forAll(type = #metal)
Considerações Finais
OCL é uma linguagem que expressa informação extra em modelos.
– Formal
– Fácil de ler e escrever – Declarativa
– Sem efeitos colaterais – Tipada
– Adotada pela OMG como parte de UML.
Extensões
– Novos tipos
– Novas operações
– O que fazer quando uma restrição for violada – Geração de código (?)
– Outros diagramas: de estados, sequência,etc
– Ferramentas que permitam geração de código (?)