Docente: Giuseppe Scollo
Università di Catania, sede di Comiso (RG)
Facoltà di Scienze Matematiche, Fisiche e Naturali
Corso di Studi in Informatica applicata, AA 2006-7
con riferimento al modello di rete di servizi presentato nella lezione 5:
inizializzazione di attributi (o estremi di associazioni)
context SchedaIscrizione::valida init: true context CorsoDiStudio::iscritti init: Set{}
specifica di derivazione del valore di elementi del modello
context SchedaIscrizione::nomeTitolare derive: titolare.titoloStudio.concat(' ').concat(titolare.nome)
specifica di operazioni query
context CorsoDiStudio::getServiziF():Set(ServizioFormativo) body: fornitori.serviziResi->asSet()
specifica di nuovi attributi e operazioni (v.
il diagramma precedente per la classe ModuloIns
)
context ServizioFormativo def: getIns():Set(Insegnamento) = getM().insegnamenti->asSet()
è buona regola di stile dare un nome a ciascun invariante
con riferimento al modello di rete di servizi presentato nella lezione 5:
invarianti su attributi
context Studente inv lunghezzaCF: codiceFiscale.length = 16
quando il tipo di un attributo è una classe
context Transazione inv servizioCdS: corso.getServiziF()->includes(ServizioFormativo)
invarianti su oggetti associati
context SchedaIscrizione inv lunghezzaCFtitolare: titolare.codiceFiscale.length = 16
invarianti e classi di associazione
context Iscrizione inv schedaIscr: iscritti.schedeServizi->includes(self.scheda)
con riferimento al modello di rete di servizi presentato nella lezione 5:
alcune operazioni sulle collezioni:
size, select
context CorsoDiStudio inv minServizi: fornitori.serviziResi->size() >= 1
context Studente inv schedeCdS: corsi->size() = schedeServizi->select(valida)->size()
altre operazioni sulle collezioni:
reject, forAll, isEmpty
context ModoServizio inv lsIscrizioni: registrazioni->forAll(scheda.livello = ls)
context ModoServizio inv lsIscrizioni: registrazioni->reject(scheda.livello = ls)->isEmpty()
l'operazione collect
, di frequente uso
implicito nella dot notation
su collezioni:
context CorsoDiStudio
fornitori.nrStudenti
abbrevia
fornitori->collect(nrStudenti)
altre operazioni sulle collezioni:
notEmpty,
includes(object),
union(collection),
intersection(collection)
Bag = Set + molteplicità
OrderedSet = Set + ordine lineare
Sequence = Bag + ordine lineare
collect
su Set
→
Bag
collect
su OrderedSet
→
Sequence
N.B. collect
implicita
nella navigazione
context PartnerFormazione inv: nrStudenti <= offertaFormativa.iscritti->asSet()->size()
tenendo conto dell'ordinamento dei sottotipi di LivelloServizio
(v. appresso per oclIsTypeOf
):
context CorsoDiStudio inv: livelli.first().oclIsTypeOf(Auto)
pre- e post-condizioni: utili per specificare il Design by Contract (Meyer)
contesto: un'operazione
suffisso @pre
:
ad es., con riferimento al modello di rete di servizi presentato nella lezione 5:
context ContoIscrizione::acquisisciCF(u:Integer) pre: dfu >= u post: (dfu = dfu@pre - u) and (cfu = cfu@pre + u)
assenza di pre- o post-condizione: meglio se esplicita con un
commento, sintassi:
-- commento
context ContoIscrizione::acquisisciDF(u:Integer) pre: -- nulla post: dfu = dfu@pre + u
specifica di invio di messaggi
nelle postcondizioni: operatore ^
(leggi: hasSent
)
context ContoIscrizione::acquisisciCF(u:Integer) post: self^consumoDF(u)
la meta-operazione oclIsTypeOf
:
ad es., con riferimento al modello di rete di servizi presentato nella lezione 5:
context ContoIscrizione inv: dfu = transazioni->select(oclIsTypeOf(AcquisizioneDFU)).uf->sum() - transazioni->select(oclIsTypeOf(ConsumoDFU)).uf->sum()
per i commenti su più righe, sintassi:
/* commento
su più righe */
variabili locali, sintassi:
let <var>[:<type>] = <expr> in <expr>
context ContoIscrizione inv: let dfuAcquisiti = transazioni->select(oclIsTypeOf(AcquisizioneDFU)).uf->sum() in let dfuConsumati = transazioni->select(oclIsTypeOf(ConsumoDFU)).uf->sum() in dfu = dfuAcquisiti - dfuConsumati
vediamo ora, in modo più sistematico, esempi di estensioni OCL a vari tipi di diagrammi UML ...
con riferimento al modello di rete di servizi presentato nella lezione 5:
specifica di regole di derivazione, anche per nuovi attributi o operazioni
context ContoIscrizione::serviziUsati:Set(ServizioFormativo) derive: transazioni.ServizioFormativo->asSet()
inizializzazione di attributi (o estremi di associazioni)
context ContoIscrizione::dfu:Integer init: 0 context ContoIscrizione::transazioni:Set(Transazione) init: Set{}
specifica di operazioni query
context ContoIscrizione::contoVuoto():Boolean body: dfu = 0
specifica di invarianti, meglio se con nome
context ContoIscrizione inv unicoLivelloServizio: transazioni.ServizioFormativo.ModoServizio.ls->asSet()->size() = 1
principio del Design by Contract (Meyer):
implicazionepre
⇒
post
specifica diritti e doveri
di fornitore e utenti di un'operazione:
contesto: un'operazione
suffisso @pre
:
ammesso solo nelle post-condizioni,
v. sopra
ad es., possiamo estendere il modello di rete di servizi presentato nella lezione 5 con le operazioni:
context CorsoDiStudio::iscrivi(s:Studente) pre: s.nome <> '' post: iscritti = iscritti@pre->including(s)
^
(leggi: hasSent)
context ServizioFormativo::registra(i:Iscrizione) pre: let c = i.CorsoDiStudio in let s = i.Studente in (fornitore.offertaFormativa->includes(c)) and (c.iscritti->includes(s)) and (i.conto.dfu >= dfuRichiesti) and (ModoServizio.ls = i.scheda.livello) post: (ModoServizio.registrazioni = ModoServizio.registrazioni@pre->including(i)) and i.conto^contoVuoto()
risoluzione di ambiguità causate da cicli
⇐
invariante su una classe
nel ciclo
context Transazione inv contoTrans: ServizioFormativo.ModoServizio.registrazioni.conto->includes(conto)
definizione di classi derivate:
derive
di ciascuna delle
sue caratteristiche, ed eventualmente aggiungendo invarianti
VerbaleEsame
con classe associata AcquisizioneCFU
precisazione di molteplicità dinamica o
opzionale
⇐
invarianti su classi associate
context Studente inv nrIscrizioniValide: corsi->size() = schedeServizi->select(valida)->size()
risoluzione di ambiguità del
vincolo or su una coppia di associazioni
bidirezionali opzionali su una stessa coppia di classi
⇐
invariante su
una delle due classi
espressioni OCL utili quando il diagramma di componenti contiene interfacce o classi
in tal caso, si applica quanto già visto:
usi principali di OCL per diagrammi di interazioni:
alt, opt
)
attenzione : elementi dei diagrammi di interazioni sono istanze (non classi), ciò implica:
usi principali di OCL per diagrammi di macchine a stati:
quando il diagramma rappresenta la dinamica di un oggetto, questo è l'istanza contestuale delle espressioni OCL e il suo tipo ne è il tipo contestuale
nel caso di espressioni OCL di valori di parametri in azioni, il contesto dell'espressione è lo stato o la transizione in cui l'azione viene eseguita
l'operazione booleana oclInState(stato)
può
applicarsi all'istanza contestuale self
per specificare
vincoli dipendenti dal suo stato, ad esempio:
context SchedaIscrizione inv: self.oclInState(attiva) implies valida inv: self.oclInState(scaduta) implies not(valida)
usi principali di OCL per diagrammi di attività:
self
all'istanza contestuale non è disponibile, dunque manca
il tipo contestuale
quest'ultimo problema si presenta sistematicamente nel (molto discutibile) tentativo di estendere i diagrammi di casi d'uso con espressioni OCL
(opinione personale: meglio non provarci ;)
definizioni di attributi o operazioni query
espressione di vincoli di inclusione fra associazioni
invarianti in luogo di ereditarietà
adoperare navigazioni brevi
fare attenzione alla scelta del contesto
evitare allInstances
quando è possibile
separare i vincoli in congiunzioni di vincoli
usare l'abbreviazione .
per collect
dare nome agli estremi di associazioni