Il diagramma di sequenza è un tipo di diagramma dell’Unified Modeling Language (UML). L’UML è un lin­guag­gio di mo­del­la­zio­ne orientato agli oggetti ed è co­sti­tui­to da elementi grafici. L’UML modella sistemi e processi di pro­gram­ma­zio­ne orientata agli oggetti, nonché processi aziendali. L’obiettivo è quello di pre­sen­ta­re chia­ra­men­te fatti complessi. A questo scopo l’UML sta­bi­li­sce una notazione stan­dar­diz­za­ta.

Un modulo rap­pre­sen­ta sempre un par­ti­co­la­re com­po­nen­te o com­por­ta­men­to. Il co­sid­det­to me­ta­mo­del­lo definisce le unità lin­gui­sti­che e il loro si­gni­fi­ca­to all’interno dell’UML. Ciò include anche la de­ter­mi­na­zio­ne di come alcuni elementi possano in­te­ra­gi­re tra loro e quali gerarchie esistano tra le ri­spet­ti­ve unità lin­gui­sti­che.

L’UML rap­pre­sen­ta elementi e relazioni sotto forma di diagrammi. L’UML2 distingue 14 diversi tipi di diagrammi, as­se­gnan­do­li a una delle tre diverse categorie: diagrammi strut­tu­ra­li, diagrammi com­por­ta­men­ta­li e diagrammi di in­te­ra­zio­ne.

  • I diagrammi di struttura (in inglese: structure diagrams) rap­pre­sen­ta­no un sistema e le sue com­po­nen­ti in uno stato statico e il­lu­stra­no le relazioni tra singoli elementi o tra elementi e concetti so­vraor­di­na­ti. Un esempio di ciò è il diagramma di classe.
  • I diagrammi di com­por­ta­men­to (in inglese: behavior diagrams) rap­pre­sen­ta­no i processi e il com­por­ta­men­to di un sistema dinamico. A dif­fe­ren­za dei diagrammi di struttura anche l’ordine dei processi e perciò il tempo sono rilevanti nella rap­pre­sen­ta­zio­ne. Un esempio di ciò è il diagramma di attività.
  • I diagrammi di in­te­ra­zio­ne (in inglese: in­te­rac­tion diagrams) sono diagrammi com­por­ta­men­ta­li. Sono elencati se­pa­ra­ta­men­te perché modellano un com­por­ta­men­to specifico, cioè le in­te­ra­zio­ni tra gli elementi del sistema. Gli elementi co­sti­tu­ti­vi fon­da­men­ta­li delle in­te­ra­zio­ni sono le co­sid­det­te linee di vita: oggetti (cioè le più piccole com­po­nen­ti in­di­pen­den­ti della pro­gram­ma­zio­ne orientata agli oggetti) che rap­pre­sen­ta­no i singoli par­te­ci­pan­ti in un’in­te­ra­zio­ne. Il diagramma di in­te­ra­zio­ne più co­mu­ne­men­te uti­liz­za­to è il diagramma di sequenza.

I diagrammi di sequenza: utilizzo e par­ti­co­la­ri­tà

Il diagramma di sequenza UML presenta le oc­cor­ren­ze degli eventi in ordine cro­no­lo­gi­co, pertanto a volte viene indicato come un diagramma di eventi o uno scenario di eventi. L’ordine (ovvero la suc­ces­sio­ne precisa) è più im­por­tan­te di tempi specifici. Tuttavia è possibile includere re­stri­zio­ni nel modello: ad esempio un limite di tempo per un par­ti­co­la­re processo (come l’im­mis­sio­ne del codice PIN presso il bancomat) può causare un evento (re­sti­tu­zio­ne della carta se non si verifica alcun comando dopo un certo periodo di tempo).

Il diagramma di sequenza descrive fon­da­men­tal­men­te come gli oggetti (e le istanze) scambiano messaggi in un ordine par­ti­co­la­re. Gli oggetti sono la base ele­men­ta­re dei diagrammi UML. A seconda del tipo di diagramma, rap­pre­sen­ta­no alcune ca­rat­te­ri­sti­che di un elemento del sistema. Nelle in­te­ra­zio­ni gli oggetti sono linee di vita.

In un sistema vengono co­stan­te­men­te fatte richieste e inviate risposte. Il de­sti­na­ta­rio prende quindi una decisione in base alla richiesta specifica e alle sue regole pre­de­ter­mi­na­te. Una simile rete di possibili decisioni e in­te­ra­zio­ni è so­li­ta­men­te rap­pre­sen­ta­ta da un diagramma di attività. Se im­ma­gi­na­te tutte le decisioni possibili (“sì” o “no”) come un diagramma ad albero, pro­ba­bil­men­te si presenta l’immagine di una rete for­te­men­te ra­mi­fi­ca­ta. Il diagramma di sequenza mostra solo un percorso specifico all’interno di questa rete.

Il diagramma di sequenza si dif­fe­ren­zia dal diagramma del caso d’uso UML, in par­ti­co­la­re per il suo ordine det­ta­glia­to: se un processo aziendale deve essere rein­tro­dot­to, il caso d’uso fornisce una buona pa­no­ra­mi­ca sui requisiti. D’altra parte, se si desidera spe­ci­fi­ca­re casi concreti e pia­ni­fi­ca­zio­ni, si utilizza un diagramma di sequenza. In quest’ultimo potete rap­pre­sen­ta­re singole sezioni in modo più det­ta­glia­to. Con questo co­sid­det­to scenario di ap­pli­ca­zio­ne si con­trol­la­no ac­cu­ra­ta­men­te le con­nes­sio­ni logiche del caso d’uso.

I diagrammi di sequenza UML sono inoltre utili se si desidera rap­pre­sen­ta­re gra­fi­ca­men­te ope­ra­zio­ni com­pli­ca­te per renderle più com­pren­si­bi­li. La mo­del­la­zio­ne chiara iden­ti­fi­ca ra­pi­da­men­te le stazioni che una singola attività deve compiere per com­ple­tar­le cor­ret­ta­men­te. In questo modo potete pia­ni­fi­ca­re e testare i vostri metodi anche prima di im­ple­men­tar­li nell’attività aziendale quo­ti­dia­na o in un sistema in­for­ma­ti­co.

Per rap­pre­sen­ta­re le strutture di controllo di un lin­guag­gio di pro­gram­ma­zio­ne di alto livello collegate diversi diagrammi di sequenza l’uno con l’altro in un frammento combinato.

N.B.
I diagrammi di sequenza sup­por­ta­no l’analisi logica per sot­to­se­zio­ni di sistemi. Se la tem­pi­sti­ca dei processi gioca un ruolo im­por­tan­te, questo tipo di diagramma è par­ti­co­lar­men­te indicato. Tuttavia non ha senso uti­liz­zar­lo per pre­sen­ta­re un intero sistema. Piuttosto, puntate a un diagramma com­por­ta­men­ta­le ap­pro­pria­to come il diagramma del caso d’uso, il diagramma di stato o il diagramma di attività. Questi il­lu­stra­no anche relazioni più ampie in un modo chiaro e facile da capire.

Diagrammi di sequenza UML: notazione ed esempi

Un diagramma UML dovrebbe aiutare a garantire che tutte le parti in­te­res­sa­te com­pren­da­no meglio i sistemi complessi. Per fare ciò il lin­guag­gio di mo­del­la­zio­ne utilizza simboli visivi. Per eccezioni e gruppi di ap­pli­ca­zio­ne specifici l’UML può essere anche per­so­na­liz­za­to. Tuttavia ha più senso im­po­star­lo come spe­ci­fi­ca­to dallo standard dell’OMG (Object Ma­na­ge­ment Group) per evitare che insorgano problemi di com­pren­sio­ne. Le seguenti spe­ci­fi­che sono conformi allo standard UML nella versione UML 2.5.

Linee di vita

La linea di vita rap­pre­sen­ta la cro­no­lo­gia di un processo. La sua testa consta di un ret­tan­go­lo che in genere include il nome dell’oggetto e il nome della classe. Se il nome dell’oggetto è mancante, la linea di vita rap­pre­sen­ta un’istanza senza nome dell’oggetto. In questo caso si può assumere che tutti gli oggetti della stessa classe agiscano allo stesso modo in questa sequenza. La linea di vita rap­pre­sen­ta sempre solo un singolo operando. Se l’operando ha diverse ca­rat­te­ri­sti­che, occorre se­le­zio­nar­ne una. Per con­clu­de­re si può dire: la mol­te­pli­ci­tà non è mai >1.

Fatto
Un operando di in­ge­gne­ria in­for­ma­ti­ca è un oggetto che è in­fluen­za­to da un operatore. Gli operandi possono essere costanti o variabili. Ad esempio un operando semplice è la variabile X. Gli operatori possono essere semplici operatori arit­me­ti­ci come “+” e “-”. Nella pro­gram­ma­zio­ne si usano questi com­po­nen­ti per funzioni semplici come “x= t *4” fino a so­fi­sti­ca­ti algoritmi.

Dalla testa ret­tan­go­la­re scende una linea trat­teg­gia­ta. Questa linea rap­pre­sen­ta il passare del tempo. Verso il basso il tempo evolve li­near­men­te. Lungo la timeline i messaggi vengono inviati e vengono fornite le risposte. Un messaggio che è pia­ni­fi­ca­to per essere inviato dopo un altro messaggio rimane più in basso nella timeline. La notazione non indica mai precisi momenti, come data e ora, ma indica soltanto l’ordine temporale. I messaggi vengono sempre po­si­zio­na­ti uno sotto l’altro a meno che non esistano in frammenti combinati in parallelo.

Le linee di vita indicano per quanto tempo un oggetto è coinvolto at­ti­va­men­te in un processo: ciò si può desumere dalla lunghezza della linea di vita pa­ra­go­na­ta alle altre. Alcuni oggetti vengono distrutti prima che il processo sia terminato. Con­tras­se­gna­te gli oggetti non più necessari con una X sulla loro linea di vita nel punto in cui devono essere distrutti.

Il diagramma di sequenza, offrendo una pa­no­ra­mi­ca molto det­ta­glia­ta, è par­ti­co­lar­men­te adatto per ve­ri­fi­ca­re la ro­bu­stez­za del vostro sistema. Potete uti­liz­za­re tre ste­reo­ti­pi di classe della linea di vita:

  • entità
  • confine
  • elemento di controllo

Nell’immagine sopra potete vedere le tre linee di vita insieme alla notazione: l’entità ha una testa rotonda situata su una linea oriz­zon­ta­le. Al confine una linea scende nel mezzo del cerchio e si connette a una linea verticale, come una T inclinata che si allontana di lato dalla testa. La testa del comando consiste in una freccia che si trasforma in un cerchio. Di tutti questi ste­reo­ti­pi di classe, la linea trat­teg­gia­ta della vita scende ver­ti­cal­men­te verso il basso.

Se ad esempio avete già svi­lup­pa­to un concetto basato su un diagramma del caso d’uso, il diagramma di sequenza può aiutarvi a elaborare, tra le altre cose, le singole fasi, tenendo conto degli attori e degli oggetti con­ce­pi­bi­li.

I confini (in inglese: boun­da­ries) rap­pre­sen­ta­no in­ter­fac­ce che in­te­ra­gi­sco­no con attori esterni. Ad esempio questi oggetti po­treb­be­ro essere in­ter­fac­ce utente, nel qual caso l’attore sarebbe una persona. Le entità (in inglese: entities), d’altra parte, rap­pre­sen­ta­no con­te­ni­to­ri di dati o oggetti che con­ten­go­no dati di sistema. Affinché i confini e le entità possano co­mu­ni­ca­re, è ne­ces­sa­rio un elemento di controllo. Il controllo non deve essere ne­ces­sa­ria­men­te un oggetto. Funziona anche un metodo at­tri­bui­to a uno degli altri due elementi. L’elemento di controllo combina entità e confini come mediatore. Controlla i segnali dei due elementi e verifica per quanto riguarda la logica.

I tre ste­reo­ti­pi co­mu­ni­ca­no secondo quattro regole:

  • gli oggetti di confine sono l’in­ter­fac­cia per la co­mu­ni­ca­zio­ne con gli attori. Pertanto gli attori co­mu­ni­ca­no soltanto con i confini.
  • Al contrario gli oggetti di controllo co­mu­ni­ca­no con altri oggetti di controllo, oltre che con entità e confini. Non in­te­ra­gi­sco­no invece con gli attori.
  • I confini quindi co­mu­ni­ca­no con oggetti di controllo e attori.
  • Le entità sono pro­fon­da­men­te radicate nel sistema come portatori di dati. Scambiano solo dati con gli oggetti di controllo.

Messaggi

Il messaggio è un elemento base del diagramma di sequenza. Nella pro­gram­ma­zio­ne orientata agli oggetti un sistema consiste di oggetti. L’UML rap­pre­sen­ta questi oggetti come nodi collegati dai co­sid­det­ti bordi. Nell’UML questi bordi svolgono compiti diversi. Nel diagramma di sequenza UML modellano i messaggi di me­ta­clas­se. La notazione prescrive una linea come forma base del bordo. Le frecce sono una forma speciale di bordo che rap­pre­sen­ta una relazione di­re­zio­na­le o un flusso di in­for­ma­zio­ni. Nel diagramma di sequenza sim­bo­leg­gia­no i messaggi. Diversi tipi di messaggi sono vi­sua­liz­za­ti in modo diverso, come mostrato nella figura qui sotto.

Date al messaggio un’etichetta che mostri il suo contenuto. Per i messaggi semplici uti­liz­za­te il seguente modulo:

[Nome messaggio] : [attribute "="] nome segnale o nome ope­ra­zio­ne [argomenti] [":" valore re­sti­tui­to]

Gli argomenti validi per i messaggi sono:

  • costanti
  • valori jolly (valori simbolici che rap­pre­sen­ta­no un valore legale X nel diagramma)
  • attributi del mittente
  • parametri dell’in­te­ra­zio­ne cir­co­stan­te
  • attributi della classe so­vraor­di­na­ta

I messaggi hanno una firma che specifica il contenuto del messaggio. La firma si riferisce a un segnale o a un’ope­ra­zio­ne e deve comparire dopo ciascuno. Ciò significa che il contenuto del messaggio o avvia un’ope­ra­zio­ne (cioè un’attività) sul ri­ce­vi­to­re o invia un segnale, perciò scambia soltanto in­for­ma­zio­ni.

Inoltre i messaggi si dif­fe­ren­zia­no in sincroni o asincroni. Per i messaggi asincroni il mittente non attende una risposta, ma riprende im­me­dia­ta­men­te il suo com­por­ta­men­to. I messaggi sincroni attendono una risposta e bloccano il canale sul quale stanno inviando.

Questi sono i tipi di messaggio stan­dar­diz­za­ti nel diagramma di sequenza UML:

  • Messaggi asincroni del tipo (Mes­sa­ge­Sort) asyn­ch­Call, i quali chiamano un’ope­ra­zio­ne e ne attivano l’ese­cu­zio­ne. Per i messaggi asincroni il sistema non attende una risposta dal de­sti­na­ta­rio, ma continua i suoi processi senza in­ter­ru­zio­ni. I parametri di fun­zio­na­men­to e gli attributi dei messaggi devono cor­ri­spon­de­re.
    • Il tipo asyn­ch­Si­gnal viene uti­liz­za­to per le istanze di segnale. Rap­pre­sen­ta la spe­di­zio­ne e la ricezione di messaggi asincroni. Tale messaggio è causato da un’azione di invio asincrona del segnale. Qui gli attributi del segnale de­ter­mi­na­no gli argomenti del messaggio.
    • Notazione: i messaggi asincroni sono modellati come una freccia con una linea continua e una punta aperta.
  • I messaggi sincroni chiamano solo le ope­ra­zio­ni, nessun segnale. Il tipo di messaggio è chiamato synchCall. I messaggi sincroni attendono una risposta dell’ope­ra­zio­ne prima di ri­pren­de­re il proprio com­por­ta­men­to. I messaggi sincroni si rap­pre­sen­ta­no con una freccia la cui punta è piena.
  • Risposte: il de­sti­na­ta­rio di un messaggio lo ri­spe­di­sce al mittente dopo che l’ope­ra­zio­ne è giunta a con­clu­sio­ne. Il simbolo per questo ha una punta di freccia aperta o colorata. La linea cor­ri­spon­den­te è trat­teg­gia­ta.
  • crea­te­Mes­sa­ge è un tipo di messaggio che segnala una nuova istanza di una linea di vita. In questo modo il sistema crea un nuovo oggetto nel diagramma di sequenza. Questo tipo di messaggio è l’unico che punta di­ret­ta­men­te alla testa della linea di vita. Altri messaggi devono puntare alla linea di vita trat­teg­gia­ta. crea­te­Mes­sa­ge ha una freccia con una punta aperta e una linea trat­teg­gia­ta come la risposta, ma punta nella direzione opposta.
  • de­le­te­Mes­sa­ge segnala il momento in cui un’istanza della linea di vita viene distrutta. Potete disegnare il messaggio di can­cel­la­zio­ne come una freccia, op­zio­nal­men­te con il tiolo <>. Deve sempre indicare una De­struc­tion Oc­cur­ren­ce Spe­ci­fi­ca­tion. Chiamato anche evento di di­stru­zio­ne, questa specifica dell’oc­cor­ren­za dell’evento segna la di­stru­zio­ne di un oggeto sulal linea di runtime con una X.

Messaggi di qualsiasi tipo po­treb­be­ro non avere mittente o de­sti­na­ta­rio o potrebbe essere sco­no­sciu­to. Lo standard UML pre­sup­po­ne quindi che la ri­spet­ti­va istanza si trovi al di fuori dello schema descritto. Se conoscete il de­sti­na­ta­rio ma non il mittente, si tratta di un messaggio trovato. Là dove so­li­ta­men­te si indica il mittente, un piccolo cerchio pieno segnala la sua assenza. Con il messaggio perso funziona esat­ta­men­te al contrario: se non conoscete il de­sti­na­ta­rio, modellate un cerchio pieno sulla punta della freccia.

Ci sono anche messaggi par­ti­co­la­ri come quelli inviati sulla propria linea di vita. La linea di vita invia quindi la ri­cor­si­vi­tà da una barra delle attività. Una nuova at­ti­va­zio­ne si attiva sulla stessa linea di vita anche mentre l’at­ti­va­zio­ne è ancora in corso. Il suo punto di partenza accetta il messaggio inviato. È possibile uti­liz­za­re questo tipo di messaggio, ad esempio, quando un’ope­ra­zio­ne viene eseguita più volte e l’oggetto deve quindi fare ri­fe­ri­men­to a se stesso. I messaggi tra due linee di vita possono anche produrre at­ti­va­zio­ni so­vrap­po­ste. Di seguito daremo un’occhiata più da vicino alle spe­ci­fi­che per le at­ti­va­zio­ni.

Un’altra parte im­por­tan­te del messaggio è il suo parametro: i parametri sono spe­ci­fi­che di valore. Il sistema valuta queste di­men­sio­ni quando invia un messaggio con una firma. Ciò accade nella specifica della pre­sta­zio­ne, cioè nel punto in cui viene inviato il messaggio. Il risultato specifica i valori per gli attributi del segnale o i parametri di input dell’ope­ra­zio­ne a seconda del de­sti­na­ta­rio. L’ope­ra­zio­ne quindi elabora ul­te­rior­men­te il valore e produce un parametro di output.

Una ca­rat­te­ri­sti­ca speciale è il parametro jolly (wildcard): se al messaggio mancano tutti i parametri, la sintassi richiede una stringa vuota. Questo simbolo indica che il valore del parametro non è impostato, tuttavia è valido nel senso dei parametri o degli attributi del de­sti­na­ta­rio, com­por­tan­do­si come un Joker. I caratteri jolly sono dei me­ta­ca­rat­te­ri per singole lettere o intere stringhe. Molti conoscono l’asterisco (*) in quanto me­ta­ca­rat­te­re. In UML è il trattino (“-”) a fungere da simbolo jolly, ovvero da me­ta­ca­rat­te­re.

I messaggi di risposta possono avere solo un’espres­sio­ne per parametro con al massimo un operando. Se il mittente di una risposta non emette alcun valore, anche il messaggio non ha valori specifici da inviare. Nor­mal­men­te il messaggio modella i parametri di output di un mittente (cioè i valori che risultano da un’ope­ra­zio­ne) come operandi. Senza un parametro di output, l’operando deve rimanere vuoto. In questo caso sem­pli­ce­men­te non modellate alcun valore di ritorno, ma il me­ta­ca­rat­te­re jolly. Se è presente un operando, il sistema lo valuta nuo­va­men­te alla specifica dell’aspetto. Il risultato della va­lu­ta­zio­ne specifica i valori per il parametro “out”, “inout” e “return”.

Fatto
I parametri IN, OUT e INOUT indicano se un’istanza accetta o re­sti­tui­sce valori. Il parametro IN indica che un’istanza sta ricevendo ed ela­bo­ran­do i valori ma non li sta inviando. Il parametro OUT specifica che non assume valori, ma li emette soltanto. Il parametro INOUT consente sia i valori in entrata che in uscita. Se non si definisce nessuno di questi valori, il sistema IN sarà quello pre­de­fi­ni­to.

L’UML specifica tre simboli che de­fi­ni­sco­no il de­sti­na­ta­rio del messaggio come espres­sio­ne del parametro. Il de­sti­na­ta­rio è il co­sid­det­to obiettivo di as­se­gna­zio­ne del messaggio (in inglese: As­si­gn­ment Target). Il messaggio di risposta assegna il valore di ritorno del parametro di output del mittente. Questi sono i simboli stan­dar­diz­za­ti:

  • Unknown
  • In­te­rac­tion Parameter
  • Attribute

Unknown (sco­no­sciu­to) è un parametro vuoto e rap­pre­sen­ta il carattere jolly. Il parametro di in­te­ra­zio­ne (In­te­rac­tion Parameter) è un ow­ned­Pa­ra­me­ter dell’in­te­ra­zio­ne alla quale ap­par­tie­ne. Cioè l’in­te­ra­zio­ne possiede il parametro, il quale ha un nome. I parametri di ope­ra­zio­ne e i parametri di in­te­ra­zio­ne hanno lo stesso tipo. Gli attributi possono essere nominati senza re­stri­zio­ni e rap­pre­sen­ta­no il nome di un com­por­ta­men­to di contesto che determina la linea di vita a cui il messaggio ritorna o l’in­te­ra­zio­ne cir­co­stan­te. Se l’in­te­ra­zio­ne non definisce il com­por­ta­men­to, agisce essa stessa come un contesto.

I gates, ovvero le porte, sono sem­pli­ce­men­te punti alla fine di un messaggio. Ap­par­ten­go­no al tipo Mes­sa­geEnd (fine del messaggio) e segnano il mittente e il de­sti­na­ta­rio di un messaggio. I gates chia­ri­sco­no il flusso di in­for­ma­zio­ni e mostrano come si muovono i messaggi tra due frammenti di in­te­ra­zio­ne. In par­ti­co­la­re rap­pre­sen­ta­no punti di con­nes­sio­ne per i messaggi tra gli utilizzi delle in­te­ra­zioni e le in­te­ra­zio­ni, nonché tra operandi di in­te­ra­zio­ne all’interno e all’esterno di un frammento combinato. Si pongono sulla cornice del diagramma.

Il diagramma di sequenza UML ha quattro tipi di gates che dif­fe­ri­sco­no a seconda dei frammenti di in­te­ra­zio­ne a cui sono associati:

  • La porta fattuale: gli utilizzi dell’in­te­ra­zio­ne rinviano da un diagramma all’altro. La porta fattuale (in inglese: Actual Gate) apre la con­nes­sio­ne con il bordo esterno dell’in­te­ra­zio­ne per messaggi al di fuori dell’in­te­ra­zio­ne, alla quale rimanda l’utilizzo dell’in­te­ra­zio­ne. La porta ha perciò un’as­so­cia­zio­ne con l’utilizzo dell’in­te­ra­zio­ne e accetta i messaggi in entrata e in uscita.
  • La porta formale: affinché un’in­te­ra­zio­ne sia in grado di scambiare messaggi con un utilizzo di in­te­ra­zio­ne, è ne­ces­sa­ria una porta formale (in inglese: Formal Gate). Essa si trova all’interno del frame.
  • La porta interna per frammenti combinati: all’interno di un frammento combinato si trova un gate al frame che scambia i messaggi con estremità di messaggi dal frammento combinato con messaggi con estremità dei messaggi all’esterno del frammento combinato. In inglese prende il nome di Inner Combined Fragment Gate).
  • La porta esterna per frammenti combinati: questa porta si trova all’esterno di un frammento combinato. Essa forma il polo opposto alla porta interna (in inglese: Outer Combined Fragment Gate).

Le porte hanno nomi espliciti o impliciti che devono cor­ri­spon­de­re in coppia. Le porte fattuali e formali devono coin­ci­de­re, così come le porte interne ed esterne per i frammenti combinati. Inoltre i messaggi devono andare nella stessa direzione e avere gli stessi in­con­fon­di­bi­li valori di proprietà nonché lo stesso Mes­sa­ge­Sort.

Un ruolo par­ti­co­la­re è giocato dai messaggi nei diagrammi di co­mu­ni­ca­zio­ne. Questo tipo di diagramma è una forma semplice del diagramma di sequenza. I diagrammi di co­mu­ni­ca­zio­ne modellano il modo in cui in­te­ra­gi­sco­no le linee di vita. A dif­fe­ren­za dei diagrammi di sequenza, si con­cen­tra­no sull’ar­chi­tet­tu­ra del sistema e su come essa influisca sul flusso dei messaggi.

Sebbene sia possibile mostrare un’ar­chi­tet­tu­ra det­ta­glia­ta, i frammenti di in­te­ra­zio­ne come i frammenti combinati non la uti­liz­za­no. Di con­se­guen­za manca un elemento strut­tu­ra­le. Invece, numerate i messaggi: talvolta i messaggi possono tra­ghet­tar­ne altri. L’ordine dei messaggi in uscita dif­fe­ri­sce dall’ordine dei messaggi in arrivo. Tuttavia lo standard UML non consiglia tali messaggi non se­quen­zia­li nel diagramma di co­mu­ni­ca­zio­ne.

La notazione UML del diagramma di co­mu­ni­ca­zio­ne detta un semplice diagramma di sequenza: un ret­tan­go­lo con un’etichetta pen­ta­go­na­le nell’in­te­sta­zio­ne. L’etichetta “sd” con­tras­se­gna questo tipo di diagramma. Inoltre notate il nome dell’in­te­ra­zio­ne: i messaggi qui hanno una forma diversa e collegano le linee di vita ret­tan­go­la­ri (UML: nodi oggetto) come linee semplici (UML: linee).

Annotate la de­scri­zio­ne della sequenza (in inglese: Sequence Ex­pres­sion) insieme a una freccia rivolta verso il ri­ce­vi­to­re. Il nome della sequenza ha la seguente forma: [Integer|Name] [Re­pe­ti­tion]. L’integer specifica la gerarchia degli elementi ni­di­fi­ca­ti. Se uno dei due Integer (ad esempio 1.2.2 e 1.2.3) si dif­fe­ren­zia in due messaggi, il sistema li manda uno dopo l’altro. Il nome d’altra parte significa tra­smis­sio­ne si­mul­ta­nea. Il sistema manda due messaggi con i nomi di sequenza 1.2.3a e 1.2.3b in modo si­mul­ta­neo per via dell’identico Integer. La ri­pe­ti­zio­ne contiene una re­stri­zio­ne che determina quando viene mandato il messaggio o un valore che determina quanto spesso il messaggio viene ripetuto.

Guards

In UML la Guard controlla il com­por­ta­men­to di un elemento, che deve:

  • Sod­di­sfa­re una de­ter­mi­na­ta con­di­zio­ne
  • Non superare o scendere al disotto di un de­ter­mi­na­to valore o
  • Con­fer­ma­re un’af­fer­ma­zio­ne

Pertanto una Guard è una li­mi­ta­zio­ne: solo quando il vincolo è sod­di­sfat­to, l’elemento in­te­res­sa­to può eseguire un de­ter­mi­na­to com­por­ta­men­to. Ci sono molti diversi elementi che possono avere una tale guardia: azioni, attributi, com­por­ta­men­ti e altri. L’UML non prescrive precisi criteri di lin­guag­gio, ma offre OCL, l’Object Con­straint Language, come opzione nativa. Vengono spesso uti­liz­za­te anche le variabili booleane.

Una re­stri­zio­ne di in­te­ra­zio­ne di questo tipo consiste in una tale espres­sio­ne booleana. Il vincolo funge da custode per l’operando all’interno di un frammento combinato. Solo se il valore del vincolo è vero, il frammento di in­te­ra­zio­ne che lo circonda inizia il proprio com­por­ta­men­to. Annotate la li­mi­ta­zio­ne tra parentesi quadre sulla linea di vita sopra una specifica di ese­cu­zio­ne. La stan­dar­diz­za­zio­ne consente frammenti combinati senza limiti di in­te­ra­zio­ne. In questo caso il sistema pre­sup­po­ne che i messaggi in arrivo siano veri.

Frammenti di in­te­ra­zio­ne nei diagrammi di sequenza

Quando create un diagramma di sequenza le linee di vita e i messaggi sono i com­po­nen­ti più im­por­tan­ti. L’UML2 rac­co­man­da una cornice per questo tipo di diagramma, tuttavia non è ob­bli­ga­to­rio. La cornice (frame) limita un processo se­con­da­rio, il co­sid­det­to frammento di in­te­ra­zio­ne. Tutte le linee di vita e i messaggi necessari si trovano all’interno del frame. Esso consiste in un ret­tan­go­lo con un’etichetta nell’angolo in alto a sinistra. L’in­di­ca­to­re per un diagramma di sequenza è l’ab­bre­via­zio­ne sd, so­li­ta­men­te in grassetto. Accanto si inserisce il nome dell’in­te­ra­zio­ne come mostrato nell’immagine qui sotto.

Oltre al limite ottico il frame serve anche ad aspetti fun­zio­na­li. Se si creano più diagrammi di sequenza (o altre in­te­ra­zio­ni), il frame delimita le rap­pre­sen­ta­zio­ni una dall’altra. Se de­si­de­ra­te che i vari frammenti di in­te­ra­zio­ne co­mu­ni­chi­no tra di loro, modellate un messaggio (freccia piena) sul bordo del frame. Nella figura sopra il sistema manda il messaggio 5 verso l’esterno. Il punto in cui la freccia incontra il frame è chiamato gate (porta). Esso ha una funzione all’interno del diagramma, ma non ha una propria notazione.

In UML i frammenti di in­te­ra­zio­ne ap­par­ten­go­no ai nodi. Questo concetto so­vraor­di­na­to è inteso in modo molto generale. Le proprietà e i compiti dei nodi sono spe­ci­fi­ca­ti da UML a seconda dei ri­spet­ti­vi tipi di diagramma nel quale si incontra uno specifico nodo. In generale si può dire che i nodi sono elementi di modello all’interno di un sistema o processo sul quale si può in­stal­la­re un artefatto. L’UML connette i nodi at­tra­ver­so linee che rap­pre­sen­ta­no lo scambio di in­for­ma­zio­ni o gra­fi­ca­men­te at­tra­ver­so le frecce o sem­pli­ce­men­te con delle linee.

In UML si possono creare diagrammi di sequenza che con­ten­go­no parti annidate. I frame aiutano a rap­pre­sen­ta­re in modo ordinato i singoli frammenti.

I diagrammi di sequenza possono contenere i frammenti di in­te­ra­zio­ne utilizzo di in­te­ra­zio­ne, in­va­rian­ti di stato, spe­ci­fi­che di oc­cor­ren­za eventi, spe­ci­fi­che di ese­cu­zio­ne e frammenti combinati.

Usi dell’in­te­ra­zio­ne

Gli utilizzi di in­te­ra­zio­ne co­sti­tui­sco­no una sot­to­clas­se che sta­bi­li­sce e prescrive la notazione, la co­stru­zio­ne e il com­por­ta­men­to di due me­ta­clas­si. Queste me­ta­clas­si sono l’uso dell’in­te­ra­zio­ne e la parziale de­com­po­si­zio­ne.

L’utilizzo dell’in­te­ra­zio­ne come me­ta­clas­se è un frammento di in­te­ra­zio­ne che richiama o utilizza un’altra in­te­ra­zio­ne. Se il diagramma di sequenza si fa troppo complesso, in questo modo potrete ottenere maggiore chiarezza. Infatti potete vi­sua­liz­za­re l’in­te­ra­zio­ne alla quale l’uso dell’in­te­ra­zio­ne rimanda nel diagramma attuale in una black box. Per iden­ti­fi­ca­re l’in­te­ra­zio­ne ri­chia­ma­ta in modo ine­qui­vo­ca­bi­le scrivete nel corpo (campo nel quale le istanze eseguono le ope­ra­zio­ni) la seguente sintassi:

  • Nome dell’attributo (attributo di una linea di vita nell’utilizzo dell’in­te­ra­zio­ne che riceve il valore di ritorno)
  • Nome della col­la­bo­ra­zio­ne (uso della col­la­bo­ra­zio­ne iden­ti­fi­ca­to che connette in­te­ra­zio­ni e col­la­bo­ra­zio­ni l’una all’altra)
  • Nome dell’in­te­ra­zio­ne dell’elemento ri­chia­ma­to
  • io-Argument: argomenti in/out dell’in­te­ra­zio­ne
  • valori di ritorno (risposta dell’in­te­ra­zio­ne ri­chia­ma­ta)

Potete modellare l’uso dell’in­te­ra­zio­ne come ret­tan­go­lo con un’etichetta pen­ta­go­na­le nell’angolo in alto a sinistra. Lì scrivete l’ab­bre­via­zio­ne “ref” (dall’inglese: “referral”).

Poiché l’utilizzo dell’in­te­ra­zio­ne punta su altri diagrammi, questi fattori esterni de­ter­mi­na­no il loro com­por­ta­men­to. Mentre l’in­te­ra­zio­ne collegata attinge a porte formali (in inglese gates), l’in­te­ra­zio­ne di rimando dispone della porta reale.

La scom­po­si­zio­ne parziale (in inglese: part de­com­po­si­tion) è appunto la divisione parziale e se­quen­zia­le di una linea di vita all’interno di un’in­te­ra­zio­ne at­tra­ver­so un’altra in­te­ra­zio­ne. L’utilizzo di tale scom­po­si­zio­ne consente di separare i dettagli l’uno dall’altro e di poter quindi osservare più da vicino le singole sotto-funzioni. Sia che i messaggi dalla linea di vita de­com­po­sta siano in entrata che in uscita sono con­si­de­ra­ti porte effettive. Essi sono collegati alle porte formali dell’azione di de­com­po­si­zio­ne. I gate e i parametri di entrambi gli elementi devono cor­ri­spon­de­re. Come uso dell’in­te­ra­zio­ne, la scom­po­si­zio­ne parziale ha anche l’etichetta “ref” ed è definita dall’in­te­ra­zio­ne connessa.

Barra delle attività/spe­ci­fi­che di ese­cu­zio­ne

La barra delle attività, in inglese execution spe­ci­fi­ca­tion (detta co­mu­ne­men­te anche sem­pli­ce­men­te at­ti­va­zio­ne), indica il tempo su una linea di vita in cui un oggetto esegue un com­por­ta­men­to o passa at­tra­ver­so un’azione. Modellate inoltre anche il tempo in cui un oggetto coinvolto invia un messaggio o attende una risposta, poiché la barra delle attività indica un periodo di tempo astratto durante il runtime. Come per l’intero diagramma, il tempo non è una grandezza assoluta, ma relativa. Anche il com­por­ta­men­to passivo, come l’attesa di una risposta, deve essere inserito come at­ti­va­zio­ne nel diagramma di sequenza.

L’UML rap­pre­sen­ta la semantica di una specifica di ese­cu­zio­ne con la struttura semplice <start,end>. La notazione per la execution spe­ci­fi­ca­tion consente due forme. Modellate un ret­tan­go­lo lungo e stretto con riem­pi­men­to grigio sulla linea di vita. Nor­mal­men­te l’at­ti­va­zio­ne in questo modulo non implica un’etichetta nel corpo. In al­ter­na­ti­va tracciate un ret­tan­go­lo bianco leg­ger­men­te più largo sulla linea di vita. Lì avete lo spazio per eti­chet­ta­re la barra delle attività. Se un oggetto esegue un’azione durante il runtime, spe­ci­fi­ca­te il nome dell’azione.

L’inizio e la fine segnano le spe­ci­fi­che dell’oc­cor­ren­za dell’evento, in breve spe­ci­fi­che dell’oc­cor­ren­za (in inglese: Event Oc­cur­ren­ce Spe­ci­fi­ca­tion). All’inizio di un’at­ti­va­zio­ne sta l’evento di inizio, alla fine l’evento di chiusura. Questi frammenti rap­pre­sen­ta­no ciascuno un singolo momento ed esistono su un’unica linea di vita. La specifica dell’oc­cor­ren­za dell’evento rap­pre­sen­ta l’inizio o la fine di un’azione. La specifica di oc­cor­ren­za del messaggio (Message Occurence Spe­ci­fi­ca­tion) fornisce il segnale per inviare e ricevere un messaggio. Pertanto il loro valore dipende sempre dal messaggio o dall’azione.

L’at­ti­va­zio­ne non ha una notazione separata. Esiste im­pli­ci­ta­men­te ai bordi esterni del ret­tan­go­lo della specifica di ese­cu­zio­ne. Quando la specifica di ese­cu­zio­ne subisce un’azione atomica, le as­so­cia­zio­ni iniziale e finale si ri­fe­ri­sco­no alla stessa specifica di oc­cor­ren­za. È possibile evi­den­zia­re ciò con una linea di col­le­ga­men­to tra l’azione e le spe­ci­fi­che di oc­cor­ren­za in entrata.

Fatto
Un’azione atomica appare come una blackbox. È una sequenza in­di­vi­si­bi­le che consta di diverse semplici ope­ra­zio­ni che non si possono osservare perché sono eseguite in maniera estre­ma­men­te veloce. Un’azione atomica viene quindi com­ple­ta­ta quasi im­me­dia­ta­men­te.

Mentre altre spe­ci­fi­che di oc­cor­ren­za non ri­chie­do­no alcuna notazione, con­tras­se­gna­te le di­stru­zio­ni delle spe­ci­fi­che di oc­cor­ren­za dei messaggi con una X maiuscola. Essa con­tras­se­gna la ri­so­lu­zio­ne di un’istanza di oggetto in un punto par­ti­co­la­re sulla linea di vita. La linea di vita si conclude con essa. Le istanze su­bor­di­na­te o le spe­ci­fi­che delle oc­cor­ren­ze in punti suc­ces­si­vi della timeline non sono quindi valide. Dopo la di­stru­zio­ne dell’oggetto non esistono più.

A volte le spe­ci­fi­che di ese­cu­zio­ne si so­vrap­pon­go­no. Ad esempio, se un oggetto invia un messaggio a se stesso, una execution spe­ci­fi­ca­tion invia un messaggio a un’altra istanza di quella classe. Entrambe le spe­ci­fi­che sono talvolta si­mul­ta­nea­men­te sulla stessa linea di vita. Nel diagramma di sequenza UML rap­pre­sen­ta­te questa cir­co­stan­za con ret­tan­go­li che si so­vrap­pon­go­no.

State invariant

La State Invariant (o in­va­rian­te di stato) è un vincolo di runtime. La linea di vita rap­pre­sen­ta un oggetto. Durante il runtime questo oggetto cambia il proprio stato at­tra­ver­so la specifica di ese­cu­zio­ne. L’in­va­rian­te di stato esamina l’oggetto per il suo cam­bia­men­to di stato nella specifica di ese­cu­zio­ne appena prima di eseguire la suc­ces­si­va specifica di oc­cor­ren­za. Tutte le pre­ce­den­ti azioni implicite all’interno della specifica di ese­cu­zio­ne sono con­si­de­ra­te eseguite.

La state invariant specifica un valore limite. Se questo valore è uguale allo stato dell’oggetto, la traccia è valida. Se l’oggetto non soddisfa la re­stri­zio­ne, la sua traccia non è valida.

In base alla notazione del diagramma di sequenza UML, l’in­va­rian­te di stato è tra parentesi graffe sulla specifica di ese­cu­zio­ne. In al­ter­na­ti­va potete uti­liz­za­re il ret­tan­go­lo ar­ro­ton­da­to dello stato di classe.

Frammenti combinati

I frammenti combinati ap­par­ten­go­no ai frammenti di in­te­ra­zio­ne. Questi frammenti sono elementi astratti del sistema e rap­pre­sen­ta­no le unità di in­te­ra­zio­ne. Ciò significa che fanno parte di un’in­te­ra­zio­ne. D’altra parte sono anche esse stesse piccole in­te­ra­zio­ni. I frammenti combinati in un diagramma di sequenza de­ter­mi­na­no il com­por­ta­men­to di più frammenti di in­te­ra­zio­ne. Ma loro stessi formano soltanto il frame. Dunque sono definiti da operatori di in­te­ra­zio­ne e operandi di in­te­ra­zio­ne. Gli operandi con­ten­go­no uno o più messaggi. Sulla linea di vita di fronte a un frammento combinato una re­stri­zio­ne, chiamata anche guard, sorveglia l’operando contenuto.

Come pre­ce­den­te­men­te descritto, gli operandi sono quantità costanti o variabili che subiscono un processo. Gli operatori in­fluen­za­no il com­por­ta­men­to degli operandi. Ad esempio, l’operatore booleano OR può pre­scri­ve­re che siano eseguiti l’operando A o l’operando B (o entrambi). All’interno di un frammento combinato un operando sta­bi­li­sce che un par­ti­co­la­re messaggio venga inviato a de­ter­mi­na­te con­di­zio­ni. L’operatore determina quali relazioni hanno gli operandi all’interno di un frammento e la loro relazione con il frammento prin­ci­pa­le.

Operatori di in­te­ra­zio­ne

L’UML definisce 12 operatori di in­te­ra­zio­ne.

Al­ter­na­ti­ve:

Nell’ambito del frammento combinato con l’operatore di in­te­ra­zio­ne “Al­ter­na­ti­ve”, un frammento su­bor­di­na­to può inviare un solo messaggio se viene sod­di­sfat­ta una par­ti­co­la­re con­di­zio­ne. Al­tri­men­ti un frammento con­cor­ren­te all’interno del frame invia il proprio messaggio. Nella figura sopra potete vedere un esempio di un frammento combinato con l’operatore “Al­ter­na­ti­va”. Per l’etichetta si usa l’ab­bre­via­zio­ne “alt”. Il frame ret­tan­go­la­re è diviso da una linea trat­teg­gia­ta oriz­zon­ta­le. L’area superiore rap­pre­sen­ta una con­di­zio­ne.

Guard:

La Guard (guardia) controlla se la con­di­zio­ne dell’operando è sod­di­sfat­ta. In tal caso il sistema invia un messaggio nell’area delle con­di­zio­ni. In caso contrario invia un messaggio nell’area dell’al­ter­na­ti­va. Un operando all’interno di questo frammento combinato ha sempre bisogno di una guardia giudicata veritiera (“true”) per essere eseguito. Se l’operando delle con­di­zio­ni non ha una esplicita guard, si assume una guardia implicita. Questo frammento rap­pre­sen­ta quindi sempre una decisione aut aut.

Option:

Questo frammento combinato nel diagramma di sequenza va modellato come l’al­ter­na­ti­va, poiché l’option (opzione) rap­pre­sen­ta anche una decisione. Tuttavia c’è un solo operando. La decisione quindi riguarda se l’operando debba essere eseguito o meno. L’operando con una con­di­zio­ne non può essere vuoto, mentre la sua al­ter­na­ti­va è vuota. Un frammento con l’operatore di in­te­ra­zio­ne “Option” è con­tras­se­gna­to dall’etichetta “opt”.

In­ter­ru­zio­ne:

Un frammento combinato in­ter­rom­pe il frammento so­vraor­di­na­to con l’operatore di in­te­ra­zio­ne “break”. Se una linea di vita soddisfa la con­di­zio­ne dell’operando, il sistema esegue il frammento combinato. In questo modo ignora il resto del frammento so­vraor­di­na­to. Affinché tutte le linee di vita possano esaurire la durata della propria vita, occorre includere ciascuna linea di vita nel frammento combinato. Al­tri­men­ti, una linea di vita potrebbe fermarsi nel mezzo di un processo senza essere ade­gua­ta­men­te distrutta. Se il frammento break manca di una guardia, la decisione è non de­ter­mi­ni­sti­ca. Pertanto con­si­glia­mo di uti­liz­za­re una guard.

Fatto
Il non de­ter­mi­ni­smo è un concetto di in­for­ma­ti­ca teorica che mira a sem­pli­fi­ca­re la mo­del­la­zio­ne. Allo stesso tempo un sistema ha più di un modo per ottenere lo stesso risultato a partire da uno stesso valore di partenza. Nella pratica vengono uti­liz­za­ti pre­va­len­te­men­te algoritmi de­ter­mi­ni­sti­ci con un solo percorso di calcolo. Un algoritmo non de­ter­mi­ni­sti­co, d’altra parte, prende un percorso im­pre­ve­di­bi­le nel calcolo, anche se si avvia il sistema con le stesse in­for­ma­zio­ni. Poiché l’algoritmo produce risultati si­gni­fi­ca­ti­va­men­te più diversi rispetto a un algoritmo de­ter­mi­ni­sti­co, il compito dovrebbe essere meno complesso. I modelli astratti sem­pli­fi­ca­no i sistemi complessi. Pertanto sono adatti per pre­fi­gu­ra­re diversi calcoli con l’algoritmo non de­ter­mi­ni­sti­co.

Il ciclo:

Un frammento combinato con l’operatore di in­te­ra­zio­ne “loop” ripete il proprio operando. Il numero esatto di passaggi è de­ter­mi­na­to dalla guardia. La guard può includere porte di ri­pe­ti­zio­ni e variabili booleane. Nell’etichetta del frame annotate i limiti di ri­pe­ti­zio­ne come segue: loop (X,Y). Le variabili X e Y indicano ciascuna un numero naturale. X è il numero minimo di ri­pe­ti­zio­ni (“min-int”), mentre Y è il numero massimo di ri­pe­ti­zio­ni (“max-int”). X deve essere un numero non negativo, mentre Y deve essere un numero non negativo maggiore o uguale a 0.

In al­ter­na­ti­va potete annotare la variabile booleana nel corpo del frame accanto all’etichetta. Essa limita ul­te­rior­men­te la ri­pe­ti­zio­ne. Se la con­di­zio­ne della variabile booleana non è più sod­di­sfat­ta e viene raggiunto il numero minimo di ri­pe­ti­zio­ni, il ciclo si arresta. Annotate la re­stri­zio­ne tra parentesi quadre. Questa re­stri­zio­ne si riferisce a fattori esterni come gli input di un attore.

A un bancomat si dispone, ad esempio, la pos­si­bi­li­tà di inserire il PIN tre volte. Se il PIN è sbagliato, vi verrà richiesto di riprovare. Nel diagramma di sequenza UML, annotate il messaggio “Inserire PIN” e la relativa risposta “PIN errato. Riprovare” con le frecce cor­ri­spon­den­ti. L’etichetta ha la forma del loop (0,2). La variabile booleana è [PIN errato]. Se il PIN è errato, il ciclo si ripeterà due volte, mentre se è corretto, il sistema sbloc­che­rà il ciclo. Se viene superato il numero massimo di tentativi, il ciclo si in­ter­rom­pe­rà, ma il processo verrà annullato come non valido.

N.B.
Se non si spe­ci­fi­ca­no i limiti di ri­pe­ti­zio­ne, il minimo è 0 e il massimo è infinito. Se il minimo e il massimo hanno lo stesso valore, dovete inserire un solo limite.

In parallelo:

Di solito la posizione di una freccia sulla linea di vita nel diagramma di sequenza prescrive sempre un ordine cro­no­lo­gi­co. In un frammento combinato con l’operatore di in­te­ra­zio­ne “in parallelo”, i suoi operandi sono au­to­riz­za­ti a eseguire i loro processi con­tem­po­ra­nea­men­te.

Po­ten­zial­men­te gli operandi in­trec­cia­no il loro ordine di processo. Tuttavia l’ordine spe­ci­fi­ca­to all’interno degli operandi viene sempre mantenuto. Nel diagramma di sequenza UML modellate questo frammento combinato con un frame solido. Separate vi­si­va­men­te i diversi operandi con linee trat­teg­gia­te, simili a quelle dell’al­ter­na­ti­va. Nell’etichetta inserite l’ab­bre­via­zio­ne “par” (vedi l’il­lu­stra­zio­ne in Critical Region). Se gli operandi devono lavorare in parallelo su un’unica linea di vita, l’UML consente una scor­cia­to­ia: la co-region svolge esat­ta­men­te questo compito. Per farlo rie­pi­lo­ga­te sem­pli­ce­men­te le voci degli eventi in­te­res­sa­ti con una parentesi quadra.

Sezione critica:

Uti­liz­zan­do una sezione critica il sistema evita che possano errori ve­ri­fi­car­si quando più processi con­di­vi­do­no le risorse. All’interno di questa area di sistema solo un processo alla volta utilizza la risorsa. Inoltre il sistema dà la priorità al ri­spet­ti­vo processo. Con l’etichetta “critical” definite una sezione critica (in inglese: critical region). Ciò impedisce ad altri operatori di in­te­ra­zio­ne di in­fluen­za­re un frammento so­vraor­di­na­to. Ad esempio blocca le tracce ni­di­fi­ca­te di un frammento parallelo e combinato nel diagramma di sequenza.

Una hotline del fornitore di gas nel grafico sopra accetta più chiamate in parallelo e le inoltra con­tem­po­ra­nea­men­te ai di­pen­den­ti della hotline. Se si tratta tuttavia di un caso di emergenza con sospetto di odore di gas, il sistema dà la priorità al messaggio e inoltra la chiamata al servizio di emergenza at­tra­ver­so la sezione critica (critical region). La sezione critica impedisce che i flussi di in­for­ma­zio­ne del frammento so­vraor­di­na­to vengano evasi in parallelo con il messaggio dalla sezione critica. Solo le linee di vita nella sezione critica si com­por­ta­no in questo modo.

Assertion:

L’operatore di in­te­ra­zio­ne “assertion” imposta lo stato di con­ti­nui­tà. Le sequenze all’interno di un operando con l’etichetta assert sono con­si­de­ra­te come valide con­ti­nua­zio­ni. L’as­ser­zio­ne afferma che tutte le sequenze al di fuori del frammento terminano in tracce non valide.

Ignorare/con­si­de­ra­re

Un diagramma di sequenza UML rap­pre­sen­ta una parte del sistema in dettaglio. Mentre ci sono alcuni messaggi che potete tra­la­scia­re, ce ne sono altri di cui avete bisogno. Uti­liz­za­te l’operatore di in­te­ra­zio­ne “ignore” per escludere alcuni messaggi. Queste in­for­ma­zio­ni emergono nel sistema su una traccia, ma non nel frammento ignore. La notazione prescrive un’etichetta in questa forma: ignore {messaggio1,messaggio2}.

I frammenti combinati con l’operatore di in­te­ra­zio­ne “consider” invece con­si­de­ra­no alcuni messaggi in un frammento. Tutti gli altri messaggi che passano at­tra­ver­so il frammento vengono ignorati dal sistema. I messaggi da includere vanno anche loro racchiusi tra parentesi graffe: consider {messaggio3,messaggio4}.

Questi due operatori hanno compiti in conflitto. Tuttavia entrambi si ve­ri­fi­ca­no spesso in frammenti ni­di­fi­ca­ti. Ad esempio i mo­del­la­to­ri spesso associano assert a ignore (nella seguente forma: assert ignore {Msg1,Msg2}) o assert e consider (nella seguente forma: assert consider {Msg3,Msg4}).

Negativo:

Per con­tras­se­gna­re un errore di sistema si utilizza l’operatore di in­te­ra­zio­ne “negativo”. Il frammento combinato include quindi tracce non valide. Ad esempio l’operatore viene uti­liz­za­to nella rap­pre­sen­ta­zio­ne di un processo di accesso at­tra­ver­so un diagramma di sequenza. Modellate la linea di vita di un attore sulla strada per il time out e in­qua­dra­te questo messaggio di errore con il frammento negativo. L’etichetta per fare questo è neg. At­tra­ver­so la mo­del­la­zio­ne esplicita delle tracce non valide nel frammento combinato negativo tutti gli altri frammenti sono con­si­de­ra­ti positivi. Le loro tracce sono perciò valide.

Sequenza rigorosa:

All’interno di un frammento combinato potrebbe essere im­por­tan­te ri­spet­ta­re un ordine rigoroso. L’etichetta strict impone ai suoi operandi una sequenza rigorosa. Ciò vale per il primo livello del frammento. Gli operandi negli altri frammenti ni­di­fi­ca­ti sono soggetti al loro ordine proprio.

Sequenza debole:

I frammenti combinati con l’operatore di in­te­ra­zio­ne sequence rap­pre­sen­ta­no un ordine debole. Il com­por­ta­men­to tra gli operandi influisce sulle proprietà di traccia piuttosto che sugli operatori di in­te­ra­zio­ne. Pertanto un se­quen­zia­men­to debole può agire come un frammento parallelo. Ciò accade quando gli operandi par­te­ci­pa­no a diverse linee di vita. A propria volta il se­quen­zia­men­to debole diventa un ordine rigoroso quando i suoi operandi appaiono sulla stessa linea di vita. L’etichetta è seq.

Il se­quen­zia­men­to debole è definito dalle seguenti proprietà:

  1. Le spe­ci­fi­che degli eventi all’interno di un operando man­ten­go­no il loro ordine.
  2. Le spe­ci­fi­che degli eventi che operano su dif­fe­ren­ti linee di vita e non si ve­ri­fi­ca­no all’interno dello stesso operando compaiono in ordine ar­bi­tra­rio.
  3. Se le spe­ci­fi­che dell’evento agiscono sulla stessa linea di vita ma in diversi operandi, il loro posto sulla linea di vita prescrive il loro ordine. Il primo operando viene prima del secondo.

Con­ti­nua­zio­ne:

La con­ti­nua­zio­ne (in inglese: con­ti­nua­tion) non è certo un frammento in­di­pen­den­te. Soltanto nei frammenti combinati al­ter­na­ti­va e sequenza debole ottiene la propria semantica, la quale prescrive alla con­ti­nua­zio­ne la stessa forma degli stati: un ret­tan­go­lo con angoli ar­ro­ton­da­ti. In op­po­si­zio­ne allo stato, una con­ti­nua­zio­ne copre op­zio­nal­men­te diverse linee di vita.

A seconda di come or­ga­niz­za­te la con­ti­nua­zio­ne nel diagramma di sequenza, cambia anche il loro compito. Se la con­ti­nua­zio­ne è all’inizio del diagramma di in­te­ra­zio­ne, modellate il com­por­ta­men­to della con­ti­nua­zio­ne. Se invece la con­ti­nua­zio­ne è alla fine del vostro frammento di in­te­ra­zio­ne, essa inoltra il processo al passo suc­ces­si­vo. Se assegnate un nome alla vostra con­ti­nua­zio­ne (come nell’esempio: nonOK), il frammento suc­ces­si­vo sulla linea di vita deve avere una con­ti­nua­zio­ne con lo stesso nome (nonOK) o non potrà modellare alcuna con­ti­nua­zio­ne. Se la con­ti­nua­zio­ne è da sola nel frammento, ciò cor­ri­spon­de a una con­ti­nua­zio­ne alla fine del frammento.

In sintesi
Se volete rap­pre­sen­ta­re gli esempi di ap­pli­ca­zio­ne in modo det­ta­glia­to o con­trol­la­re la logica di un sistema, create un diagramma di sequenza. La notazione vi consente di modellare il flusso del messaggio nel corso della durata di un oggetto. Potete anche rap­pre­sen­ta­re le ope­ra­zio­ni complesse in modo chiaro uti­liz­zan­do frammenti di in­te­ra­zio­ne ni­di­fi­ca­ti. Il diagramma di sequenza è senza dubbio uno dei diagrammi com­por­ta­men­ta­li UML più uti­liz­za­ti.
Vai al menu prin­ci­pa­le