OCL – The Object Constraint Language Franklin Ramalho PhD Student – CIn - UFPE Roteiro Motivação Introdução Tipos e instâncias Herança Estilos para especificação em OCL Questões de modelagem com OCL Considerações Finais Motivaçã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 – Descrever guardas – Servir como linguagem de navegação Invariantes É uma expressão cujo resultado deve ser verdadeiro para todas as instâncias da classe, tipo ou interface associada Exemplo: 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 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 Tipos e instâncias Tipos Valor – Tipos Básicos • • • • Integer Real String Boolean – Tipos Collection • • • • Set Bag Sequence Collection Tipos Objeto – Tipos Modelo (classes, interfaces ou tipos definidos no modelo UML) Tipos e instâncias OCLAny é o supertipo de todos os tipos – – – – – – = <> oclType oclIsKindOf(type : OclType) oclIsTypeOf(type : OclType) oclAsType(type : OclType) Context Burning inv: self.oclType = Burning self.oclIsKindOf(Transaction) = true self.oclIsTypeOf(Transaction) = false self.oclIsTypeOf(Burning) = true Tipos e instâncias OCLType é o supertipo de todos os tipos – – – – – name : String attributes : Set (String) associationEnds : Set (String) operations : Set (String) allInstances : Set(sometype.oclType) Customer.name = ‘Customer’ Transaction.attributes = Set {‘points’, ‘date’} Transaction.associationEnds = Set {‘servicelevel’, ‘loyaltyAccount’, ‘card’} Transaction.operations = Set {‘program’} Tipos Básicos Boolean Context Customer inv: Context Customer inv: title = (if isMale = true age() > 21 and age() < 65 then ‘Mr.’ else ‘Ms.’ endif) Context Service inv: self.pointsEarned > 0 implies self.pointsBurned = 0 Tipos Básicos Integer e Real 2654 * 4.3 + 101 =11513.2 1.175 * (-8.9).abs – 10 = 0.4575 12.max(33) = 33 33.max(12) = 33 33.7.min(12) = 12 13.mod(2) = 1 String ‘casa’.size = 6 ‘casa’.toUpper = ‘CASA’ ‘casa’.concat(‘mento’) = ‘casamento’ 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) LoyaltyProgram 1..n enroll() +partners 1..n ProgramPartner numberOfCustomers : Integer 1..n ServiceLevel name : String Context LoyaltyProgram inv: serviceLevel->size = 2 LoyaltyProgram 1..n enroll() Context ServiceLevel inv: loyaltyProgram.partners -> +partners 1..n ProgramPartner numberOfCustomers : Integer includesAll(availableServices.progr amPartner) ServiceLevel name : String 1..n 0..n +deliveredServices Service condition : Boolean pointsEarned : Integer +availableServices pointsBurned : Integer 0..n description : String Context LoyaltProgram inv: partners.deliveredServices->forAll ( pointsEarned = 0 and pointsBurned = 0) implies membership.loyaltyAccount->isEmpty 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{15, 1, 4, 7, 10} Sequence{1, 4, 7, 10}->prepend( 15 ) = Sequence{1, 4, 7, 10, 15} Tipos Collection Context ProgramPartner inv: numberOfCustomers = loyaltyProgram.customer->size Context ProgramPartner inv: numberOfCustomers = loyaltyProgram.customer>asSet->size Tipos Collection Operações de interação – select Context CustomerCard inv: self.trasactions->select( points > 100 ) –reject – collect Context LoyaltyAccount inv: transaction->collect (points)-> exists (p: Integer | p = 500) Tipos Collection Iterate collection->iterate( element : Type1; result : Type2 = <expression> | <expression-with-element-and-result>) – iterate Context ProgramPartner inv: self.service.transaction->iterate( t: Transaction; result: Integer = 0 | if t.oclType = Burning then result + points else result endif ) 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. 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) Restrições e Herança Principio Liskov: “Onde quer que uma instância de uma classe seja esperada, ela pode ser substituída por uma instância de alguma de suas sub-classes” Na redefinição de uma restrição em uma sub-classe: – Uma invariante pode ser fortalecida, não enfraquecida – pré-condição deve ser enfraquecida, não fortalecida – Pós-condição deve ser fortalecida, não enfraquecida Restrições e Herança Context Stove inv: temperature <= 200 Context ElectricStove inv: temperature <= 300 Context Stove inv: temperature <= 150 Restrições e Herança Context Stove::open() pre: #off post: status = #off and isOpen Context ElectricStove::open() pre: #off post: status = isOpen Context ElectricStove::open() pre: temperature <= 50 post: status = #off and isOpen Estilos para especificação OCL Escolha correta do objeto Context +husband Person +employees 0..1 0..n wife 0..1 +employers 0..n Company 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 Adicionar atributos ou operações extras Estilos para especificação OCL Context Membership inv: program.partners.deliveredServices->forAll(pointsEarned = 0) implies LoyaltyAccount->isEmpty Context LoyaltyProgram inv: isSaving = partners.deliveredServices->forAll(pointsEarned = 0) Context Membership inv: program.isSaving implies LoyaltyAccount->isEmpty Evitar expressões de navegação complexa Questões de modelagem com OCL Especificar Restrições de unicidade Context Person inv: person.allInstances->forAll(p1, p2 | p1 <> p2 implies p1.socialSecurityNumber <> p2.socialSecurityNumber Questões de modelagem com OCL Adicionar detalhes ao modelo versus adicionar restrições +strings GuitarString Guitar 0..1 0..n Electric Guitar +strings MetalString 0..1 0..1 +strings PlasticString ClassicGuitar 0..1 0..n +strings GuitarString Guitar 0..1 Electric Guitar 0..n MetalString ClassicGuitar Context ClassicGuitar inv: strings->forAll(oclType = PlasticString) Context ElectricGuitar inv: strings->forAll(oclType = MetalString) PlasticString Context Guitar inv: type = #classic implies strings->forAll(type = #plastic) Context Guitar inv: type = #electric implies strings->forAll(type = #metal) Questões de modelagem com OCL Restrição or 0..1 projectLeader Person 0..1 0..1 {or} projectMember managedProject Project 0..1 performedProject Questões de modelagem com OCL 0..1 projectLeader Person 0..1 0..1 Project projectMember 0..1 performedProject Context Person inv: managedProject->isEmpty or performedProject->isEmpty Context Project inv: projectLeader->isEmpty or projectmember->isEmpty 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 (?)