2 
generale, [5] e [6], mentre alla fine del capitolo si focalizza l'attenzione sui concetti che 
interessano direttamente il meccanismo il progetto TIRAN[8].  
Nel capitolo quattro viene descritto nei primi quattro paragrafi come il progetto TIRAN si 
colloca nel panorama dei sistemi fault-tolerant [5], [6], [7]. Successivamente viene 
descritta l'applicazione nel  caso particolare dell'ENEL, [8]. 
Nel capitolo cinque in ultimo vengono analizzate le specifiche della DS indicate nei 
documenti ufficiali di TIRAN, in particolare in [8], [9] e [10], rispetto le quali  sono poi 
fatte alcune ipotesi semplificative. 
Allo scopo di fornire un supporto decisionale alla progettazione sono sviluppati quattro 
modelli del meccanismo di sincronizzazione che sono descritti prima attraverso l'UML e 
poi sono formalizzati con le SWN. 
Per ogni modello sono calcolati degli indici di prestazione sia in presenza sia in assenza 
di errori nel sistema in base ai quali è poi svolta un'analisi qualitativa confrontando le 
prestazioni dei quattro modelli. 
Concludiamo facendo un'osservazione sul linguaggio utilizzato. Si noterà che in tutta la 
tesi sono molte le parole in lingua inglese, questo fatto non è casuale ma dipende da una 
precisa scelta. Molti termini non sono stati tradotti per due motivi: il primo è per 
permettere una corrispondenza immediata con la bibliografia, il secondo è che non 
sempre esiste una precisa traduzione italiana. Ad esempio il termine dependability in 
italiano può essere tradotto con "fidatezza" ma il suo significato è piuttosto complesso e 
si è quindi preferito spiegarne il significato senza tradurre il termine.  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3 
Capitolo 1. 
 
Introduzione all'Unified Modeling Language 
 (UML).  
 
 
La progettazione di sistemi software si è sempre avvalsa di diverse tecniche di 
rappresentazione che utilizzano diversi linguaggi a seconda di quali aspetti si vogliano 
descrivere. L'Unified Modeling Language nasce allo scopo di fornire un unico linguaggio 
che permetta di esprimere qualunque aspetto del progetto.  
In questo capitolo vengono descritti gli elementi principali dell'UML.  
La bibliografia di riferimento è l'[1], un breve saggio di introduzione agli aspetti 
fondamentali dell'UML, ed il [2] che è invece la guida completa aggiornata al giugno 
1999. 
 
1.1  Cos'è l' UML. 
 
L'ULM fa parte di un metodo per l'analisi a la progettazione Object-Oriented nato alla 
fine degli anni '80. Un metodo é formato da due parti: un linguaggio per la modellazione 
(modeling language) e un processo (process). 
Modeling Language. 
L'ULM é appunto un linguaggio (prevalentemente grafico) per esprimere progetti mentre 
i processi sono delle regole (variabili a seconda del progetto) da seguire per la 
realizzazione dei progetti stessi. 
Allo stato attuale l'UML é formato da una notazione e da un meta-modello. 
Notation e Meta-model. 
La notazione é la struttura grafica, la sintassi del modello. Ad esempio la notazione che 
riguarda il diagramma di classe definisce come siano rappresentati i concetti, quali le 
associazioni, le classi e la molteplicità. I concetti vanno quindi opportunamente definiti. 
In generale una definizione rigorosa va a discapito dell'utilità del metodo. Nel caso di 
metodi OO un modo per avere maggior rigore senza perdere in utilità é definire un meta-
modello. 
Il meta-modello é un diagramma, generalmente un diagramma di classi che definisce la 
notazione.  
 
Diamo ora una descrizione del processo generale per la realizzazione di un certo progetto 
in UML. Teniamo però conto che l'ULM può essere associato ad un qualunque processo 
e che la scelta del tipo di processo dipende dal progetto. 
Possiamo individuare quattro fasi principali nel processo: 
Inception->Elaboration->Costruction->Transition. 
(Inizio)  (Elaborazione)  (Costruzione)   (Transizione) 
La prima cosa da osservare é che il processo é iterativo; il software non é rilasciato in un 
sol colpo passando dalla fase di elaborazione a quella di transizione. La fase di 
costruzione consiste in diverse iterazioni in ognuna delle quali si realizza solo una parte 
del progetto, si testa, eventualmente s’integra e in fine la si passa ad un'altra iterazione. 
Inception. 
4 
Si realizza ideando un progetto, ad esempio la commessa di un cliente per realizzare un 
catalogo su web. 
Elaboration. 
Conoscendo la richiesta del committente in questa fase bisogna analizzare il problema 
rispondendo a tre domande. 
1) Che cosa ci é stato chiesto di realizzare? 
2) Come abbiamo intenzione di costruirlo? 
3) Che tecnologia abbiamo intenzione di usare? 
Nel rispondere a queste domande bisogna prestare attenzione ad alcuni rischi quali ad 
esempio dare delle risposte sbagliate. Può capitare infatti di realizzare un sistema che non 
soddisfi le specifiche richieste dal committente (Requirement risk). Oppure si potrebbe 
scegliere una tecnologia per la realizzazione in cui non si ha abbastanza esperienza 
(Tecnological risk). 
Evidentemente le specifiche del progetto sono il punto di partenza dell'elaboration. 
L'ULM a questo riguardo é uno strumento adatto a descriverle attraverso i casi d'uso (use 
cases). I casi d'uso sono le interazioni tra il sistema e un utilizzatore (ad esempio la 
richiesta ad un programma gestore testi di stampare un testo in grassetto).  
Un altro elemento importante dell'UML é il domain model. Con dominio del modello 
intendiamo un qualunque modello il cui soggetto primario è il "mondo" che il sistema sta 
supportando a qualunque livello sia lo stato del processo di sviluppo. Mettendo insieme i 
due tipi di informazione, use case e domain model, si può costruire un modello del 
progetto facilmente generalizzabile e quindi riutilizzabile per altri progetti. Per la 
costruzione del modello del dominio sono particolarmente utili alcun tipi di diagrammi i 
quali mettono in luce aspetti diversi: class diagrams, activity diagrams, interaction 
diagrams.  
La costruzione del domain model va pensata come uno scheletro iniziale arricchito 
successivamente  a mano a mano che si ha una maggiore comprensione del problema e 
non come la costruzione di un modello di alto livello perché in questo modo sì perdono 
troppi particolari. 
Construction. 
Durante questa fase si costruisce il sistema con una serie di iterazioni ognuna delle quali 
é un  mini progetto. Ogni passaggio é iterativo nel senso che richiede una riscrittura 
parziale del codice per renderlo più flessibile ed efficiente. 
Anche in questa fase é utile l'ULM attraverso i class e activity diagrams. 
Transition. 
In questa fase si fa dell'ottimizzazione che riduce la chiarezza e la lunghezza del codice 
per     incrementarne le performance. Inoltre sempre in questa fase si fissano i bugs. 
 
1.2 Use Case. 
 
Use case: tipica interazione tra un utilizzatore ed un computer (per esempio la richiesta ad 
un gestore testi di scrivere in grassetto). 
Proprietà degli use case sono: 1) un use case "cattura" una qualche funzione visibile 
all'utilizzatore; 
2) un use case può essere grande o piccolo; 
3) un use case  ha una discrete utilità per l'utilizzatore. 
In questo modo si vede che per identificare un use case é sufficiente parlare con 
l'utilizzatore e discutere con lui delle cose che vuole fare con il sistema. Si prende poi 
ogni singola cosa gli si assegna un nome ed una breve descrizione. Durante la fase di 
elaborazione non serve altro, i dettagli si aggiungeranno a mano a mano che il progetto 
5 
avanza. È necessario osservare che non sempre le interazioni con il sistema e l'obiettivo 
dell'utilizzatore coincidono. Se ad esempio consideriamo un word processor le 
funzionalità di cambiare stile e di muovere uno stile da un documento ad un altro possono 
essere interpretate come use cases ma lo scopo dell'utilizzatore potrebbe essere descritto 
come: realizzare documenti con lo stesso formato. Da quest’esempio si può anche 
osservare che un approccio ai problemi che descriva direttamente le interazioni con il 
sistema escludendo o analizzando troppo superficialmente gli scopi dell'utilizzatore può 
far sì che si perdano di vista eventuali soluzioni alternative al problema. 
 
1.2.1 Use case diagrams. 
 
Descrivo ora gli elementi che compaiono in questi diagrammi: actors, extends, uses. 
Actor. É il ruolo giocato dall'utilizzatore rispetto il sistema. Ogni actor può richiedere più 
use cases e viceversa ogni use case può avere più actors. L'identificazione degli actors è 
utile per identificare gli use cases specie se il sistema è molto grande e complesso. 
Ci sono diversi modi di definire gli actors ognuno dei quali mette in luce problemi diversi 
noi ci atterremo alla seguente definizione: gli actor sono tutto ciò che necessita degli use 
case. Se ad esempio un sistema bancario ogni notte genera un file che è successivamente 
utilizzato da un programma che lo usa per aggiornare i conti correnti allora il programma 
è un actor in quanto è colui che necessita della realizzazione di quel file da parte del 
sistema. 
Un esempio di diversa definizione di actor è la seguente: in caso di interazioni esterne il 
sistema esterno è considerato actor solo se è lui ad iniziare il contatto. 
Una caratteristica importante da osservare è che gli actors non coincidono con gli 
utilizzatori. Se ad esempio consideriamo un sistema che può essere configurato per 
utilizzatori diversi ogni utilizzatore può essere identificato da una lista di actors che è 
utilizzata per determinare quali use cases quell'utilizzatore può richiedere. Un altro 
motivo per cui è utile individuare gli actors è il caso in cui ci sia la necessità di assegnare 
delle risorse a domande in competizione. In questo caso infatti è particolarmente utile 
sapere chi necessita e di che cosa. 
Diciamo in fine che non è detto che l'individuazione di tutti gli actors permetta di 
individuare tutti gli use cases. 
Uses ed Extends. Nei diagrammi degli use cases oltre ai legami tra actors e use cases vi 
sono altri due tipi di legami che rappresentano relazioni tra use cases. 
Extends: si ha quando si hanno due use cases simili ma uno fa qualche cosa in più 
dell'altro. Ad esempio il caso dell'addebito di un assegno ha modalità diverse a seconda 
che con tale addebito il conto vada in rosso oppure no. Vediamo alcune regole di base per 
identificare i rapporti extends: 
1) identificare prima l'use case "normale" (addebito dell'assegno con sufficiente liquidità 
sul       conto); 
2) per ogni passo svolto nell'use case "normale" bisogna chiedersi: "cosa può andare 
storto" e "come si potrebbe risolvere differentemente"; 
3) disegnare tutte le variazioni come estensioni di un dato use case. 
Uses: sono relazioni tra use cases che occorrono quando si ha un comportamento che è 
ripetuto identico in diversi use cases e non si vuole farne copia per ognuno. È da 
osservare che uses ed extends sono simili perché entrambe si riferiscono a comportamenti 
comuni di use cases diversi ma nel caso degli extends gli actors hanno una relazione con 
l'use case che viene esteso mentre per gli uses non è detto che ci sia un actor in relazione 
all'use case da cui la relazione uses discende. Inoltre un actor che richieda un use case 
extends è supposto che richieda anche l'esecuzione di tutti gli use cases da cui l'extends 
6 
discende mentre l'esecuzione di un use case di una relazione uses richiede solo 
l'esecuzione dell'use case da cui discende direttamente. 
Scenario. Si riferisce ad un singolo cammino all'interno di un use case individuato 
attraverso la particolarizzazione delle condizioni descritte da quell'use case. Ad esempio 
consideriamo l'ordinazione della spesa. Possiamo considerare un singolo use case con 
diversi scenari: 
1) trovo tutto ciò che voglio e ho soldi a sufficienza; 
2) non c'è  tutto ciò che voglio anche se ho soldi a sufficienza; 
3) trovo tutto ciò che voglio ma la carta di credito viene rifiutata; 
ecc.... 
  
1.3  Class Diagrams. 
 
Un class diagrams descrive il tipo di oggetti del sistema che si sta analizzando e quali 
relazioni statiche esistono tra loro. 
Abbiamo due tipi di relazioni: 
association (un commerciante può affittare un certo numero di videocassette); 
subtypes (un'infermiera è un tipo di persona).  
I class diagrams inoltre forniscono anche altre informazioni quali gli attributi, le 
operazioni e una descrizione del modo in cui gli oggetti sono connessi. 
Ci sono tre prospettive per disegnare un class diagram. 
• Conceptual (Concettuale): in questa prospettiva si disegna un diagramma che 
rappresenta i concetti nel dominio che stiamo studiando. In una prospettiva concettuale, 
pur essendo i concetti correlati alle classi che li implementano, il modello dovrebbe 
essere disegnato con poco o addirittura senza riguardo per il software che lo implementa. 
• Specification (Descrittiva): in questa prospettiva si guarda invece alle interfacce del 
software, il modo cioè con cui il software comunica con l’esterno. Osserviamo quindi i 
tipi più che le classi
6
.  
• Implemantation (Implementativa): è la prospettiva più usata e focalizza l'attenzione 
sulle classi. 
Sapere la prospettiva in cui ci si vuole porre è importante sia per la progettazione sia per 
l'interpretazione dei class diagrams. Descriviamo ora le notazioni. 
Association: rappresentano relazioni di tipo concettuale tra classi. Nell'esempio riportato 
in figura 1.1 il diagramma indica che un Order deve venire da un singolo Customer e che 
un Customer può fare più Order ognuno dei quali ha diverse Order Line, in particolare 
una per ogni prodotto richiesto. 
Ogni associazione ha due funzioni ognuna delle quali è una direzione d’associazione tra 
classi; così l'associazione tra Order e Customer contiene in realtà due associazioni, una da 
Order a Customer e l'altra da Customer ad Order. La direzione d’associazione è 
particolarmente significativa se messa in relazione al concetto di molteplicità che viene 
indicata nei diagrammi con il simbolo * o con dei numeri che sono posti al punto d’arrivo 
dell'associazione. Ad esempio l'associazione tra Customer e Order è marcata con il 
simbolo " * " per l'associazione Customer->Order; con tale simbolo s’indica che un 
Customer può essere associato a più Orders (un cliente può evidentemente fare più 
ordini), in particolare con * s’indica la possibilità teorica di fare infiniti Order da parte del 
Customer. Sull'associazione Order->Customer invece c'è un uno il quale indica che ogni 
                                                 
6
 Nei linguaggi OO la parola classe spesso si riferisce sia all'interfaccia sia all'implementazione. 
7 
Order può essere associato ad un solo Customer. In generale la molteplicità è indicata con 
n..m dove n ed m sono gli estremi inferiore e superiore possibili. 
     
 
 
  
 
Order 
dateReceived 
isPrepaid 
number: String 
price: money 
dispatch() 
close() 
creditRating():String 
Customer  
name  
address 
Association 
* 
1 
Costraint 
Attributes 
Operations 
Class 
Generalization 
Order Line 
quantity: Integer  
price: Money  
isSatisfied: Boolean 
line  
items 
* 
* 
1 
* 
Product 
{if Order.customer.creditRating is  
"poor", then Orders.isPrepaid   
must be true} 
1 
{creditRating()==  
"poor"} 
sales rep 
0..1 
Employee 
Multiplicity:  
optional 
Multiplicity:  
Many-valued 
Multiplicity:  
mandatory 
Personal  
Customer 
creditCard# 
Corporate  
Customer 
remind()  
billForMonth(integer) 
contractName  
creditRating  
creditLimit 
Fig.1.1  
 
Passiamo ora alla prospettiva descrittiva. In questa prospettiva le associazioni 
rappresentano "responsabilità"; il fatto che ci sia un'associazione tra Customer e Order 
implica che ci sia uno o più metodi in Customer che mi dicano quali Order il Customer 
ha fatto ed implica anche che ci siano dei metodi in Order che mi permettano di 
identificare quale Customer ha fatto un certo Order. Queste responsabilità non dicono 
nulla su come devono essere strutturati i dati.  
8 
La prospettiva implementativa affronta invece proprio questo aspetto. L'esistenza di 
un'associazione tra classi implica, infatti, l'esistenza di puntatori indicanti le classi 
associate. Riferendoci al solito esempio il diagramma ci indica che Order deve avere un 
vettore di puntatori ad OrderLine e un puntatore a Customer. In questa prospettiva è poi 
possibile associare alle linee che rappresentano le associazioni tra classi la "Navigability" 
attraverso delle frecce. Ad esempio in figura 1.2 
 
 
 
Order 
Customer 
* 
1 
Navigability 
Fig.1.2 
 
 
la navigabilità significa che Order ha la responsabilità di indicare il proprio Customer e 
quindi dovrà contenere un puntatore a Customer mentre Customer non ha l'obbligo di 
contenere alcun puntatore ad Order. 
Attributes. Nella prospettiva concettuale l'attributo "name" di Customer indica 
semplicemente che i Customer hanno un nome. Dal punto di vista descrittivo invece 
significa che Customer è in grado di comunicare il suo nome ed è in grado di settarlo. In 
fine in una prospettiva implementativa significa che Customer ha un campo (detto anche 
istanza di variabile o dato membro) per il suo nome. 
Operations. Corrispondono ai metodi che operano su di una classe. A livello descrittivo 
corrispondono alle operazioni pubbliche su un tipo. Implementativamente può essere 
utile indicare se le operazioni siano private o protette, in questo caso si fa seguire 
l'operazione da uno dei seguenti simboli: 
+ per public; # per protected; - per private. 
Dal punto di vista concettuale le operazioni non dovrebbero descrivere l'interfaccia di una 
classe ma piuttosto le sue responsabilità principali. 
Distinguiamo poi le operazioni in due gruppi a seconda che cambino o no lo stato di una 
classe. 
Definiamo Query Operations un'operazione che prende un valore di una classe senza 
cambiare lo stato osservabile della classe; diciamo invece Modifiers un'operazione che 
cambi lo stato osservabile della classe. Consideriamo per esempio un oggetto 
ContoCorrente che calcoli il bilancio di un conto corrente in funzione delle entrate/uscite 
attraverso l'operazione "bilancio". Supponiamo poi che ControCorrente memorizzi i 
bilanci in un certo campo. La prima volta che viene chiamato l'operazione "bilancio" il 
campo dove memorizzare il bilancio è vuoto e "bilancio" ne modifica lo stato 
memorizzandoci appunto i vari bilanci calcolati. Abbiamo così che qualunque richiesta 
d’informazioni sui bilanci del ContoCorrente (query) non modifica lo stato di 
ContoCorrente mentre il metodo "bilancio" sì e quindi è un modifiers. 
Vi sono poi i Setting Methods e i Getting Methods. 
I setting methods si limitano ad inserire i valori nei campi mentre i getting methods li 
ritornano ed entrambe non fanno altro. È da osservare che sia le queryes sia i modifiers 
possono essere setting o getting methods. 
9 
Un'ultima distinzione da fare è tra operazioni e metodi. Mentre l'operazione è qualcosa 
chiamato su un oggetto il metodo è il corpo della procedura. Questi due concetti possono 
coincidere ma quando si ha a che fare con polimorfismi no, se, infatti, si ha una classe 
con un operazione che chiamo f e due sottoclassi ognuna delle quali sovrascrive 
l'operazione f allora abbiamo un'operazione e due metodi. 
Generalization. Un tipico esempio di generalizzazione è quello del Customer indicato 
figura 1.1.Un cliente, infatti, può essere sia un individuo sia un'azienda. Le similarità 
possono essere poste in un sopratipo che abbiamo chiamato Customer, mentre delle 
particolarità si tiene conto in due sottoclassi distinte (indicate anche come sottotipi) che 
abbiamo chiamato PersonalCustomer e CorporateCustomer. 
Anche la generalizzazione è soggetta ad interpretazioni differenti a seconda della 
prospettiva. 
Concettualmente possiamo dire che CorporateCustomer è un sottotipo di Customer se 
tutte le istanze di CorporateCustomer sono anche istanze di Customer. In generale dire 
che Corp.Cust. è sottotipo di Customer significa che qualunque cosa si dica per Customer 
essa è valida anche per Corp.Cust. 
Dal punto di vista descrittivo invece la generalizzazione indica che l'interfaccia del 
sottotipo deve includere tutti gli elementi provenienti dall'interfaccia del sopratipo. Un 
altro modo di interpretare questo fenomeno in questa prospettiva è quello che si richiama 
al concetto di sostituibilità. Secondo questo concetto dovrei essere in grado di sostituire 
un sottotipo con qualunque altro sottotipo che richieda lo stesso sopratipo. 
Essenzialmente questo si traduce nel fatto che se scrivo del codice per il tipo Customer 
allora esso dovrà funzionare ugualmente bene per ogni suo sottotipo. 
Implementativamente invece il concetto di generalizzazione si traduce in quello 
d’ereditarietà tra classi. Per comprendere la differenza tra il punto di vista descrittivo e 
quello implementativo dobbiamo dire che mentre nel primo ci si riferisce a sottotipi ed 
ereditarietà tra interfacce nel secondo ci si riferisce a sottoclassi ed ereditarietà delle 
implementazioni.     
Costraint Rules. Dal grafico considerato emergono immediatamente delle limitazioni o 
caratteristiche peculiari del sistema cosi modellato. Una caratteristica è che ogni Order ha 
un proprio Customer e quindi se due clienti vogliono ordinare 50 cappelli devono fare 
due ordini separati, un'altra caratteristica è che le Line Item sono considerate una per ogni 
oggetto ordinato e ciò fa sì che non si possa pensare ad un ordine di 10 cappelli bianchi, 
neri, rossi ma ad un ordine di 10 cappelli bianchi, 10 cappelli neri, 10 cappelli rossi. 
Oppure ancora dal grafico si vede che mentre il Corp.Cust. gode di credito il Pers.Cust. 
no. Nell'UML non esiste una regola fissa per indicare questo tipo di specifiche, una 
possibilità e quella di indicarle tra parentesi graffe. 
Stereotypes. Il significato di stereotipo è una sorta di classificazione ad alto livello di un 
oggetto che dà qualche indicazione di quali responsabilità abbia l’oggetto. Un esempio 
chiarificatore è la differenza tra controller e coordinator. Spesso progettando con 
linguaggi OO si può avere a che fare con una classe che sembra fare tutto. In tal caso 
significa che si è fatta una progettazione di cattiva qualità perché significa avere un 
controller molto complesso e quindi difficile da gestire. Dando più responsabilità agli 
altri oggetti del sistema si ottiene l’effetto di semplificare il controller il quale diventa un 
coordinator in quanto potrà limitare la sua attività al controllo della sequenza dei task 
mentre la responsabilità di come questi siano inviati è demandata ad altri oggetti. Uno 
stereotipo in genere è posto tra “ ”. 
Aggregation e Composition. Il problema di definire le aggregazioni sta nel chiarire la 
differenza tra aggregazione e associazione. Purtroppo non c’è ancora un’unica 
definizione accettata da tutte le metodologie. In generale possiamo dire che 
10 
un’aggregazione è parte di una relazione; ad esempio è come dire che un’auto ha un 
motore e le ruote come sue parti.  
Nell’insieme delle aggregazioni l’U.M.L. prevede un tipo di aggregazione detta 
composizione. In una composizione un oggetto parte può appartenere ad un solo tutto, 
inoltre ci si aspetta che le parti vivano o muoiano con il tutto. Qualunque cancellazione 
del tutto deve ricadere anche sulle parti. 
Vediamo l’esempio di figura 1.3: 
 
 
 
 
 
  
 
 
 
 
 
 
Fig1.3 
 
Un’istanza di Punto può essere o un poligono o un cerchio ma non entrambe. Un’istanza 
di stile può invece essere condivisa da più Poligoni o Cerchi. Dal grafico si ricava anche 
che la cancellazione di Poligono o Cerchio cancella anche i Punti associati ma non Stile. 
Derived association e derived attributes. Associazioni  ed attributi derivati sono quelli 
che possono essere ottenuti rispettivamente da altre associazioni ed altri attributi in un 
class diagram.  
Ad esempio l’attributo età di un oggetto Persona può essere ottenuto conoscendo la data 
di nascita.  
Anche per associazioni ed attributi è importante la prospettiva.  
Nel caso della prospettiva descrittiva le caratterizzazioni derivate indicano un forte 
legame tra i valori e non una semplice descrizione di cosa è stato calcolato e cosa sia 
invece memorizzato come dato iniziale. Consideriamo la seguente classe: 
 
 
 
 
 
 
 
 
 
Questo diagramma descrittivamente suggerisce che start ed end siano dati e duration sia 
calcolato. In realtà un programmatore può implementare questa classe in qualunque modo 
purché mantenga il funzionamento esterno della classe. Potrebbe infatti calcolare end 
conoscendo start e duration. Dal punto di vista concettuale l’indicatore di derivato è utile 
per ricordare dove queste derivazioni esistono. 
 
1.4  Package Diagrams. 
Poligono 
Stile 
colore 
è pieno. 
Cerchio 
raggio 
Punto 
1 
1 
1 
* *
3..* 
Composizione 
Aggregazione 
Time Period 
 
start:Date 
end:Date 
/duration:Date 
11 
 
Con Package ci si riferisce ad un meccanismo che permette di raggruppare le classi in 
unità di più alto livello dette appunto Package. L’idea di package può essere applicata a 
qualunque elemento del modello e non solo sulle classi. 
Dependency. Esiste una dipendenza tra due elementi se cambiamenti alla definizione di 
uno può causare cambiamenti nell’altro. Tra classi la dipendenza può esistere per vari 
motivi, si pensi per esempio ad una classe che abbia un’altra classe come parte dei suoi 
dati o ad una classe che ne nomini un’altra come parametro di un’operazione.  
Diciamo poi che esiste una dipendenza tra packages se esiste una dipendenza tra due 
qualunque classi appartenenti a package distinti. E da osservare che dipendenze e 
package sono solo casi particolari di class diagram. La loro utilità sta nel fatto che 
permettono di spezzare sistemi di grandi dimensioni in sistemi più piccoli e quindi più 
gestibili. 
 
A 
B 
C 
Dominio 
D 
E 
F 
G 
H 
L 
(globali) 
Comuni 
Fig.1.4 
 
 
Una prima caratteristica dei package è che le dipendenze non sono transitive come ad 
esempio la relazione di amicizia tra persone: se A è amico di B e B è amico di C non è 
detto che A sia amico di C. Questa proprietà si traduce ad esempio nel caso dei package 
di figura 1.4 nel fatto che un cambiamento in una classe del package L non influenza le 
classi del package E ma solo quelle del package C. Il difetto di avere una dipendenza per 
12 
cui vale la proprietà transitiva è che diventa difficile limitare lo scope (il dominio) dei 
cambiamenti nella compilazione del codice. 
Vediamo ora cosa significa disegnare una dipendenza ad un package che contiene altri 
packages: ci sono due convenzioni, la prima afferma che la dipendenza tra il package A 
ed il package B con B contenente dei subpackages dà la visibilità di tutti i subpackages e 
dei loro contenuti. La seconda convenzione invece dice che sono visibili solo gli elementi 
presenti nel package contenente e non anche quelli nel package contenuto. Noi 
considereremo la prima convenzione che chiameremo convenzione di trasparenza. 
L’utilità dei package non è nel dare direttamente un modo per ridurre le dipendenze nel 
modello che si sta progettando ma nel mostrare quante e quali siano che è il punto di 
partenza per ridurne il numero. 
Torniamo ora all’esempio riportato in figura 1.4. In questo esempio c’è un package che 
ho chiamato Dominio che contiene a sua volta altri due packages D ed E. L’utilità di 
questo raggruppamento sta evidentemente nel fatto che posso disegnare dipendenze da e 
verso Dominio senza dover disegnare ogni singola dipendenza di D ed E. Un’altra 
caratteristica di questo esempio è di avere un package segnato come “(globale)”, significa 
che tutti i package del sistema hanno una dipendenza da Comune. 
 Come suggerisce il grafico, le generalizzazioni sono possibili anche con i package e 
vanno interpretate in termini di interfaccia; nell’esempio dato il package F è 
particolarizzato in G ed H e questo vuole dire che F può usare o l’interfaccia G o 
l’interfaccia H.  
E’ poi possibile  marcare con “{ astratto} ” i package indicando così che quel package 
definisce un’interfaccia che è implementata da packages più specifici.  
Osserviamo in fine che le generalizzazioni implicano l’esistenza di una dipendenza del 
sopratipo dal sottotipo e viceversa.      
 
1.5  State Diagrams. 
 
 Gli state diagrams permettono di descrivere tutti i possibili stati che un particolare 
oggetto può assumere e come l’oggetto cambia di stato in base al realizzarsi di particolari 
eventi. 
In figura 1.5 è rappresentato lo state diagram di un ordine di fornitura. 
Si inizia dallo start dal quale si ha una transizione nello stato di Checking, questa 
transizione è etichettata con la scritta “/get first item”. In generale la le etichette delle 
transizioni prevedono tre parti ognuna delle quali è opzionale: Event [Guard] / Action, 
nel nostro caso abbiamo solo l’action “get first item”. Una volta eseguita l’azione si entra 
nello stato Checking, a tale stato è associata un’attività che è indicata con la seguente 
sintassi: do / activity ed in questo caso è chiamata “check item”. Sebbene sia  l’activity 
che l’action siano dei processi la loro differenza non si limita al fatto che l’una si riferisce 
ad uno stato mentre l’altra ad una transizione.  
L’action, oltre ad essere associata alle transizioni è considerato un processo molto veloce 
e non interrompibile. 
E’ da notare che la definizione di “veloce” dipende dal sistema che stiamo descrivendo, 
Nel caso di sistemi real-time “veloce” potrebbe essere l’esecuzione di poche istruzioni di 
macchina, mentre per sistemi informativi potrebbe essere alcuni secondi. 
 L’activity invece, oltre ad essere  associata agli stati, può richiedere molto tempo per 
essere eseguita e può essere interrotta da un evento. 
 
13 
 
 
Checking 
do/check 
item 
Dispatching 
do/initiate 
delivery  
Waiting Delivered 
delivered 
/get first item 
[All item checked && all 
item available] 
[Not all items checked 
/get next item ] 
[All items checked && 
some items not in stock] 
Item recived 
[some items not in 
stock] 
Item recieved 
[all items available] 
state 
transition 
activity 
start 
self 
transition 
Fig1.5 
 
Se una transizione non è etichettata con alcun evento significa che tale transizione 
avverrà non appena sarà completata l’attività associata al rispettivo stato. Nel nostro caso 
non appena verrà completata l’attività associata allo stato di Checking si passerà o nello 
stato di Dispatching o nello stato diWaiting. La scelta tra le tre transizioni verrà effettuata 
attraverso le guard indicate tra parentesi quadre. 
Una guard è una condizione logica che ritorna un valore di “vero” o “falso”, la rispettiva 
transizione occorre solo se la guard ritorna il valore “vero”. Un’altra caratteristica delle 
guard è che sono mutuamente esclusive per un dato evento, questo vuole dire che 
supponendo di essere in uno stato dal quale si può uscire attraverso più transizioni, solo 
una può essere attivata dal realizzarsi di un evento. 
Un evento, in generale, è il realizzarsi di condizioni che possono cambiare lo stato 
dell’oggetto, possono cioè fare scattare una transizione di stato. Gli eventi possono essere 
di diversi tipi, non necessariamente esclusivi tra loro: 
•  una  condizione prestabilita (descritta da un’espressione Booleana) diventa vera, 
producendo così un’istanza di cambiamento di stato. L’evento occorre ogniqualvolta il 
valore dell’espressione Booleana cambia da falso a vero. E’ da notare che il 
comportamento descritto è diverso da quello delle guard. Una guard è valutata solo una 
volta per ogni volta che si realizza il corrispondente evento, se è falsa la transizione non 
scatta e l’evento è perso; 
•  la ricezione da parte di un oggetto di un esplicito segnale da un altro oggetto  definisce 
una istanza detta signal event ed è indicata etichettando l’arco di transizione con il nome 
dell’evento; 
•  la ricezione di una chiamata per un’operazione, implementata come transizione, da 
parte di un oggetto rappresenta un’istanza detta call event. E’ da osservare che non c’è 
nessuna differenza di notazione tra i signal event e i call event, la differenza è espressa in 
modo esplicito solo nella definizione della rispettiva classe; 
14 
•  il passaggio di un determinato intervallo di tempo dopo un evento designato, o 
l’occorrenza di un determinato istante  è detto time event. 
Nel nostro esempio si può uscire dallo stato di Checking solo se è stato verificato che tutti 
gli oggetti richiesti sono disponibili ([All items checked && all items available]), in 
questo caso si passerà nello  stato Dispatching. Se invece si sono controllati tutti gli 
oggetti ed è stato verificato che alcuni non sono disponibili allora si passerà nello stato 
Waiting. In fine se non tutti gli oggetti sono stati controllati si passa all’oggetto 
successivo attraverso l’action /get next item e si rientra nello stato di Checking. 
Lo stato Waiting è uno stato in cui si attende che tutti gli oggetti mancanti arrivino, tale 
stato non ha un’activity, questo significa che l’ordine semplicemente attende che si 
realizzi l’evento che un oggetto richiesto sia disponibile. Ogni volta che si rende 
disponibile un oggetto vengono valutate le due guards che permettono l’uscita da tale 
stato, se tutti gli oggetti richiesti sono disponibili allora si passa nello stato Dispatching, 
se invece ne manca ancora qualcuno si ritorna in Waiting. 
Una volta entrati nello stato di Dispatching inizia l’attività do/initiate delivery. Per uscire 
da questo stato c’è una sola transizione etichettata dall’evento delivered (che si suppone 
essere definito altrove), questo significa che la transizione dell’ordine dallo stato di 
Dispatching allo stato di Delivered potrà occorrere solo se si realizza l’evento delivered e 
non per il completamento dell’attività initiate delivery. 
Supponiamo ora di voler descrivere la possibilità che un ordine sia cancellato trovandosi 
in uno stato qualsiasi, potrebbe accadere ad esempio che venga ordinato un oggetto che 
non può rendersi disponibile e quindi l’ordine permarrebbe nello stato Waiting 
all’infinito, o più semplicemente chi ha fatto l’ordine non può pagare e quindi non si 
vuole consegnare la merce, ecc… 
 Per risolvere il problema o si aggiunge un nuovo stato che chiamiamo Cancelled 
raggiungibile da tutti gli altri attraverso transizioni etichettate dall’evento cancelled, 
oppure si può costruire un Superstate come indicato in figura 1.6. Gli stati che sono 
inclusi in un superstate  ereditano qualunque transizione del superstate.  
Vi sono poi due eventi  che non compaiono nel nostro esempio ma sono di una certa 
importanza e precisamente entry ed exit. Qualunque azione che sia etichettata con entry 
viene eseguita qualunque sia lo stato in cui si entra attraverso la corrispondente 
transizione.  L’azione associata all’evento exit viene eseguita qualunque sia la transizione 
che permette di cambiare stato. 
15 
 
 
Checking 
do/check 
item 
Dispatching 
do/initiate 
delivery  
Waiting 
Delivered 
delivered 
/get first item 
[All item checked && all 
item available] 
[Not all items checked 
/get next item ] 
[All items checked && 
some items not in stock] 
Item recived 
[some items not in 
stock] 
Item recieved 
[all items available] 
state 
transition 
activity 
start 
self 
transition 
Fig1.6 
Active 
Superstate name 
Cancelled 
cancelled 
  
 
1.6  Concurrent State Diagrams. 
 
Nell’esempio di figura 1.6 abbiamo analizzato gli stati che un ordine può raggiungere in 
base alla disponibilità degli oggetti richiesti, ma vi sono altri punti di vista 
complementari. Consideriamo ora lo stesso problema dal punto di vista però 
dell’autorizzazione al pagamento, vogliamo descrivere il fatto che se un ordine non 
riceve l’autorizzazione al pagamento deve essere cancellato. Lo state diagram 
corrispondente all’eventuale autorizzazione, descritto in figura 1.7, è di facile 
interpretazione, si inizia con un’attività di controllo nello stato Authorizing, terminata 
tale attività se il controllo ha dato esito positivo ([payment OK]) si passa nello stato di 
Authorized e quindi in quello di Delivered non appena si realizza l’evento deliver, se 
invece c’è stato un esito negativo del controllo ([payment not OK]) si entra nello stato di 
Rejected. 
L’oggetto Ordine che stiamo descrivendo presenta due comportamenti di cui tenere 
conto.