Introduzione
Gli
elementi che costituiscono un qualsivoglia sistema non vengono assemblati
semplicemente per persistere in una posizione di riposo, bensì interagiscono
tra loro scambiandosi messaggi al fine di raggiungere uno scopo ben preciso.
In ogni sistema, dunque, ciascuna componente svolge un determinato compito
ed interagisce con altri oggetti al fine di produrre un risultato “globale”,
una funzionalità che va ben oltre la “semplice” somma dei risultati
prodotti dai singoli oggetti.
Mentre,
l’aspetto statico di un sistema è documentabile per mezzo dei class
ed object diagram, per ciò che concerne il comportamento dinamico,
l’UML fornisce quattro tipologie di diagrammi: statechart, sequence, collaboration
ed activity. Anche gli use case permettono di illustrare aspetti dinamici
del sistema, da un punto di vista funzionale e quindi, con un livello di
astrazione molto elevato
Il
Sequence diagram descrive come gli oggetti interagiscono temporalmente
tra loro. Viene quindi visualizzata la sequenza di messaggi che gli oggetti
inviano e ricevono al fine di realizzare una determinata funzione. In questo
tipo di diagrammi, l’attenzione viene focalizza sul fattore tempo.
Il
Collaboration Diagram, come il precedente, illustra l’interazione tra oggetti,
però, in questo caso, l’attenzione viene spostata dal fattore tempo
al fattore spazio. Ciò equivale a dire che si evidenzia l’organizzazione
strutturale degli oggetti che si scambiano i messaggi.
L’Activity
Digram rappresenta un ulteriore istanza dei digrammi di interazione in
cui l’attenzione viene centrata sulle attività da svolgere: non
a caso presenta molte analogie con i famosissimi Flow Chart. Negli Activity
Diagram, un oggetto interagisce con un altro realizzando determinate attività.
Lo
statechart diagram, in sintesi, descrive un automa a stati finiti, costituito
da stati, transizioni, eventi ed attività. In altre parole, mostra
in quali stati un oggetto può transitare durante il suo ciclo di
vita: dalla sua istanziazione alla relativa distruzione. Per ogni stato
viene descritto il relativo comportamento, gli eventi che ne determinano
l’entrata e l’uscita, ecc. Questo tipologia di diagramma evidenzia il comportamento
di un oggetto in funzione di un insieme ordinato di eventi.
Poiché
tutti i diagrammi testé presentati permettono di modellare/documentare
un’interazione, nell’ambito della descrizione di ciascuna di esse, è
sufficiente (ed opportuno) utilizzare una sola tipologia di tali diagrammi.
Pertanto, di volta in volta, è necessario selezionare quale tipologia,
e quindi quale aspetto, permette di illustrare l’interazione con maggiore
chiarezza.
Tipicamente
si tende a preferire i Sequence Diagram, sia perché il fattore tempo
risulta più intuitivo, sia perché è possibile introdurli
fin dalle primissime fasi dell’analisi al fine di presentare degli “scenari”
di use case (consultare articolo [7]). Si preferisce ricorrere agli altri
quando il Sequence risulta troppo complicato e quindi poco leggibile.
Si
tenga presente che “una interazione ben strutturata è come un algoritmo
ben strutturato – efficiente, adattabile, e comprensibile- (Grady Booch).
Prima
di proseguire nell’analisi di dettaglio dei singoli diagrammi, si ritiene
opportuno procedere con l’illustrazione dei concetti che stanno alla base
di ogni interazione.
Concetti base
- Comunicazione tra oggetti
Un’interazione
è un comportamento che include lo scambio di messaggi tra un insieme
di oggetti al fine di produrre una determinata funzionalità. In
questo contesto, al termine “messaggio” non va attribuito un significato
strettamente testuale, esso è utilizzo per indicare una comunicazione
esplicita tra oggetti realizzata attraverso un qualsivoglia meccanismo.
Nella stragrande maggioranza dei casi si tratta di una semplice operazione
di invocazione di funzione (pardon metodo). Chiaramente, nulla vieta che
due oggetti comunichino effettivamente per mezzo di un vero e proprio scambio
di messaggi, effettuato attraverso un opportuno meccanismo di comunicazione,
nella stessa macchina o attraverso una rete (comunicazioni via Socket,
invocazione di metodi remoti: RPC, RMI, CORBA, ecc.).
Nel
linguaggio UML, una singola interazione tra oggetti, ossia lo scambio di
un messaggio, è rappresentato graficamente per mezzo di un segmento
che li unisce. In articolare si possono incontrare le seguenti tipologie
di messaggi:
-
SINCRONI:
questi tipi di messaggio permettono di realizzare una tipologia di comunicazione
indicata con la denominazione di “rendezvou”; si tratta di un meccanismo
che consente di sincronizzare l’esecuzione parallela di due o più
processi: un vero appuntamento virtuale. Ciò implica che la “procedura”
che gestisce il messaggio ricevuto deve concludersi prima che l’oggetto
“mittente” possa proseguire la relativa esecuzione. Lo scambio sincrono
di messaggi tra oggetti attivi, inizia con l’oggetto chiamante che esegue
un’operazione di spedizione di un messaggio e si pone in uno stato di attesa.
L’oggetto chiamato accetta l’invocazione, esegue le relative elaborazioni
e quindi invia un messaggio all’oggetto chiamante, eventuale corredato
con un risultato di ritorno. A questo punto i due oggetti possono proseguire
nella loro evoluzione indipendentemente gli uni dagli altri. Chiaramente,
si tratta di una semplice schematizzazione che non tiene conto di problematiche
più complesse come la perdita di messaggi, partial failure, ecc..
-
ASINCRONI:
il meccanismo di comunicazione realizzato da questa tipologia di messaggi
viene spesso indicato con la denominazione di “mailbox”, in quanto è
caratterizzato dall’assenza di un esplicito messaggio di ritorno all’oggetto
chiamante: proprio come avviene con il servizio postale…(Qui l’ironia sarebbe
troppo facile!) Lo scambio asincrono di un messaggio tra oggetti attivi
prevede che l’oggetto chiamante esegua un’operazione di invio e quindi
proceda per la propria esecuzione. Nel frattempo, l’oggetto destinatario
accetta il messaggio quando è pronto (sono quindi necessari meccanismi
di accodamento dei segnali ricevuti) e prosegue per la esecuzione.
-
GENERICI
o SEMPLICI: sono utilizzati per rappresentare un flusso di controllo semplice.
In particolare servono per visualizzare come il flusso di controllo viene
scambiato tra due oggetti senza scendere nei dettagli della comunicazione.
Si ricorre a questa tipologia di messaggi quando i dettagli della comunicazione
non sono noti o si ritengono irrilevanti per la fase di progettazione in
corso.
|
Figura
1. Rappresentazione grafica delle diverse tipologie di messaggi.
Sequence Diagram
I
Sequence Diagram sono un’istanza dei diagrammi di interazione la cui caratteristica
è focalizzare l’attenzione sull’ordinamento temporale dei messaggi.
Dal punto di vista grafico i Sequence Diagram utilizzano una rappresentazione
bidimensionale basata su due assi: l’asse verticale che indica il trascorrere
del tempo, e quello orizzontale utilizzato per mostrare gli oggetti coinvolti
nella sequenza dei messaggi. Tipicamente, i diagrammi di sequenza, vengono
tracciati inserendo l’oggetto che istanza l’interazione a sinistra, proseguendo
poi verso destra aggiungendo via via gli altri oggetti che ricevono o spediscono
i messaggi: partecipano all’interazione (Figura 2).
|
Figura
2 . Esempio di Sequence Diagram
Le
caratteristiche che distinguono i Sequence Diagram dai Colaboration (riportati
di seguito) sono, sostanzialmente due:
-
è
presente la linea di vita (lifeline) di ogni oggetto. Come evidenziato
in figura 2, si tratta di una linea tratteggiata che si estende verticalmente
a partire dalla rappresentazione del relativo oggetto. In un Sequence Diagram,
molti oggetti esistono per tutta la durata dello “scenario” e pertanto
vengono riportati in alto, altri invece, vengono creati durante l’interazione
(si consideri l’istanza della classe “Order”). In questo caso, la lifeline
inizia a seguito della ricezione di un apposito messaggio di creazione:
stereotipo “<<create>>”. Ancora, alcuni oggetti vengono distrutti
durante l’interazione. Ciò accade con la ricezione di un altro specifico
messaggio: stereotipo “<<destroy>>” (Si consideri sempre l’istanza
della classe “Order”). La distruzione di un oggetto viene ulteriormente
evidenza per mezzo del simbolo grafico a forma di “X”. Da tener presente
che Rose non permette di rappresentare correttamente la generazione, durante
l’interazione, di un oggetto né la relativa distruzione.
-
è
evidenziato il flusso di controllo (focus of control). Si tratta di un
rettangolo sovrapposto alla lifeline che indica il periodo di tempo durante
il quale un oggetto esegue un’azione, sia direttamente, sia per mezzo di
procedure subordinate. L’inizio del rettangolo, ossia il lato minore superiore,
viene allineato con l’avvio dell’azione, tipicamente corrispondente alla
ricezione di un messaggio, mentre il lato parallelo in basso, ne rappresenta
la terminazione della stessa che, generalmente, genera la spedizione di
un messaggio. Sul “focus of control” è possibile evidenziare altri
foucs annidati (ricorsioni, invio di messaggi a sé stessi, ecc.).
Si
consideri il Sequence Diagram di figura 2. In primo luogo si può
osservare che poiché l’attenzione viene focalizzata sulla proiezione
dinamica del sistema, vengono presi in considerazione gli oggetti e non
le classi da cui vengono istanziati. La notazione utilizzata è quella
introdotta nell’articolo dedicato ai diagrammi delle classi e degli oggetti
(vedere [8]).
Dall’analisi
del diagramma, si può osservare che gli oggetti istanza delle classi
“Sender”, “Order Tack”, “TicketDB” e “Account”, già esistono, ossia
sono istanziati, prima che l’interazione abbia inizio. Mentre l’oggetto
“Order” viene creato e distrutto durante l’interazione. Lo “scenario” è
avviato dall’oggetto “Sender”, che invia un messaggio all’oggetto “OrderTraker”,
ossia ne invoca il metodo “request()”. Si può facilmente constatare
che la classe “Sender” rappresenta un attore esterno del sistema, e, come
tale, è stato rappresentato per mezzo del relativo stereotipo.
L’oggetto
“OrderTraker”, ricevuto il messaggio, invoca, a sua volta, il metodo “requestFreeTickets()”,
dell’oggetto “TicketDB”, che, verosimilmente, si occupa di gestire le tabelle
necessarie per memorizzare i dati relativi alla gestione vendita biglietti.
L’esito del metodo “requestFreeTickets()”, valore booleano, viene inviato
a ritroso all’oggetto “OrderTraker”. A questo punto si possono verificare
due alternative:
-
non ci
sono sufficienti biglietti disponibili: il controllo torna all’oggetto
“Sender” e l’iterazione finisce;
-
il numero
dei biglietti a disposizione soddisfa la richiesta: l’iterazione prosegue.
Si consideri
la seconda alternativa. L’oggetto “OrderTraker”, ricevuto il parametro
di ritorno con valore “true” (biglietti disponibili), invia un messaggio
“<<create>>” all’oggetto “Order” e quindi lo istanzia. Non appena
creato, l’oggetto “Order”si occupa di riservare i biglietti e a tal fine,
invoca il metodo “reserve()” dell’oggetto “TicketDB”. Quest’ultimo, a sua
volta, invoca il metodo di “debit()”, per addebitare il costo dei biglietti
all’opportuno “Account”. L’oggetto “Account” risponde invocando il metodo
“Bonus()” dell’oggetto “TicketDB” che dà luogo ad una invocazione
ricorsiva dello stesso metodo. Terminata l’interazione, il controllo torna
via via fino all’oggetto “sender” che aveva istanziato l’intero processo.
Durante il passaggio a ritroso del controllo, l’oggetto “Order” viene distrutto.
In
generale, i Sequence Diagram sono degli ottimi strumenti, utili anche per
modellare/documentare sottosistemi o meccanismi di carattere genrale; non
a caso vengono utilizzati per rappresentare gli scenari dei casi d’uso.
Probabilmente,
la loro caratteristica fondamentale è di essere molto intuitivi,
e quindi adatti per la formalizzazione di processi da sottoporre ad un
pubblico non necessariamente tecnico. Coloro che provengono da esperienze
di progettazioni strutturate dovrebbero già possedere una certa
familiarità con questa tipologia di diagrammi.
Nel
diagramma di figura 3, è stato utilizzato un Sequence Diagram per
illustrare il meccanismo di comunicazione utilizzato dall’RMI (Remote Method
Invocation) per far comunicare classi presenti su diverse Java Virtual
Machine.
|
Figura
1 Sequence diagram relativo al meccanismo di comunicazione RMI
Figura
3.
4.
Collaboration Diagram.
I
Collaboration Diagram sono diagrammi una seconda istanza dei interazione
la cui peculiarità risiede nel focalizzare l’attenzione sull’organizzazione
strutturale degli oggetti che partecipano all’interazione (inviano e/o
ricevono messaggi).
Le
caratteristiche che contraddistinguono i Collaboration Diagram dai Seuqence
sono essenzialmente due:
1.
è presente il percorso (path). Al fine di evidenziare come gli oggetti
sono collegati tra l’oro, è possibile realizzare opportune stereotipizzazioni
dei link, come “<<self>>” per indicare che il messaggio è
stato inviato da un oggetto a sé stesso, oppure “<<parameter>>”
che specifica che l’oggetto è visibile in quanto è un parametro
del mittente, ecc.
2.
i messaggi vengono numerati. Ciò è necessario per evidenziare
l’ordinamento temporale dei messaggi. Si aggiunge un prefisso al nome del
messaggio che ne indica, appunto, la posizione nella sequenza temporale.
A dir il vero, è possibile numerare anche i messaggi presenti nei
Sequence Diagram, anche se ciò non sia assolutamente necessario:
la sequenza temporale è ben visibile dal diagramma stesso, leggendolo
dall’alto verso il basso.
|
Figura
4 Collaboration Diagram corrispondente al Sequence di figura 2.
Adornamenti
Con
riferimento al punto 1, sono previste diverse stereotipizzazioni associabili
ai link, intesi come collegamenti tra oggetti, tra le quali, le più
importanti sono:
-
·Global.
Si applica agli oggetti che prendono parte ad un link per indicarne il
“ruolo”. Evidenzia che un dato oggetto è in grado di “vederne” un
altro a cui è connesso per mezzo di un parametro globale, che come
tale è conosciuto dal sistema. Viene rappresentato per mezzo di
un quadrato che racchiude il carattere ‘G’. Se tale parametro è
condiviso, allora il quadrato è riempito con il colore bianco, altrimenti
con quello nero. (vedere Figura 5).
-
Local.
Vale il discorso riportato nel punto precedente. In questo caso, chiaramente,
la visibilità tra gli oggetti è garantita da una variabile
locale. La lettera inserita nel quadratino è la ‘L’.
-
Parameter.
Come sopra.Field. Come sopra.
-
Self.
Indica un’autoinvocazione.
Chiaramente,
è sempre possibile ricorrere ai famosi “tagged value”.
|
Figura
5 Esempio di collaboration Diagram con evidenziati i ruoli “Global”
e “Field”
Notazione dei
messaggi
Quando
si realizzano i Collaboration Diagram, bisogna porre attenzione alla notazione
utilizzata. La sintassi generale prevede i seguenti simboli:
<predecessore>
[<condizione di guardia>] [<sequenza di espressioni>]
[<valore
di ritorno> := <segnatura del metodo>]
dove:
<predecessore>
:= <sequenza di numeri>, ‘,’ … ‘/’
La
sequenza di numeri serve ad introdurre un ordinamento temporale dei messaggi.
Ovviamente, i messaggi con numero d’ordine minore sono generati (e verosimilmente
gestiti) prima di altri con numeri d’ordine superiore.
Il
numero d’ordine di ciascun messaggio può essere strutturato secondo
un preciso criterio gerarchico, al fine di evidenziare sotto messaggi o
processi annidati.
<condizione
di guardia> := [ <condizione> ]
Per
ciò che concerne la condizione di guardia, può essere espressa
in qualsivoglia pseudocodifica, l’importante è curarne la leggibilità
e racchiudere la condizione tra parentesi quadre.
[<sequenza
di espressioni> := * [ <clausola iterativa>] : [<operazione>]
Il
simbolo “sequenza di espressioni” rappresenta un vero e proprio ciclo “for”.
E’ necessario premettere il carattere asterisco proprio per evidenziare
il ciclo, dopodiché va specificato l’indice, con il relativo dominio,
ed infine l’operazione che si intende iterare, separata dalla precedente
per mezzo dei due punti.
Esempio:
1.1.
* [ind = 0..n-1] : sendMessagge(ind)
Per
terminare, il valore di ritorno prevede una sintassi ben conosciuta:
<valore
di ritorno> := <segnatura del metodo>
Per
esempio: rit = getSender(n)
Esempi
di messaggi:
1:
repaint()
2.1
[t < 100] : wait()
3.,
4., 5. : sendNotification(listener)
Considerazioni
relative alle due tipologie di diagrammi
I
Collaboration ed i Sequence diagram sono semanticamente equivalenti: ciò
significa che si può passare da una rappresentazione all’altra,
in modo automatico e senza ridurne il contenuto informativo.
Alcuni
tool, tra cui Rational Rose, permettono di passare da un Sequence Diagram
all’equivalente Collaboration automaticamente.
Entrambi
i diagrammi possono essere utilizzati anche per evidenziare aspetti salienti
della use case view, attraverso un livello di astrazione, che considerata
la fase del ciclo di vita del sistema, non può che essere elevato.
I
Sequence vanno a realizzare i famosi scenari degli use case. In particolare
vengono utilizzati per illustrarne graficamente il flusso degli eventi.
In questo caso si utilizza una serie di Sequence Diagram: il primo per
illustrare lo scenario principale, tipicamente quello in cui tutto si realizza
correttamente. I rimanenti Sequence vengono utilizzari per documentare
flussi secondari e casi particolari.
Considerata
l’equivalenza semantica, ne segue che ogniqualvolta sia possibile utilizzare
un Sequence è anche plausibile utilòizzare un Collaboration.
Ciononostante, questi ultimi non vengono utilizzati per illustrare degli
scenari, bensì per cominciare a dare un’organizzazione, in termini
di collaborazione, agli use case.
A
questo punto il lettore potrebbe avere qualche perplessità circa
il criterio da utilizzarsi per selezionare il diagramma che, di volta in
volta, meglio descrive una determinata interazione.
Tipicamente
si tende ad utilizzare il Sequence Diagram, sia perché è
già presente, seppur in forma molto generale, sin dalle primissime
fasi di analisi, sia perché risulta molto intuitivo.
Conclusioni
Il
presente articolo è stato dedicato all’introduzione dell’analisi
del comportamento dinamico del sistema: “Eppur si muove!”. In particolare
sono stati introdotti i diagrammi utilizzati per analizzare/documentare
le interazioni, ossia i Sequence e i Collaboration Diagram, che, verosimilmente,
sono i più utilizzati per la proiezione dinamica della logical view.
Si è anche visto che si tratta di diagrammi semanticamente equivalenti,
da una tipologia è sempre possibile passare all’altra senza ridurne
il contenuto informativo. La differenza sostanziale risiede nell’aspetto
dell’interazione al quale si vuole conferire maggior enfasi. Nei Sequenmce
Diagram l’attenzione è focalizzata sull’ordinamento temporale dei
messaggi, ,mentre nei Collaboration, si preferisce dare risalto all’organizzazione
strutturale degli oggetti che si scambiano i messaggi.
Tipicamente
è abbastanza difficile che un singolo diagramma sia in grado di
illustrare esaurientemente un’intera iterazione, pertanto non è
infrequente il caso in cui sia necessario ricorrere a diversi diagrammi
per illustrare un determinato aspetto del sistema.
“Una
interazione ben strutturata è come un algoritmo ben strutturato
– efficiente, adattabile, e comprensibile- (Grady Booch).
Bibliografia
7.1.
[1] The Unified Modeling Language User Guide
Grady
Booch, James Rumbaugh, Ivar Jacobson
Addison
Wesley
Questo
libro vanta il primato di essere stato scritto dai progettisti originali
del linguaggio, sebbene sia conosciuto come “Grady’s book”, dal nome del
suo primo autore. La mancanza di una sua copia (magari autografata!) può
generare giudizi di scarsa professionalità per coloro che operano
nel settore della progettazione O.O... Ciò però, costituisce
una condizione necessaria, ma non sufficiente, in quanto bisogna, assolutamente,
aggiungere una copia del [3] e una del [4]. Sono soldi spesi bene! Forse,
il limite del libro, se proprio se ne vuole trovare uno, è quello
di essere poco accessibile ad un pubblico non espertissimo di progettazione
O.O. Un altro piccolo inconveniente è che, probabilmente, taluni
esempi possano sembrare di carattere accademico: poco rispondenti alle
problematiche del mondo reale.
7.2.
[2] UML Toolkit
Hans-Erik
Eriksson, Magnus Penker
Wiley
Questo
libro si fa particolarmente apprezzare per via del taglio pratico dello
stesso. Illustra in modo semplice il linguaggio, attraverso numerosi esempi,
limitando le digressioni di carattere teorico. Si suppone infatti, che
coloro che si occupano di progettazione O.O. abbiano una certa familiarità
con i relativi concetti. Chissà perché si ha la sensazione
che non sia sempre così! Naturalmente, studiare libri che illustrano
gli aspetti teorici dell’informatica, è sempre qualcosa più
che auspicabile. È altresì vero però, che coloro che
non hanno tempo da perdere, per la lettura di concetti arcinoti, gradiscono
arrivare rapidamente al nocciolo. Ciò spesso equivale a strappare
alle nottate lavorative ore preziose per il sonno.
7.3.
[3] The Unified Modeling Language Reference Manual
Grady
Booch, James Rumbaugh, Ivar Jacobson
Addison
Wesley
Il
commento da riportare per questo libro, noto per come “Rumbaugh’s book”,
è sostanzialmente equivalente a quanto riportato per il primo. Esso
però offre un livello di difficoltà decisamente inferiore,
e pertanto dovrebbe essere più accessibile. Come suggerisce il nome,
si tratta di un manuale, per cui ne rispetta la tipica struttura.
7.4.
[4] Design Patterns: Elements of Reusable Object-Oriented Software
Erich
Gamma, Richard Helm, Ralph Johnson, John Vlissides, Grady Booch
Addison
Wesley.
Si
tratta di un ottimo libro che bisogna assolutamente avere se si vuole lavorare
nell’ambito della progettazione O.O. . I “pattern” riportati, forniscono
un ottimo ausilio al processo di disegno del software. L’utilizzo del libro
contribuisce ad aumentare la produttività, fornisce soluzioni chiare,
efficienti e molto eleganti. La fase di disegno del software, spesso, si
riduce ad individuare e personalizzare i “pattern” che risolvono la problematica
specifica. Si è di fronte ad una nuova frontiera della progettazione
O.O.: il riutilizzo di parti del progetto. L’unica pecca imputabile, è
che i vari diagrammi non sempre rispettano il formalismo UML.
7.5.
[5] www.omg.org
Si
tratta del sito ufficiale del Object Managment Group.
7.6.
[6] www.mokabyte.it, numero 34 (Ottobre 1999)
UML
e lo sviluppo del software.
7.7.
[7] www.mokabyte.it, numero 35 (Novembre 1999)
Use
Case: l’analisi dei requisiti secondo l’U.M.L.
7.8.
[8] www.mokabyte.it, numero 36 (Dicembre 1999)
Diagrammi
delle classi e degli oggetti: proiezione statica della Design View.
7.9.
[9] www.mokabyte.it, numero 37 (Gennaio 2000)
Proiezione
statica della “Design View” parte seconda: esempi “celebri” di diagrammi
delle classi.. |