L'Object Constraint Language o OCL è un linguaggio di specifica formale inizialmente proposto come estensione per il linguaggio di modellazione object-oriented UML e successivamente (2003) entrato a far parte del nuovo standard del linguaggio (UML 2.0). OCL può essere impiegato insieme a qualunque metamodello basato su MOF. Inoltre, OCL è un elemento chiave del nuovo standard per la trasformazione di modelli di OMG, QVT, e fa parte della famiglia di standard che compongono la Model Driven Architecture. I principali ideatori di OCL sono Jos Warmer e Anneke Kleppe.

OCL deriva da Syntropy. Il nucleo di OCL può essere descritto come un linguaggio mutuato dal calcolo dei predicati del primo ordine per l'espressione di condizioni logiche inerenti lo stato e le operazioni di oggetti in un contesto object-oriented. Con la potenza del calcolo dei predicati, OCL consente di descrivere invarianti che legano il valore degli attributi di una classe, precondizioni e postcondizioni delle operazioni, e via dicendo. A partire dalla versione 2.0 (che è quella inclusa nello standard UML), il linguaggio è stato arricchito di elementi che consentono di descrivere la semantica di operazioni di tipo interrogazione (query), ovvero prive di effetti collaterali.

Gran parte delle informazioni che si possono descrivere in OCL non sono esprimibili in nessun altro modo formale nel contesto di UML (ovvero non possono essere rappresentate dai diagrammi UML).

Descrizione

Invarianti semplici

In genere, in UML, un'espressione OCL è associata a una classe, e descrive proprietà degli oggetti istanze di quella classe. QUeste proprietà sono espresse in forma di condizioni che legano i valori degli attributi, dei parametri, dei valori tornati delle operazioni, e così via. Nel seguente esempio compare un'espressione che fa riferimento a un attributo:

context Persona inv:
età>=0

La parola chiave context</context> precede la dichiarazione della classe a cui questa regola OCL si applica. inv: specifica che questa particolare regola è una invariante, ovvero deve essere interpretata come una condizione che è sempre vera, per tutti gli oggetti di classe Persona. L'espressione che segue dichiara che l'età di una persona è sempre non negativa.

Nel caso in cui un attributo di una classe sia a sua volta un oggetto, è possibile riferirsi ai suoi attributi o metodi utilizzando la dot notation:

context Persona inv:
età>=0 and età<padre.età

Questa regola arricchisce la precedente con un ulteriore vincolo (legato da un "AND" booleano, che specifica che ogni persona è più giovane del proprio padre.

Invarianti su collezioni

Gli attributi con molteplicità maggiore di 1 (ovvero che rappresentano insiemi), detti collezioni, possono essere manipolati in OCL con un insieme di operatori specifici.

L'operatore ->size() fornisce la numerosità di una collezione. La seguente regola indica che ogni persona ha due genitori:

context Persona inv:
genitori->size()=2

L'operatore ->forAll corrisponde al quantificatore universale del calcolo dei predicati del primo ordine. La seguente regola rappresenta una sintesi delle precedenti, che specifica che ogni persona ha due genitori ed è più giovane di entrambi:

context Persona inv:
genitori->size()=2 and genitori->forAll(genitore:Persona | età<genitore.età)

Il quantificatore esistenziale è rappresentato dall'operatore ->exists. Questo operatore ritorna un valore booleano (vero o falso) a seconda che nella collezione esista almeno una istanza che soddisfa una certa condizione. La condizione viene espressa facendo riferimento agli attributi e i metodi dell'istanza da selezionare. Nel seguente esempio, si indica che deve esistere un genitore il cui sesso è maschile, e uno il cui sesso è femminile.

context Persona inv:
genitori->size()=2 and genitori->exists(sesso=m) and genitori->exists(sesso=f)

L'operatore ->select ha una sintassi analoga all'exists->; anziché produrre un valore booleano, questo operatore produce una collezione (la collezione di tutte le istanze che soddisfano la condizione specificata). Le due seguenti espressioni sono quindi equivalenti:

collezione->exists(condizione)
collezione->select(condizione)->size>0

L'operatore ->includes torna invece un valore booleano a seconda che una certa collezione includa o meno un determinato oggetto.

Precondizioni e postcondizioni

OCL consente di descrivere (parzialmente o completamente) la semantica di un'operazione di una classe per mezzo di precondizioni e postcondizioni.

Voci correlate

Bibliografia

Collegamenti esterni