|
|
Le basi del linguaggio UML
1. Introduzione
Cosa è l'UML
e in cosa consiste questo linguaggio.
Nel mondo costantemente in fermento ed in evoluzione
quale e' quello dello sviluppo di applicazioni Object Oriented, diviene sempre
più difficile costruire e gestire applicazioni di alta qualità in tempi brevi.
Come risultato di tale difficoltà e dalla esigenza di avere un linguaggio
universale per modellare gli oggetti che potesse essere utilizzato da ogni
industria produttrice di software, fu inventato il linguaggio UML, la
cui sigla sta per Unified Modeling Language.
In termini pratici, potremmo dire che il linguaggio UML rappresenta, in qualche
modo, una cianografia, un progetto di ingegneria edile, riportato nel
mondo dell'Information Technology.
L'UML è, dunque, un metodo per descrivere l'architettura di un sistema in
dettaglio. Come è facile intuire, utilizzando una sorta di cianografia sarà
molto più facile costruire o manutenere un sistema e assicurarsi che il sistema
stesso si presterà senza troppe difficoltà a futuri cambiamenti dei requisiti.
La forza dell'Unified Modeling Language consiste nel fatto che il processo di
disegno del sistema può essere effettuata in modo tale che i clienti, gli
analisti, i programmatori e chiunque altro sia coinvolto nel sistema di
sviluppo possa capire ed esaminare in modo efficiente il sistema e prendere
parte alla sua costruzione in modo attivo.
Si consideri il seguente esempio: Nessuno di noi acquisterebbe un appartamento
dando come requisito semplicemente il solo fatto che abbia 4 camere da letto, 3
bagni e che sia grande circa 180 metri quadri. Tutti desidereremmo studiare a
tavolino, magari con l'ausilio dell'architetto, tutti i dettagli possibili
(finestre, porte, ecc.) servendoci, a tale scopo, della mappa della casa. In
modo pressoché analogo si può pensare che funzioni la "macchina"
dello sviluppo di sistemi software. Invece di leggere la piantina della casa,
in questo caso ci si servirà dei diagrammi UML che non fanno altro che
documentare in modo esauriente e a tutti i livelli le caratteristiche tecniche
che dovranno essere implementate.
2. Cenni Storici del Linguaggio UML
Breve storia
della nascita del linguaggio UML
Durante gli anni '90 furono introdotte
nel mercato dell'Information Technology parecchie metodologie per il disegno e
la progettazione di sistemi software.
Vi era un problema, però: ognuna di queste tecnologie aveva il suo insieme
proprio di notazioni e simboli, che differiva, a volte in modo rilevante, dalle
altre.
Ognuno di questi metodi aveva, naturalmente, i suoi
punti di forza e i suoi punti deboli.
Ma, successivamente, stavano convergendo verso un'unica visione che
incorporasse le qualità migliori che ognuno di essi aveva mostrato. L'unico
problema che restava era il fatto che ogni metodo portava ancora con sè la
propria notazione. Tale problema non era da sottovalutare in quanto l'uso di
simbologia differente portava facilmente a confusione sul mercato a causa del
fatto che un determinato simbolo poteva avere un significato differente per analisti
e disegnatori differenti.
Finalmente, dopo un periodo di tempo in cui andò avanti la cosidetta "guerra
della metodologia" ci si rese conto che era assolutamente necessario
produrre uno standard che unificasse anche la notazione utilizzata.
Fu così che, nell'Ottobre del 1995, nacque la prima bozza dell'UML.
La prima versione ufficiale, prodotta dall'OMG (Object Management Group) fu rilasciata nel Luglio del 1997 e nel Novembre dello stesso anno l'UML venne adottato come standard.
3. I vantaggi del linguaggio UML Quali sono i vantaggi utilizzando UML?
Elenchiamo, qui di seguito, alcuni dei benefici derivanti dall'utilizzo del linguaggio UML:
Un sistema software grazie al linguaggio UML viene disegnato professionalmente e documentato ancor prima che ne venga scritto il relativo codice, da parte degli sviluppatori. Si sarà così in grado di conoscere in anticipo il risultato finale del progetto su cui si sta lavorando.
Poichè, come detto, la fase di disegno del sistema precede la fase di scrittura del codice, ne consegue che la scrittura del codice stessa è resa più agevole ed efficiente oltre al fatto che in tal modo è più facile scrivere del codice riutilizzabile in futuro. I costi di sviluppo, dunque, si abbassano notevolmente con l'utilizzo del linguaggio UML.
È più facile prevedere e anticipare eventuali "buchi" nel sistema. Il software che si scrive, si comporterà esattamente come ci si aspetta senza spiacevoli sorprese finali.
L'utilizzo dei diagrammi UML permette di avere una chiara idea, a chiunque sia coinvolto nello sviluppo, di tutto l'insieme che costituisce il sistema. In questo modo, si potranno sfruttare al meglio anche le risorse hardware in termini di memoria ed efficienza, senza sprechi inutili o, al contrario, rischi di sottostima dei requisiti di sistema.
Grazie alla documentazione del linguaggio UML diviene ancora più facile effettuare eventuali modifiche future al codice. Questo, ancora, a tutto beneficio dei costi di mantenimento del sistema.
La comunicazione e l'interazione tra tutte le risorse umane che prendono parte allo sviluppo del sistema è molto più efficiente e diretta. Parlare la stessa "lingua" aiuta ad evitare rischi di incomprensioni e quindi sprechi di tempo.
4. Che cos'è il Visual Modeling? Definizione concetto di Visual Modeling e Sistema.
Si è già accennato nell'introduzione circa la
similitudine tra i diagrammi UML e una cianografia. È, però, importante capire
bene ed approfondire un attimo il concetto di "Visual Modeling" prima
di andare avanti.
Abbiamo già utilizzato, precedentemente, il termine Sistema. Ma, prima di
tutto, cosa è esattamente un Sistema (informatico)?
Un Sistema è una combinazione di componenti software e hardware che
fornisce una soluzione ad un'esigenza del mondo reale (business problem).
Per far sì che un Sistema sia efficiente, sarà necessario recepire bene le
richieste del cliente e fare in modo che esse vengano condivise e recepite come
requisiti indispensabili dall'intero team di lavoro. Successivamente, si
useranno tali requisiti per generare il codice necessario alla costruzione del
Sistema assicurandosi, andando avanti nella scrittura del codice, che non si
perda di vista l'obiettivo finale. Tale procedimento prende il nome di "Modeling"
(o, se preferite, modellazione).
Il "veccho" metodo di modeling dei sistemi, conosciuto anche come
"Metodo a Cascata" (Waterfall Method), si basava sul fatto che
i vari passi che costituivano il processo di sviluppo di un sistema fossero
sequenziali (l'inizio di uno avveniva soltanto dopo il termine di un altro).
Quello che accadeva seguendo il waterfall method era che le persone del team si
trovavano a lavorare su task differenti e spesso, non avevano alcun modo di
comunicare a discapito di importanti questioni inerenti il Sistema stesso. Un
altro punto debole del waterfall method era il fatto che esso prevedeva
che si concedesse la maggior parte del tempo alla scrittura del codice,
togliendolo, in tal modo, all'analisi ed al disegno che invece rappresentano la
base per un solido progetto.
Il Visual Modeling, che ha soppiantato ormai
il waterfall method, altro non è che il processo che prevede la visualizzazione
grafica di un modello, utilizzando un insieme ben definito di elementi grafici,
che nel linguaggio UML sono rappresentati dai 9 Diagrammi di base.
Il processo per la costruzione di un Sistema coinvolge molte persone: Prima di
tutto il cliente, ovvero la persona che desidera avere una risoluzione
ad un problema o ad una sua esigenza. Un analista ha il compito di
documentare il problema del cliente e trasmettere tali informazioni agli sviluppatori,
i quali costituiscono la parte del team che si occupa di implementare il
codice, testarlo ( con il supporto di un team apposito per il test) e
installarlo sull'hardware dei computer.
Questo tipo di suddivisione dei compiti è necessario poiché al giorno d'oggi i
sistemi sono diventati davvero molto complessi e la conoscenza è divenuta molto
più specializzata da non poter essere gestita soltanto da una persona.
Il Visual Modeling prevede una continua interazione tra i vari membri del team
di lavoro. Analisti e disegnatori, per esempio, necessitano di un continuo
scambio di vedute per permettere che i programmatori possano basarsi su una
solida informazione. A loro volta, i programmatori devono interagire con gli
analisti ed i disegnatori per condividere le loro intuizioni, modificare i
disegni e consolidare il codice.
Il vantaggio di tale tipo di approccio è che la conoscenza generale del team
cresce notevolmente, ognuno è in grado di capire a fondo il sistema e il
risultato finale non può che essere un sistema più solido (con il cliente più
soddisfatto!).
Il RAD
5. RAD (Rapid Application Development)
Il RAD per lo
sviluppo rapido del progetto.
Un progetto per lo sviluppo di un sistema non può
basarsi sull'improvvisazione ma deve seguire un iter tecnico-logico che
consenta di arrivare in tempi brevi alla soluzione migliore.
Il RAD rappresenta proprio una sorta di "t 929d31j racciato" del
progetto che viene incontro a tale esigenza.
Il RAD (Rapid Application Development), ovvero lo sviluppo rapido di
applicazioni, consiste, fondamentalmente, di cinque sezioni:
Raccolta delle informazioni
Analisi
Disegno
Sviluppo
Deployment
6. Raccolta delle Informazioni
Prima di iniziare
analizziamo le richieste del cliente
Questa azione consiste, a sua volta, di parecchie
altre azioni. Esaminiamole una per una tenendo presente sempre che è di
fondamentale importanza capire bene i requisiti che il cliente richiede.
Soltanto così si otterranno dei sistemi stabili e robusti.
Processo di scoperta del Business.
In questa fase, gli analisti studiano i processi di business del cliente
servendosi di colloqui specifici con il cliente stesso e chiedendogli di
analizzare a fondo i processi rilevanti, passo per passo. Di solito, al termine
di tale attività vengono abbozzati uno o più Activity
Diagrams.
Analisi del Dominio.
L'analista intervista il cliente con lo scopo di capire bene le entità
principali del dominio del cliente. Alla conversazione tra l'analista ed il
cliente, prende parte anche un altro membro del team il quale prende
accuratamente nota di tutto. In particolare, si cerca di porre particolare
attenzione ai termini chiave del dominio che vengono appuntati come possibili
Classi. Al termine di tale analisi, alcuni termini dell'analisi diverranno attributi
mentre determinate azioni, che sono, anch'esse, ritenute di rilevante
importanza, saranno etichettate come operazioni delle classi. Al termine
di tale sezione si produce un Class Diagram
ad alto livello ed una buona serie di appunti).
Identificazione della possibile correlazione tra sistemi.
All'inizio del processo di sviluppo, il team di sviluppo identifica esattamente
le dipendenze tra i vari sistemi, ovvero da quali eventuali sistemi esistenti
il nuovo sistema dovrà dipendere e, viceversa, quali sistemi dovranno dipendere
dal nuovo. Il responsabile di tale fase è, solitamente un System Engineer. Al
termine di tale sezione si produrrà un Deployment
Diagram.
Identificazione dei requisiti di sistema.
Questa fase rappresenta la prima sessione di sviluppo misto (Joint Application
Development - JAD). Infatti, ad essa partecipano i responsabili
dell'organizzazione del cliente, i potenziali utenti e i membri del team di
sviluppo. Può essere utile la presenza di un supervisore che si pone come
obiettivo quello di riuscire a carpire dai responsabili e dagli utenti ciò che
essi realmente desiderano dal sistema. Almeno due membri del team dovrebbero
prendere appunti e rifinire il Class Diagram
disegnato nella precedente fase di Analisi del Dominio.
Presentazione dei risultati al cliente.
Quando il team reputa concluse le operazioni di raccolta delle informazioni, il
Project Manager presenta i risultati
di tale analisi al cliente.
7. Analisi Una volta terminata la raccolta delle informazioni possiamo cominciare ad analizzarle.
A questo punto, il team è pronto per andare a fondo
sui risultati ottenuti dalla raccolta delle informazioni e approfondire,
dunque, la conoscenza del problema. Alcune delle azioni di Analisi iniziano, in
realtà, proprio durante la fase di raccolta delle informazioni quando viene
abbozzato uno "schizzo" del Class Diagram.
Comprensione dell'utilizzo del sistema.
In una sessione JAD (Joint Application Development) con i potenziali utenti, il
team di sviluppo lavora con gli utenti per definire gli actors (Con tale
termine si può intendere sia una persona che un sistema, ma ne parleremo in
seguito) che interagiscono con ogni singolo use case (caso d'uso) sia come beneficiari
che come iniziatori dello stesso use case. È questo il momento in cui vengono
prodotti gli Use Case Diagrams.
Consolidare gli Use Cases.
È importante continuare a lavorare con gli utenti al fine di verificare ogni
singolo use case in base alla sequenza di azioni che ognuno di essi descrive.
Durante tale fase, viene aggiunta una descrizione testuale ai singoli passi di
ogni use case diagram.
Rifinire i Class Diagrams.
La persona incaricata di modellare gli oggetti, durante la sessione JAD, dovrà
porre la massima attenzione alle discussioni e alle richieste dei clienti al
fine di rifinire i vari diagrammi delle classi. Tale operazione può consistere
nel dare dei nomi appropriati alle classi, alle associazioni, alle classi
astratte, alle generalizzazion e alle aggregazioni. È questo il momento in cui
il Class Diagram diviene più dettagliato.
Analizzare i cambi di stato negli oggetti.
Durante la creazione dei modelli, sarà importante anche porre attenzione alla
descrizione di eventuali cambi di stato di un oggetto, dove questo si renda
necessario. Vengono prodotti in questa fase gli State
Diagrams.
Definire le interazioni tra gli oggetti.
Fino ad ora il team di lavoro è arrivato a mettere giù un insieme di Use Cases
e di Class Diagrams più o meno rifiniti. È ora tempo di definire come gli
oggetti descritti interagiranno tra di loro. Il responsabile della descrizione
dei modelli dovrà sviluppare un insieme di diagrammi che includano i cambi di
stato. È qui che vengono prodotti i Sequence
Diagrams e i Collaboration Diagrams.
Analizzare l'integrazione del sistema da sviluppare con gli altri sistemi
preesistenti.
Il System Engineer, procedendo in parallelo con tutte le fasi descritte sin
qui, scopre ed analizza tutti i dettagli relativi alla integrazione del sistema
che si intende sviluppare con eventuali sistemi pre-esistenti o comunque
sistemi con i quali sarà necessario cooperare. Le domande che sarà opportuno
porsi per tale operazione saranno qualcosa del tipo: Quale tipo di
comunicazione viene utilizzata? Come è fatta l'architettura della rete? Il
sistema dovrà interagire con un database? Se si, con quali tipi di database? In
tale fase verranno costruiti i Deployment
Diagrams.
8. Disegno In questa fase vengono definiti i contorni del progetto.
Durante la fase di disegno, il team lavora in base ai
risultati che sono stati forniti dall'analisi al fine di disegnare la
soluzione. Il Disegno e l'Analisi necessitano, a questo punto, di essere
aggiornati vicendevolmente fin quando non si reputa che la fase di disegno sia
completata.
Sviluppare e rifinire gli Object Diagrams.
I programmatori leggono il class diagram e generano tutti gli Object Diagrams
necessari anche in base all'esame di ogni operazione. Parallelamente si
sviluppa un corrispondente activity diagram. Tale Activity
Diagram costituirà la base per la maggior parte della scrittura del
codice nella fase di sviluppo.
Sviluppare i Component Diagrams.
Durante tale fase i programmatori giocano un ruolo molto importante. Il lavoro
principale, in questo caso, consiste nel visualizzare i componenti che
prenderanno parte nella fase successiva e mostrare le dipendenze tra loro. È in
questa fase che vengono prodotti i Component
Diagrams.
Pianificare il Deployment del sistema.
Dopo aver costruito il Component Diagram il System Engineer inizia a
pianificare il deployment dell'intero sistema per gestire le varie interazioni
con altri sistemi. I diagrammi così creati mostreranno dove i componenti
risiederanno.
Disegnare e creare un prototipo dell'interfaccia utente.
Tale fase richiede un'altra sessione JAD con gli utenti come continuazione
della precedente. Tale fase costitusce un punto intermedio tra Analisi e
Disegno. Un analista GUI (Graphical User Inteface) lavora con gli utenti per
sviluppare prototipi su carta di come il sistema si interfaccierà con l'utente
finale. In questa fase vengono prodotte delle stampe dei prototipi delle possibili interfacce utente.
Disegno dei Test.
Per sviluppare questa fase è consigliabile avvalersi di uno sviluppatore o di
un tester esperto che non appartenga però al team di sviluppo del sistema. Egli
utilizzerà gli Uses Cases diagrams per sviluppare dei casi di test (Test Cases) che siano, preferibilmente,
automatizzati.
Inizio della Documentazione.
Uno o più specialisti della documentazione lavorano con i disegnatori del
sistema per iniziare la documentazione ed arrivare man mano ad una struttura di
alto livello per ogni documento. Viene prodotta in questa fase una bozza di
documentazione.
9. Sviluppo Concretizziamo ciò che abbiamo raccolto.
Se le precedenti fasi di analisi e disegno sono state
eseguite con accuratezza e scrupolo, la fase dello sviluppo non potrà che
scorrere velocemente e senza grossi intoppi.
Implementazione del Codice.
Con i Class Diagrams, gli Object Diagrams, gli Activity Diagrams e i Component
Diagrams a disposizione, i programmatori implementano il codice per il sistema.
Test del Codice.
Ogni nuova implementazione del codice sarà, necessariamente interfacciata con
una opportuna fase di test. Si può, praticamente, dire che le due fasi
camminano di pari passo fin quando il codice supera tutti i livelli di test
sviluppati nella fase di disegno. Vengono prodotti in questa fase i risultati
del Test.
Costruzione della Interfaccia Utente e collegamento al codice.
Questa fase si può considerare come un legame tra Disegno e Sviluppo. Qui, uno
specialista GUI costruisce dei prototipi di interfaccia e che dovranno essere
collegati al codice. Naturalmente tale collegamento necessita di una opportuna
fase di test e verifica. A questo punto si dovrebbe avere a disposizione il
Sistema funzionante completo con l'interfaccia utente.
Completamento della documentazione.
Il completamento del sistema permette agli esperti della documentazione di
terminare la stesura di tutto il materiale necessario per descrivere il
sistema.
10. Deployment
A questo
punto possiamo installare il sistema sull'hardware
Quando la fase di sviluppo (development) è
completata, il sistema viene installato sull'hardware appropriato ed integrato
con i sistemi con cui deve interagire. Questa fase prende il nome di Deployment.
Pianificare un piano per il backup ed il recupero delle informazioni.
Questa fase, in realtà, può anche iniziare molto prima che lo sviluppo del
sistema inizi. Il System Engineer crea un piano che descriverà i passi da
seguire nel caso in cui il sistema dovesse andare in crash (Piano di Crash Recovery).
Installare il sistema completo sull'hardware appropriato.
Questo passo viene eseguito dal System Engineer con l'eventuale supporto
necessario da parte dei programmatori.
Testare il sistema installato.
Dopo aver installato il software sulle macchine appropriate, il team di
sviluppo testa il sistema. Le domande che sarà opportuno chiedersi in questa
fase sono del tipo: Il sistema si comporta come ci si aspettava? Il piano di
backup e di recovery funzionano? A seconda del risultato di tali test si
deciderà se è opportuno un ulteriore raffinamento del sistema.
Festeggiare il risultato ottenuto.
Anche questa fase, che non ha certo delle caratteristiche tecniche, riveste una
grande importanza. Se tutto funziona a dovere è giusto andare a festeggiare il
successo ottenuto con l'intero team.
L'applicazione pratica dell'UML
11. Gli Strumenti di lavoro UML
Quale
strumento utilizzare per agevolare il lavoro?
Come ogni linguaggio che si rispetti anche l'UML
necessita dell'utilizzo di tools appropriati che ne agevolino l'utilizzo.
L'utilizzo di carta e penna è sicuramente sempre valido ma non può certamente
garantire da solo un risultato apprezzabile. Ci sono sul mercato tanti tools
che trattano l'UML. Probabilmente, però, il più diffuso è lo strumento della
Rational, Il Rose.
Il Rational Rose è stato disegnato per fornire ai team di sviluppo tutti gli
strumenti necessari per il modellamento di soluzioni robuste ed efficienti.
La Microsoft ha prodotto uno strumento che permette di definire un sottoinsieme dei modelli che il Rational Rose mette a disposizione: il Microsoft Visual Modeler. Diciamo che tale software può essere consigliato a chi si avvicina per la prima volta al mondo del Visual Modeling
12. Componenti UML Elementi e diagrammi che costituiscono l'UML
Il linguaggio UML contiene svariati elementi grafici
che vengono messi insieme durante la creazione dei diagrammi. Poiché l'UML è un
linguaggio, esso utilizza delle regole per combinare i componenti del
linguaggio nella creazione dei diagrammi.
L'obiettivo dei diagrammi è quello di costruire molteplici viste di un sistema
tutte correlate tra di loro. L'insieme di tali viste costituirà quello che
abbiamo definito Visual Modeling.
Passiamo ora in rassegna, brevemente, tutti i diagrammi UML, prima di
analizzarli più dettagliatamente in seguito.
Il linguaggio UML consiste di nove diagrammi di base, ma si tenga presente che
è assolutamente possibile costruire e aggiungere dei diagrammi differenti dagli
standard (che vengono definiti ibridi) rispetto a quelli definiti dal
linguaggio.
Class Diagram
Per avere una idea immediata di cosa sia una classe possiamo usare come esempio
il fatto che tutti gli oggetti o esseri viventi, spesso, sono riconducibili a
determinate categorie (ad esempio: computers, automobili, piante, animali,
ecc.). Queste categorie costituiscono le classi.
Definizione:Una classe è una categoria o un gruppo di oggetti (con questo termine includiamo, per comodità anche gli esseri viventi) che hanno attributi simili e comportamenti analoghi.
I Class Diagrams forniscono le rappresentazioni
utilizzate dagli sviluppatori.
Object Diagram
Un oggetto è una istanza di una classe - ovvero un qualcosa di specifico che ha dei valori
determinati per i suoi attributi e dei comportamenti specifici.
Use Case Diagram
Uno Use Case (caso d'uso) è una descrizione di un comportamento
particolare di un sistema dal punto di vista dell'utente. Per gli sviluppatori,
gli use case diagram rappresentano uno strumento notevole: infatti tramite tali
diagrammi, essi possono agevolmente ottenere una idea chiara dei requisiti del sistema
dal punto di vista utente e quindi scrivere il codice senza timore di non aver
recepito bene lo scopo finale. Nella rappresentazione grafica, viene utilizzato
un simbolo particolare per l'actor (l'utente o un altro sistema che
interagisce) che vedremo in seguito.
Definizione: L'actor è l'entità che interagisce con uno use case facendo partire la sequenza di azioni descritte dallo use case stesso e, eventualmente, ricevendo delle precise risposte dal sistema.. Puo' essere una persona o anche un altro sistema.
State Diagram
Ad un determinato istante, durante il funzionamento del sistema, un oggetto si
trova in un particolare stato. Gli State Diagrams rappresentano tali stati, ed
i loro cambiamenti nel tempo. Ogni state diagram inizia con un simbolo che
identifica lo stato iniziale (Start State) e termina con un altro simbolo che
rappresenta lo stato finale (End State). Per esempio, ogni persona può essere
identificato dai seguenti stati: neonato, infante, bambino, adolescente,
adulto, anziano.
Sequence Diagram
I class diagrams e gli object diagrams rappresentano informazione statica. In
un sistema funzionante, tuttavia, gli oggetti interagiscono l'uno con l'altro,
e queste interazioni avvengono in relazione al trascorrere del tempo. Il
sequence diagram mostra le dinamiche, basate sul tempo, delle varie interazioni
tra gli oggetti.
Activity Diagram
Le attività che si riscontrano all'interno di use case o all'interno del
comportamento di un oggetto accadono, tipicamente, in una sequenza ben
definita. Tale sequenza viene rappresentata con gli activity diagrams.
Collaboration Diagram
Gli elementi di un sistema lavorano insieme per realizzare e soddisfare le
necessità del sistema. Un linguaggio di modellazione deve avere un modo per
rappresentare tale cooperazione. Il Collaboration Diagram nasce proprio per
questa ragione.
Component Diagram
Oggi, nell'ingegneria del software viene sempre più utilizzato il modello di
organizzazione secondo il quale ognuno nel team di lavoro si occupa di lavorare
su un componente differente. Il component diagram descrive questa importante
caratteristica.
Deployment Diagram
Il Deployment Diagram mostra l'architettura dal punto di vista fisico e
logistico di un sistema. Tale diagramma può descrivere i computer e i vari
dispositivi presenti, mostrare le varie connessioni che intercorrono tra di
essi e, ancora, il software che è installato su ogni macchina.
Una domanda che ci si potrebbe porre a questo punto è la seguente: Ma è
proprio necessario sviluppare tutti e nove i diagrammi che l'UML mette a
disposizione?
La risposta a questa domanda può variare in relazione alla complessità del
Sistema che si intende costruire ma, in linea di massima, tende ad essere
affermativa. La ragione di ciò consiste nel fatto che, come si è già detto, i
diagrammi UML sono stati pensati per venire incontro all'esigenza di rendere il
Sistema comprensibile da differenti persone con differenti figure
professionali.
13. Rappresentazione di una classe Gli oggetti in UML vengono distinti in categorie, vediamo come.
Si è detto precedentemente che gli oggetti possono
essere suddivisi in categorie e, quindi, in classi. Il Class Diagram del linguaggio UML consiste di
svariate classi connesse tra di loro tramite delle relazioni.
Prima di tutto, però, è importante definire graficamente una classe in UML:
Una classe viene rappresentata da un rettangolo. Il nome della classe, per convenzione, è una parola con l'iniziale maiuscola ed appare vicino alla sommità del rettangolo. Se il nome della classe definita consiste di una parola composta a sua volta da più parole allora viene utilizzata la notazione in cui tutte le iniziali di ogni parola sono scritte in maiuscolo.
Definizione generica di una classe
Un attributo rappresenta una proprietà di una classe. Esso descrive un insieme
di valori che la proprietà può avere quando vengono istanziati oggetti di
quella determinata classe. Una classe può avere zero o più attributi.
Un Attributo il cui nome è costituito da una sola parola viene scritto sempre
in caratteri minuscoli. Se, invece, il nome dell'attributo consiste di più
parole (es: Informazioni-Cliente) allora il nome dell'attributo verrà scritto
unendo tutte le parole che ne costituiscono il nome stesso con la particolarità
che la prima parola verrà scritta in minuscolo mentre le successive avranno la
loro prima lettera in maiuscolo. Nell'esempio appena visto l'attributo sarà
identificato dal termine: informazioniCliente.
La lista degli attributi di una classe viene separata graficamente dal nome
della classe a cui appartiene tramite una linea orizzontale.
Nell'icona della classe, come si vede nella figura precedente, è possibile specificare un tipo in relazione ad ogni attributo (string, float, int, bool, ecc.). E' anche possibile specificare un valore di default che un attributo può avere.
Un'Operazione è un'azione che gli oggetti di una certa classe possono compiere. Analogamente al nome degli attributi, il nome di un'operazione viene scritto con caratteri minuscoli. Anche qui, se il nome dell'operazione consiste di più parole, allora tali parole vengono unite tra di loro ed ognuna di esse, eccetto la prima, viene scritta con il primo carattere maiuscolo. La lista delle operazioni (metodi) viene rappresentata graficamente sotto la lista degli attributi e separata da questa tramite una linea orizzontale.
Anche I metodi possono avere delle informazioni addizionali. Nelle parentesi che seguono il nome di un'operazione, infatti, è possibile mostrare gli eventuali parametri necessari al metodo insieme al loro tipo. Infine, se il metodo rappresenta una funzione è necessario anche specificare il tipo restituito.
Altre informazioni addizionali che possono essere
unite agli attributi di una classe sono le "Constraints" e le
Note.
Le "Constraints" sono delle caselle di testo racchiuse tra
parentesi. All'interno delle parentesi viene specificata una o più regole che
la classe è tenuta a seguire obbligatoriamente.
Le Note solitamente sono associate con gli attributi e/o con i metodi. Esse forniscono
una informazione aggiuntiva ad una classe. Una nota può contenere sia elementi
grafici che elementi di testo.
Come si può riuscire a discernere le classi da utilizzare dalla intervista
con il cliente?
E' necessario, a tal fine, prestare particolare attenzione ad i nomi che i
clienti usano per descrivere le entità del loro business. Tali nomi saranno
ottimi candidati per diventare delle classi nel modello UML. Si deve prestare,
altresì, attenzione ai verbi che vengono pronunciati dai clienti. Questi
costituiranno, con molta probabilità, i metodi (le operazioni) nelle classi
definite. Gli attributi di una classe verranno stabiliti con le analoghe
modalità utilizzate per i nomi delle classi.
14. Associazioni Definiamo il concetto di associazione
Quando più classi sono connesse
l'una con l'altra da un punto di vista concettuale, tale connessione viene
denominata associazione.
Graficamente, un'associazione viene rappresentata con una linea che connette
due classi, con il nome dell'associazione appena sopra la linea stessa.
Quando una classe si associa con un'altra, ognuna di
esse gioca un ruolo all'interno dell'associazione. E' possibile mostrare questi
ruoli sul diagramma, scrivendoli vicino la linea orizzontale dalla parte della
classe che svolge un determinato ruolo, come si vede nella figura precedente.
Un'associazione può essere più complessa del concetto di connettere una classe
ad un'altra. E' possibile, infatti che più classi possano connettersi ad una
singola classe.
Qualche volta un'associazione tra due classi deve seguire una regola. Tale
regola si indica inserendo una "constraint" vicino la linea che
rappresenta l'associazione.
Esattamente come una classe,
un'associazione può avere attributi ed operazioni. In questo caso si parla di
una Classe Associazione (vedasi figura precedente).
Le classi associazione vengono visualizzate allo stesso modo con cui si mostra
una classe normale. Si utilizza una linea tratteggiata per connettere una
Classe Associazione alla linea di associazione.
La molteplicità è un tipo speciale di associazione in cui si mostra il numero di oggetti appartenenti ad una classe che interagisce con il numero di oggetti della classe associata. Una classe, in generale, può essere correlata ad una altra nei seguenti modi:
Uno ad uno
Uno a molti
Uno ad uno o più
Uno a zero o uno
Uno ad un intervallo limitato (es.: 1 a 2 - 20)
Uno ad un numero esatto n
Uno ad un insieme di scelte (es.: 1 a 5 o 8)
Il linguaggio UML utilizza un asterisco (*) per
rappresentare le opzioni "molti" e "più".
Qualche volta, una classe può trovarsi in associazione con se stessa. Ciò si
verifica quando una classe contiene oggetti che possono giocare svariati ruoli.
Tali associazioni sono chiamate: "Associazioni Riflessive".
Associazione Riflessiva
Senza le relazioni, un modello di classi sarebbe soltanto una lista di
rettangoli che rappresentano un "vocabolario" del sistema. Le
relazioni mostrano come i termini del vocabolario si connettono tra di loro per
fornire un quadro della fetta di sistema che si sta modellando. L'associazione
rappresenta, dunque, la connessione concettuale fondamentale tra le classi in
cui ogni classe, come detto, gioca un ruolo specifico
15. Ereditarietà e Generalizzazione Chiariamo il concetto.
Se si conosce qualcosa riguardo ad
una categoria di cose, automaticamente si conosce qualcosa che è possibile
trasferire ad altre categorie che, in qualche modo, discendono dalla categoria
che conosciamo. Chiariamo meglio questo concetto.
Ad esempio, se si conosce qualcosa su un animale generico (ad esempio si sa che
un animale mangia, dorme, è nato, si sposta da un luogo ad un altro., ecc.),
potremo dire che tutte le sottocategorie di animali (rettili, anfibi,
mammiferi, ecc.) erediteranno le stesse caratteristiche. Tale meccanismo, in
Analisi Object Oriented, viene definito come: Ereditarietà
Un esempio di ereditarietà
Una classe figlia (o sottoclasse) può ereditare gli attributi e le operazioni
da un'altra classe (che viene definita classe padre o super classe) che sarà
sempre più generica della classe figlia.
Nella generalizzazione, una classe figlia può rappresentare un valido sostituto
della classe padre. Cioè, in qualunque posto appaia la classe padre, sarebbe
possibile far apparire la classe figlia. Il viceversa non è, invece, vero.
In UML l'ereditarietà viene rappresentata con una linea che connette la classe
padre alla classe discendente e dalla parte della classe padre si inserisce un
triangolo (una freccia).
Se ragioniamo dal punto di vista dell'associazione, l'ereditarietà può essere
vista come un tipo di associazione.
Come devono fare gli analisti per scoprire l'ereditarietà di una o più classi?
L'analista deve far si che gli attributi e le operazioni per una classe siano
generali e si applichino a parecchie altre classi (le sottoclassi) che, a loro
volta, potranno "specializzare" la classe padre aggiungendo attributi
e operazioni propri. Un'altra possibilità è che l'analista noti che due o più
classi hanno un numero di attributi ed operazioni in comune.
Le classi che non permettono di istanziare nessun tipo di oggetto sono dette
classi astratte. In UML una classe astratta si indica scrivendo il suo nome in
corsivo.
Riassumendo si può dire che una classe può ereditare attributi ed
operazioni da un'altra classe. La classe che eredita è figlia della classe
(padre) da cui prende gli attributi e le operazioni. Le classi astratte sono
utilizzate soltanto come classi base per l'ereditarietà e non forniscono alcun
oggetto implementabile.
16. Aggregazioni Le classi che costituiscono i componenti di un'aggregazione.
Qualche
volta una classe può rappresentare il risultato di un insieme di altre classi
che la compongono. Questo è un tipo speciale di relazione denominata aggregazione.
Le classi che costituiscono i componenti e la classe finale sono in una
relazione particolare del tipo: parte - intero (part-whole)
Un'aggregazione è rappresentata come una gerarchia in cui l' "intero"
si trova in cima e i componenti ("parte") al di sotto. Una linea
unisce "l'intero" ad un componente con un rombo raffigurato sulla
linea stessa vicino all' "intero".
Un esempio di aggregazione
Esaminiamo le "parti" che costituiscono un Televisore. Ogni TV ha un
involucro esterno (Box), uno schermo, degli altoparlanti, delle resistenze, dei
transistors, un circuito integrato e un telecomando (oltre, naturalmente, ad
altri tantissimi componenti!). Il telecomando può, a sua volta, contenere le
seguenti parti: resistenze, transitors, batterie, tastiera e luci remote.
Il Class Diagram che ne deriva sarà il seguente:
Qualche
volta l'insieme di possibili componenti di un'aggregazione si identifica in una
relazione OR. Per modellare tale situazione, è necessario utilizzare una
constraint - la parola OR all'interno di parentesi graffe su una linea tratteggiata
che connette le due linee parte-intero.
Una composizione è una tipo più forte di aggregazione. Ogni componente
in una composizione può appartenere soltanto ad un "intero". Il
simbolo utilizzato per una composizione è lo stesso utilizzato per un'aggregazione
eccetto il fatto che il rombo è colorato di nero.
Se, ad esempio, si esamina l'aspetto esterno degli uomini, si evincerà che ogni
persona ha (tra le altre cose): una testa, un corpo, due braccia. e due gambe.
Tale concetto viene rappresentato nel seguente grafico:
Una associazione composita. In tale associazione ogni
componente appartiene esattamente ad un intero
Riepilogando diciamo che un'aggregazione specifica un'associazione di
tipo "parte - intero" in cui una classe che rappresenta l'
"intero" è costituita da più classi che la compongono.
Una composizione è una forma più forte di aggregazione in cui un componente può
appartenere soltanto ad un "intero". Le aggregazioni e le
composizioni sono rappresentate come linee che uniscono l' "intero" e
il componente singolo tramite, rispettivamente, un rombo aperto e un rombo
riempito di nero, entrambi disegnati dalla parte dell' "intero".
17. Interfacce e Realizzazioni
Utilizziamo
le interfacce per definire le operazioni
Finora abbiamo detto che è importante definire le classi in
base all'intervista fatta con il cliente, e far sì che tali classi vengano
messe nelle corrette relazioni tra di loro. Tuttavia, è possibile che alcune
classi non siano correlate ad una particolare classe padre e che il loro
comportamento possa includere alcune operazioni tutte recanti lo stesso nome.
In tal caso esiste la possibilità di definire tali operazioni per una classe e
riutilizzarle per le altre: è proprio quello che avviene tramite l'utilizzo
delle interfacce.
Un'interfaccia è un insieme di operazioni che specifica alcuni aspetti del
comportamento di una classe; in altre parole, si può dire che un'interfaccia
rappresenta un insieme di operazioni che una classe offre ad altre classi.
Definizione: Un'interfaccia viene modellata allo stesso modo in cui viene modellato il comportamento di una classe e rappresenta un insieme di operazioni che una classe offre ad altre classi. |
Per modellare un'interfaccia si utilizza lo stesso modo utilizzato per
modellare una classe, con un rettangolo. La differenza consiste nel fatto che
un'interfaccia non ha attributi ma soltanto operazioni (metodi). Un altro modo
utilizzato in UML per rappresentare le interfacce è quello che utilizza un
piccolo cerchio che si unisce tramite una linea alle classi che implementano
l'interfaccia stessa.
La tastiera del computer è un tipico esempio di interfaccia riutilizzabile. La
pressione di un tasto (KeyStroke) rappresenta un'operazione che è stata
riutilizzata dalla macchina per scrivere. La collocazione dei tasti è la stessa
della macchina per scrivere, ma il punto cruciale è che la pressione di un
tasto è stata trasferita da un sistema (i due sistemi, come si evince
facilmente, nel nostro caso sono la macchina per scrivere ed il computer) ad un
altro. D'altro canto, sulla tastiera dei computer si trovano un insieme di
operazioni che non si trovano sulla macchina per scrivere (Ctrl, Alt, PageUp,
PageDown, ecc.)
Una interfaccia è una collezione di operazioni che
una classe esegue
Per distinguere le interface dalle classi, dal punto di vista UML si utilizza
la scrittura interface all'inizio del nome di ogni interfaccia,
come mostrato nella figura precendente.
La relazione tra una classe ed un'interfaccia viene definita realizzazione.
Tale relazione è visualizzata nel modello da una linea tratteggiata con un
triangolo largo aperto costruito sul lato dell'interfaccia
18. Visibilità
Attribuiamo
le possibilità di utilizzo alle varie classi
La Visibilità si applica ad
attributi o operazioni e specifica la possibilità che hanno le classi di usare
gli attributi e le operazioni di un'altra classe.
Sono consentiti tre livelli di visibilità:
Livello pubblico: L'utilizzo viene esteso a tutte le classi
Livello protetto: L'utilizzo è consentito soltanto alle classi che derivano dalla classe originale
Livello privato: Soltanto la classe originale può utilizzare gli attributi e le operazioni definite come tali.
A livello grafico vengono utilizzati, generalmente, i seguenti simboli per distinguere i tre livelli:
Livello pubblico: +
Livello protetto: #
Livello privato: -
Il Rational Rose, invece, utilizza i seguenti simboli, per le operazioni:
Livello pubblico:
Livello protetto:
Livello privato:
E gli stessi, con il colore differente, per gli attributi:
Livello pubblico:
Livello protetto:
Livello privato:
Class Diagram
19. Class Diagram - Un esempio pratico
Proviamo a
creare un documento
Prendiamo come esempio una
applicazione classica: quella che permette di scrivere un documento di testo.
Cerchiamo di descrivere i passi che costituiscono tale applicazione.
Supponiamo che si stia digitando un documento di testo, utilizzando qualche
famoso editor di testi, come Microsoft Word, ad esempio. L'utente ha due
possibilità iniziali:
Cominciare a scrivere un nuovo documento
Aprire un documento esistente
Il testo da scrivere, ovviamente, verrà digitato
tramite l'utilizzo della tastiera.
Ogni documento è composto di svariate pagine, e ogni pagina, a sua volta, è
composta da una testata, dal corpo del documento e da un piè di pagina. Nella
intestazione e nel piè di pagina è possibile aggiungere la data, l'ora, il
numero di pagina, la collocazione del file, ecc.
Il corpo del documento è formato da frasi. Le frasi, a loro volta, sono
composte da parole e segni di punteggiatura. Le parole sono formate da lettere,
numeri e/o caratteri speciali. Inoltre,. Vi è la possibilità di aggiungere
delle immagini e delle tabelle nel documento. Le tabelle sono costituite da
righe e colonne ed ogni cella di una tabella può contenere del testo o delle
immagini.
Dopo aver terminato il documento, l'utente può scegliere di salvarlo o
stamparlo.
Abbiamo in tal modo descritto, in maniera semplificata ma congruente, il
processo di creazione di un documento tramite Microsoft Word. Rifacendoci a
quanto già detto circa l'intervista con il cliente, siamo in grado, allora, di
estrarre la seguente lista di parole chiave:
documento , editor di documenti, Microsoft Word, testo
, tastiera, intestazione, piè pagina, corpo del documento, data, ora,
numero di pagina, collocazione del file, pagina, frase, parola, segno di
punteggiatura, lettera, numero, carattere speciale, immagine, tabella, riga,
colonna, cella, utente.
Potremmo dire che le parole chiave evidenziate sono sicuramente candidate a
diventare classi o attributi per il modello da sviluppare.
Come è possibile osservare, nell'esempio descritto l'oggetto attorno a cui
ruota un po' tutto il discorso è il Documento. Per tale ragione, sarà
una buona idea identificare nel Documento la classe centrale del nostro Class Diagram.
Un documento, come detto, può avere svariate pagine e, quindi, potremo definire
un attributo: numeroDiPagine che descrive tale caratteristica. Invece, per le
operazioni, sarà bene definire i metodi: Apri( ), Salva( ), Stampa( ),Nuovo(
). Si è detto, poi, che ogni documento è composto di pagine. La Pagina
sarà, dunque, un buon candidato per essere una classe del nostro diagramma.
La Classe Pagina conterrà un attributo : numeroDiPagina,
che identificherà il numero della pagina dell'oggetto, e le seguenti
operazioni: nuovaPagina(), nascondiIntestazione() e nascondiPièdiPagina().
I metodi per la testata e il piè di pagina ci fanno intendere che è bene
definire altre due classi: Intestazione e PiePagina.
Tali classi hanno i seguenti attributi in comune: data, ora, numeroDiPagina
e pathFile. Tali attributi sono opzionali per ogni intestazione o pie' di
pagina e l'utente potrà configurarli a suo piacimento.
La somiglianza tra Intestazione e PièPagina ci spinge a definire ancora una
nuova classe che sia in comune alle due appena descritte. È qui che utilizziamo
il concetto di ereditarietà che abbiamo definito in precedenza.
La classe padre sarà BottomUp (questo nome è scelto perché le
intestazioni e i piè di pagina appaiono, rispettivamente, nella parte alta e
bassa di ogni pagina del documento) e conterrà gli attributi che sono in comune
alle classi Intestazione e PiePagina oltre alle operazioni (anch'esse in
comune) : visualizza(), modifica() e nascondi().
Le classi Intestazione e PiePagina (figlie di BottomUp) avranno la necessità,
quindi, di definire, rispettivamente, soltanto le operazioni: nuovaIntestazione()
e nuovoPiePagina().
Prima di passare ad esaminare il corpo del documento
o il testo, diamo uno sguardo alla definizione dei componenti di un testo. Come
detto, il testo del documento è composto di frasi. Le frasi, a loro volta, sono
composte di parole e le parole sono formate da caratteri. Se le parole sono,
dunque, array di caratteri e le frasi sono identificabili come array di parole,
allora una frase è anche (per una sorta di proprietà transitiva) un array di
caratteri.
Quindi, il corpo di un documento può essere descritto come un array di
caratteri. Per tale ragione, per descrivere il testo di un documento faremo uso
della classe Carattere con alcune sottoclassi.
La classe Carattere avrà gli attributi: codiceASCII e tipo (il tipo ci
informa sulla tipologia di carattere, ovvero se esso è in formato normale,
corsivo, grassetto o sottolineato) e definirà le operazioni: Normale(),
Corsivo(), Grassetto() e Sottolineato().
Come discendenti della classe Carattere definiremo poi: Lettera,
SegnoDiPunteggiatura, CarattereSpeciale e Numero.
Inoltre, nel corpo del documento, come detto, possono comparire tabelle o
immagini. Entrambe costituiranno altre due nuove classi nel nostro diagramma.
La Classe Tabella contiene gli attributi numeroDiRighe
e numeroDiColonne e definisce le operazioni inserisciRiga( ) e inserisciColonna(
).
Ogni tabella consiste di una o più celle e, come già detto, in ogni cella è
possibile che compaiano testo o immagini.
Dovremmo essere ad un buon punto per iniziare a mettere insieme tutti i tasselli finora definiti. Utilizzando le associazioni tra le classi che abbiamo descritto otterremo dunque il seguente Class Diagram che descrive il nostro esempio:
Use Case Diagram
20. Use Case Diagrams
Esaminiamo un
diagramma dinamico.
I Class
Diagrams forniscono una visione statica delle classi che
intervengono nella creazione di un Sistema. Il tipo di diagramma che andiamo a
vedere adesso presenterà, invece, una visione dinamica e mostrerà come il
sistema e le relative classi cambino con il passare del tempo.
La visione statica aiuta gli analisti nella comunicazione con il cliente. La
visione dinamica del Sistema, d'altra parte, fornisce agli analisti un valido
mezzo per instaurare un dialogo chiaro con il team degli sviluppatori ed aiuta
gli sviluppatori stessi a creare i programmi.
Esattamente come il Class Diagram rappresenta un ottimo modo per stimolare il cliente
a parlare sul sistema dal suo punto di vista, lo Use
Case Diagram rappresenta un eccellente strumento per stimolare dei
potenziali utenti a intervenire con le loro critiche ed opinioni sulla
funzionalità che il Sistema dovrà avere.
Non è sempre facile per gli utenti riuscire a spiegare tecnicamente come essi
intendano costruire il sistema desiderato; infatti, accade sempre più spesso
che essi in realtà sappiano esprimersi meglio dal punto di vista pratico che
non dal punto di vista prettamente tecnico. Lo Use
Case (Caso d'uso) è allora lo strumento ideale per aitare a
"rompere il ghiaccio".
Le interviste con gli utenti iniziano facendo uso della terminologia del
dominio ma poi deviano ed utilizzano la terminologia del cliente. I risultati
iniziali delle interviste devono portare alla definizione di Actors
(attori) e use cases ad alto livello che descrivano i requisiti funzionali in
termini generali. Già questa informazione è in grado di fornire i limiti e gli
scopi del sistema che si intende sviluppare.
Nelle interviste successive con gli utenti si cercherà di approfondire
maggiormente tali requisiti, portando così alla definizione di modelli use case
che soddisfino le relazioni di inclusione e estensione.
In questa fase è importante la comprensione del dominio, poiché se si hanno
lacune in tal senso potrebbe accadere che si sviluppino troppi use cases e che
ciò possa provocare un rallentamento nel processo di analisi.
Gli Use Case sono collezioni di scenari che riguardano l'utilizzo del sistema in
cui ogni scenario descrive una sequenza di eventi.
La sequenza di eventi descritta da uno Use Case viene iniziata da una persona,
o da un altro sistema o da un pezzo di hardware o ancora dal passare del tempo.
Le entità che iniziano la sequenza di eventi sono definiti Actors. Il risultato
della sequenza deve portare a qualcosa di utile all'actor che ha iniziato la
sequenza o, anche, ad un differente actor.
È anche possibile riutilizzare gli use cases. Per far ciò si possono usare due
modi:
Inclusion: Questo modo permette di utilizzare i passi appartenenti ad una sequenza di un use case e inglobarli in un altro use case.
Extension: Tramite questo metodo è possible creare un nuovo use-case semplicemente aggiungendo dei passi ad un use case esistente.
Vedremo ora come rappresentare un modello Use Case e visualizzare le relazioni tra più use cases.
21. Introduzione all'Use Case Model Vediamo insieme come rappresentare un modello Use Case
Un actor inizia la sequenza di un particolare use case, ed un actor (possibilmente lo stesso che ha iniziato, ma non necessariamente) riceve un ritorno dallo use case.
Graficamente, un ellisse rappresenta
un use case ed un omino rappresenta un actor. L'actor che inizia la sequenza di
eventi di un use-case viene sempre inserito alla sinistra dell'use case mentre,
al contrario, l'actor che riceve gli effetti causati dalla sequenza scatenata
dall'use case stesso, viene disegnato alla destra.
Il nome dell'actor appare appena sotto la raffigurazione dello stesso actor
mentre il nome dell'Use Case appare o dentro l'ellisse o appena al di sotto di
esso. Una linea di associazione, infine, connette un actor all'use case e
rappresenta la comunicazione tra l'actor e lo use case. La linea di
associazione è una linea continua, simile a quella che connette due classi in
associazione tra loro.
Come detto, ogni use case è una lista di scenari, ed ogni scenario è una
sequenza di passi. Per ciascun use case, ogni scenario avrà la sua propria
pagina rappresentata nel seguente modo:
Un actor che dà inizio alla sequenza dell'use case
Le Pre condizioni per lo use case
I passi dello scenario vero e proprio
Le Post Condizioni quando lo scenario è completo
L'actor che beneficia dell'use case
Gli Use Case Diagram danno del valore aggiunto alla
raccolta di informazioni. Essi visualizzano gli use case, facilitano la
comunicazione tra gli analisti e gli utenti e tra gli analisti ed il cliente.
22. Relazioni tra Use Cases Definiamo le quattro relazioni che permettono il riutilizzo dei Use Cases
Quando abbiamo iniziato a parlare di Use Case Diagrams, abbiamo detto che è
possibile il riutilizzo di un Use Case Diagram e si è detto che ciò era
fattibile utilizzando due modi: tramite l'inclusion e tramite l'extension.
L'inclusion e la extension rappresentano una sorta di relazioni
tra use case. In effetti, esistono anche altri due tipi di relazioni
applicabili agli Use Cases : le generalizzazione (Generalization)
e il raggruppamento (Grouping).
Ma, proviamo a definire meglio tutte e quattro queste relazioni:
Inclusion
L'inclusion permette il riutilizzo di un use case all'interno di un altro use
case. Per rappresentare graficamente una inclusion, si utilizza il simbolo
utilizzato per la dipendenza tra classi - una linea tratteggiata che connette
le classi con una freccia che punta sulla classe da cui dipende l'altra classe.
Appena sotto questa linea, si aggiunge uno stereotipo - la parola <<include>>
racchiusa, come si vede, tra doppie parentesi formate dai simboli
"<<" e ">>"
Extension
L'extension permette di creare un nuovo use case aggiungendo dei passi in più
ad un use case già esistente.
Anche qui una linea tratteggiata con una freccia finale viene utilizzata per
rappresentare l'extension, insieme con uno stereotipo che mostra la parola
<<extends>> tra parentesi. All'interno dell'use case base,
il punto di extension appare sotto il nome dell'use case stesso.
Generalization
Le classi, come abbiamo visto, possono ereditare le caratteristiche di un'altra
classe (classe padre). Allo stesso modo, tale ragionamento è applicabile agli
use case. Nella eredità tra use case, lo use case figlio eredita il
comportamento ed il significato dal padre ed in più aggiunge le sue
caratteristiche specifiche. Anche in questo caso vale lo stesso ragionamento
applicato nel caso delle classi: e' possibile applicare lo use case figlio,
laddove è possibile applicare il padre. La Generalization viene rappresentata
allo stesso modo con cui viene rappresentata per le classi - ovvero con una
linea continua che ha un triangolo aperto che punta al padre. La relazione di
Generalization può esistere anche tra actors.
Grouping
In alcuni use case diagrams, ci potrebbero essere molti use case e, magari, si
desidererebbe organizzare il diagramma in modo migliore. Una tale situazione si
può verificare quando si sta progettando un sistema che consiste di più
sottosistemi. Il modo più semplice è di organizzare a gruppi gli use case che
in qualche modo siano correlati (qualcosa di simile ad un tabbed folder).
Use Case Diagram - Un Esempio Proviamo con un esempio pratico a progettare un sistema automatico
In questo esempio si cercherà di
modellare, tramite gli use case diagrams, una macchina self-service per
alimenti e bevande. La principale funzione di una siffatta macchina è,
ovviamente, quella di permettere ad un utente di acquistare un prodotto
alimentare (cioccolata, succo di frutta, ecc.). Ogni utente che interagisca con
la macchina potrà, certamente, dire che la principale funzione (e quindi il
principale use case) della macchina stessa potrà essere definita come :
"Acquisto di un prodotto".
Proviamo ad esaminare ogni possibile scenario all'interno di questo use case.
Gli scenari che ne derivano saranno, naturalmente, scaturiti dalle
conversazioni con l'utente.
Lo use case "Acquista un prodotto"
L'actor in questo use case è il cliente. Il cliente vuole comprare alcuni dei
prodotti offerti dalla macchina self-service. Per prima cosa egli dovrà
inserire delle monete all'interno della macchina, poi selezionare il tipo di
prodotto (o più di uno, se la macchina lo consente) e quindi ricevere dalla
macchina la lista dei prodotti scelti prima di procedere all'acquisto vero e
proprio. Lo use case per tale tipo di scenario può essere il seguente:
Ma, se ci si pensa un attimo più
approfonditamente, vengono alla mente altri tipi di scenari. È possibile che la
macchina self-service non sia in grado, ad un certo momento, di fornire uno o
più prodotti oppure che la macchina non abbia a disposizione l'esatto numero di
monete per fornire il resto al cliente.
Ci si deve chiedere: Ci è stato chiesto di gestire questi tipi di scenari?
Se la risposta è affermativa, torniamo un attimo indietro al momento in cui il
cliente inserisce le monete nella macchina ed effettua la selezione. Supponiamo
allora che la macchina, a questo punto, non sia in grado di soddisfare la
richiesta del cliente. In tal caso sarà preferibile presentare un messaggio al
cliente che lo informi che la macchina non ha come disponibile il prodotto
scelto e che permetta al cliente stesso di effettuare una nuova scelta o
richiedere la restituzione delle monete.
Se, invece, si è verificato lo scenario in cui è stato fornito un errato
ammontare di monete, si suppone che la macchina restituirà l'importo originale
di soldi al cliente. La precondizione, in tal caso, è il cliente (affamato o
assetato!) e la post condizione è il prodotto acquistato o la restituzione dei
soldi.
Quanto descritto rappresenta lo scenario di un use case dal punto di vista di
un utente (e quindi di un actor). Ma potrebbero esserci anche altri tipi di
actors. Per esempio, un fornitore di prodotti deve essere in grado rifornire la
macchina e il proprietario della macchina deve poter recuperare le monete
accumulate. Questo ci induce a creare almeno altri due use case che chiameremo:
"Ricarica la Macchina" e "Ritira le Monete". Andiamo ad
esaminarli entrambi simulando un' intervista con il fornitore e con il
proprietario.
Lo use case "Ricarica
la Macchina"
Le azioni che un fornitore dovrà compiere ad intervalli di tempo regolari
(diciamo una o due settimane) sono:
Il fornitore disattiva la macchina
Apre il contenitore dei prodotti
Riempie ogni scompartimento fino alla massima capacità (Si potrebbe anche supporre che il fornitore riempia la macchina tenendo conto delle maggiori preferenze dei clienti)
Alla fine, il fornitore chiude il contenitore dei prodotti e riattiva la macchina
In questo caso, potremmo dire che la precondizione è
rappresentata dal trascorrere dell'intervallo di tempo tra una ricarica e
l'altra e la post condizione è data dal fatto che il fornitore ottiene un nuovo
insieme di potenziali clienti.
Lo use case diagram, in questo caso, è rappresentato dalla seguente figura:
Lo use case "Ritira Le
Monete"
Il responsabile per questo Use Case è il proprietario della macchina. In
effetti, tuttavia, questi potrebbe coincidere con il fornitore. I passi che il
proprietario della macchina deve fare sono uguali a quelli del fornitore ma la
differenza consiste nel fatto che il proprietario non ha a che fare con i
prodotti ma con i soldi. Quando l'intervallo di tempo tra un ritiro e l'altro è
trascorso, il proprietario della macchina ritira l'ammontare di monete che si è
depositato nella macchina La post condizione, in tal caso, è rappresentata dai
soldi ritirati dal proprietario. Lo use case che descrive tale scenario è,
dunque, rappresentato nella figura seguente:
Molti dei passi necessari allo Use Case "Ritira
le monete" (disattivare la macchina, aprire il contenitore, ecc.) sono
uguali a quelli visti per lo use case "Ricarica la macchina". Questo
è un buon motivo per avvalerci dell'utilizzo dell'inclusion. Combiniamo allora
i due passi: Disattiva la macchina e apre il contenitore in uno use case che
denominiamo: "Disattiva la macchina". Alla stessa maniera
definiamo un nuovo Use case che chiamiamo "Riattiva la Macchina"
che inglobi i passi di chiudere il contenitore e riattivare la macchina.
Otterremo:
Cerchiamo ora di raffinare ulteriormente i nostri use
cases.
Lo use case "Ricarica la macchina" potrebbe essere la base per un
altro use case: "Ricarica la macchina in base alle vendite". Qui, il
fornitore può riempire gli scompartimenti non più in modo uniforme per ogni
prodotto ma in base alle vendite dei singoli prodotti. Questo rappresenta un
buon esempio di extension di un use case.
Dopo l'inclusion e l'extension così definiti, lo use case "Ricarica la
macchina" può diventare:
Possiamo anche utilizzare la generalizzazione
guardando gli actors: fornitore e proprietario. Sarà possibile definire un
Actor più generico (Agente del Fornitore) che inglobi molte delle
caratteristiche del Proprietario e del Fornitore.
Tale generalizzazione è mostrata nella figura che segue:
Un esempio di generalizzazione di un Actor
La figura sopra mostra il diagramma finale completo per la macchina self service
State Diagrams
23. State Diagrams
Esaminiamo
gli elementi comportamentali
Descriveremo, adesso, elementi che non abbiamo ancora mai
esaminato. Tali elementi sono detti elementi comportamentali e mostrano
come varie parti di un diagramma UML possano cambiare nel tempo.
Allo stesso modo in cui un sistema interagisce con gli utenti e, possibilmente,
con altri sistemi, così gli oggetti che costituiscono il sistema stesso passano
attraverso i necessari cambiamenti che servono a favorire le interazioni.
Se si sta modellando un sistema, è necessario avere un meccanismo che gestisca
le modifiche all'interno del modello stesso. Tale meccanismo, in UML, è
rappresentato dagli State Diagrams.
Per esempio, quando si preme un interruttore, una lampada cambia il suo stato
da spento ad acceso (o viceversa). Oppure, ancora, quando si preme un tasto
della tastiera o si muove il mouse durante il funzionamento di uno screen saver
sul computer, il computer abbandona la modalità di screen saver e ritorna a
funzionare regolarmente in modo attivo.
Gli State Diagrams visualizzano gli stati che un oggetto può attraversare e i
passaggi transitori che intercorrono tra questi stati. Inoltre gli State
Diagrams mostrano il punto di partenza e il punto di arrivo di una sequenza di
cambi di stato.
Definizione: Uno State Diagram mostra gli stati di un singolo oggetto. |
Veniamo alla rappresentazione grafica. Gli stati di uno State Diagram sono
rappresentati con un rettangolo con gli angoli arrotondati. Il simbolo che
mostra la transizione da uno stato ad un altro viene disegnato utilizzando una
linea continua che termina con una freccia.
Un cerchio nero pieno rappresenta il punto di partenza di una sequenza di stati
mentre il punto di arrivo viene rappresentato da due cerchi concentrici in cui
il più interno è riempito di nero (occhio di bue).
Nella figura precedente si può vedere un esempio di
quanto detto. Inoltre, come si può notare, è possibile aggiungere maggiori
dettagli alla figura stessa dividendo il rettangolo in tre aree separate.
L'area in alto contiene il nome dello stato, l'area centrale contiene le
variabili di stato (timers, contatori, date, ecc.) e l'area in basso
rappresenta le attività (cioè quello che accade quando il sistema entra in un
determinato stato e cosa, invece, succede quando il sistema abbandona quello
stato
24. Dettagli di Stato e Transizioni Vediamo come indicare un evento
È possibile indicare sugli State Diagram un evento
che causa il verificarsi di una transizione (un evento trigger) e
l'azione che viene eseguita che fa sì che il cambio di stato possa avvenire.
Per aggiungere graficamente eventi e azioni si scrive vicino la linea di
transizione una descrizione di essi, utilizzando una barra per separare un
evento di trigger da un'azione.
Qualche volta può accadere che un evento causi una transizione senza azioni
associate e, qualche altra volta una transizione si verifica perchè uno stato
completa un'attività (piuttosto che a causa di un evento). Questo tipo di
transizione viene chiamata transizione senza trigger (triggerless transition).
È anche possibile inserire una condizione di controllo (guard condition).
Quando la si incontra, la transizione ha luogo. (Per esempio lo screen saver
viene attivato quando l'intervallo di tempo di x minuti viene raggiunto).
Gli State Diagrams consentono, inoltre, di definire degli stati all'interno di
altri stati. In tal caso, gli stati interni verranno definiti sotto-stati (substates)
i quali, a loro volta, possono essere disinti in sottostati sequenziali e
sottostati concorrenti
I primi, come si evince dal nome stesso, rappresentano una sequenza di stati
che vengono raggiunti uno susseguentemente all'altro. I sottostati concorrenti,
invece, rappresentano due o più sottostati sequenziali che si verificano allo
stesso tempo. Tutto ciò viene rappresentato graficamente con una linea tratteggiata
tra gli stati concorrenti. Per comprendere meglio questi concetti, comunque, si
faccia riferimento all'esempio del paragrafo successivo.
L'UML fornisce un simbolo che mostra che uno stato composto ricorda i suoi
attivi sottostati quando l'oggetto effettua transizioni fuori dallo stato
composto. Il simbolo usato è:
unito da una linea continua ai sottostati "ricordati", con una
freccia che punta al sottostato opportuno.
Un messaggio che causa una transizione in un oggetto dello State Diagram (che
riceve il messaggio stesso) viene chiamato segnale (signal).
Nel mondo orientato agli oggetti, il mandare un segnale viene visto allo stesso
modo come la creazione di un oggetto Segnale e la trasmssione di questo ad un
oggetto Ricevente. L'oggetto Segnale può avere delle proprietà che saranno
rappresentate da attributi.
Infine, poiché un segnale è un oggetto, è anche possibile creare gerarchie di
ereditarietà di segnali
State Diagram - Un esempio pratico Proviamo con un esempio pratico ad utilizzare gli State Diagram
Supponiamo di voler creare un
modello che descriva il funzionamento di un tostapane. Ovviamente, rivolgiamo
la nostra attenzione agli state diagram che un simile sistema può avere.
Quali sono i passi perchè un tostapane riesca a preparare un toast?
Per prima cosa bisognerà accendere il tostapane, quindi mettere le fette di pan
carrè all'interno di esso ed attendere alcuni minuti perchè sia cotto il toast.
Lo state diagram iniziale sarà, dunque:
Ma quello rappresentato non è il diagramma finale.
Per prevenre che il toast si bruci, la resistenza del tostapane deve produrre
calore che non superi determinati valori di temperatura. Naturalmente, perchè
il toast si cuocia a dovere è necessario anche che la temperatura non vada al
di sotto di un certo valore minimo.
Per tale ragione un termometro misura la temperatura prodotta dalla resistenza
e quando il limite massimo viene raggiunto la resistenza passa in uno stato di
attesa e non emette altro calore. Tale stato perdura finché la temperatura
decresce fino ad arrivare al valore minimo. A questo punto ritorna lo stato di
"In Lavorazione". Con questi ulteriori dettagli, il nostro State
Diagram diverrà:
Ma per descrivere la transizione tra lo stato di "In Lavorazione" e lo stato "Inattivo" è necessario aggiungere dei sottostati al diagramma, come mostrato nella prossima figura:
Si può notare che gli stati "In Lavorazione
" e "Inattivo" sono molto simili. Entrambi devono misurare e
comparare gli stati ma si differenziano nel processo di confronto della
temperatura. Infatti, lo stato di "In Lavorazione" deve comparare la
temperatura corrente con la temperatura limite superiore (se viene raggiunta
allora si passa allo stato "Inattivo") e lo stato
"Inattivo" confronta la temperatura corrente con la temperatura
limite inferiore (lo stato "Inattivo" viene rimpiazzato dallo stato
di "In Lavorazione" quando accade che la temperatura scende al di
sotto del limite).
È utile utilizzare gli State Diagrams perché essi aiutano gli analisti, i
disegnatori e gli sviluppatori a capire il comportamento degli oggetti in un
sistema. Gli sviluppatori, in particolare, devono conoscere come gli oggetti
devono comportarsi in quanto è loro compito tradurre tali comportamenti in
software.
Sequence Diagrams
25. Sequence Diagrams
Cosa sono e a
cosa servono i Sequence Diagrams
Gli State Diagrams,
che abbiamo visto nel precedente paragrafo, focalizzano la loro attenzione
sugli stati di un oggetto. Ma è necessario, oltre alla definizione degli stati,
instaurare una comunicazione tra gli oggetti. L'UML, a tale proposito definisce
il Sequence Diagram che, appunto,
permette di modellare la comunicazione tra un oggetto ed un altro in relazione
al trascorrere del tempo. Si capisce subito che in questo tipo di
rappresentazione un ruolo cruciale viene svolto dal tempo.
L'idea chiave qui è che le interazioni tra gli oggetti avvengano seguendo un
ordine ben preciso e che tale sequenza avvenga, nel tempo, dall'inizio alla
fine.
Il Sequence diagram è costituito da oggetti rappresentati nel modo ormai usuale
- come rettangoli recanti un nome (con il nome sottolineato), messaggi
rappresentati da linee continue recanti una freccia alla loro fine e il tempo
rappresentato come progressione verticale.
26. I componenti dei Sequence Diagrams
Gli Oggetti,
i Messaggi e il Tempo
Oggetti
Gli oggetti sono disegnati vicino la sommità del diagramma e sono disposti in
sequenza da sinistra verso destra. Essi possono essere inseriti in un qualunque
ordine che semplifichi la comprensione del diagramma. Da ogni rettangolo si
diparte una linea tratteggiata verso il basso, denominata "linea della
vita" (lifeline). Lungo la lifeline si trova un piccolo rettangolo
chiamato "attivazione" (activation). L'activation rappresenta
l'esecuzione di un'operazione di cui l'oggetto si fa carico. La lunghezza del
rettangolo, invece, rappresenta la durata dell'activation. Tutto questo è
mostrato nella figura seguente:
Messaggi
Un messaggio che viaggia da un oggetto ad un altro, viene disegnato a partire dalla
lifeline dell'oggetto da cui parte il messaggio e arriva sulla lifeline
dell'oggetto a cui il messaggio è diretto.
Si può anche verificare il caso in cui un oggetto mandi un messaggio a se
stesso, cioè un messaggio che parte dalla sua lifeline e arriva alla stessa
lifeline. Tale tipo di comportamento viene definito Ricorsione.
Nella tabella seguente vengono identificati tutti i possibili messaggi
definiti in UML per i sequence diagrams, ognuno dei quali, come si vede, ha una
rappresentazione grafica differente.
Simple |
Rappresenta il trasferimento del controllo da un oggetto ad un altro. |
|
synchronous |
Se un oggetto invia un messaggio sincrono, allora si attende che gli venga restituita una risposta al messaggio stesso prima di poter continuare con altre operazioni. |
|
asynchronous |
Diversamente dai messaggi sincroni, se un oggetto invia un messaggio asincrono, non attende che gli venga inviata alcuna risposta prima di continuare con altre operazioni |
|
Il Tempo
Il sequence diagram rappresenta il trascorrere del tempo se visto in direzione
verticale. Il tempo, graficamente, viene fatto partire alla base di ogni
oggetto e proseguire fino in basso. Ad esempio, un messaggio che si trovi più
vicino all'oggetto rispetto ad un altro (rispetto alla direzione verticale), si
verificherà prima nel tempo.
Nei sequence diagram viene utilizzata il simbolo dell'actor per rappresentare l'inizio della sequenza, ma in realtà tale simbolo (come abbiamo visto quando abbiamo parlato degli Use Case diagrams) non appartiene all'insieme dei simboli propri del sequence diagram
27. Modi di creare le Sequenze Analizziamo i componenti di un sequence diagram
In maniera uguale agli use case diagrams in cui è possibile mostrare
o un'istanza (uno scenario) singola di uno use case o, più genericamente, un
insieme degli scenari di un use case, così i sequence
diagrams possono essere definiti su una singola istanza oppure
definire un modello più generico.
I sequence diagrams generici forniscono spesso la possibilità di rappresentare
delle istruzioni condizionali (if) e dei cicli while in cui ogni condizione
descritta da un if (oppure da un while) viene racchiusa tra parentesi quadrate
(nel caso del while la parentesi quadrata sinistra viene preceduta da un
asterisco). Si veda l'esempio più avanti per maggiore chiarezza.
Esiste la possibilità, in un sequence diagram, di creare un oggetto.
Quando ciò avviene, l'oggetto creato viene rappresentato nel modo visto finora
e cioè con un rettangolo all'interno del quale viene descritto il nome
dell'oggetto.
La differenza, in questo caso, consiste nel fatto che l'oggetto non viene
posizionato alla sommità del sequence diagram come si farebbe con gli altri
oggetti ma, piuttosto, lungo la dimensione verticale che indica il tempo in cui
tale oggetto viene creato.
Può accadere, qualche volta, che un oggetto esegua un'operazione che invochi lo
stesso oggetto che l'ha provocata. In tal caso si parla di ricorsione.
Ad esempio, si supponga che uno degli oggetti del sistema sia un calcolatore e
che una delle sue operazioni sia il calcolo degli interessi. Al fine di
permettere il calcolo per un lasso di tempo che racchiuda parecchi periodi,
l'operazione per calcolare gli interessi deve invocare se stessa diverse volte.
Il sequence diagram nella figura sottostante, mostra tale caso:
Sequence Diagram - Un esempio Come creare un sequence diagram
Useremo lo stesso esempio visto in precedenza, ovvero quello della macchina Self-Service. Definiamo i seguenti tre oggetti della Macchina Self-Service con cui descriveremo il nostro diagramma:
La Parte Frontale. - L'interfaccia che la macchina presenta all'utente
La Cassetta delle monete - La parte in cui vengono accumulate le monete e che gestisce i vari controlli della macchina
Il Contenitore dei Prodotti - La parte che contiene gli alimenti che vengono acquistati dal cliente
Il Sequence Diagram che modelleremo farà uso della seguente sequela di azioni:
Il cliente inserisce le monete nella macchina
Il cliente esegue la selezione del prodotto desiderato
Le monete arrivano nella Cassetta delle Monete
Il dispositivo di controllo della Cassetta delle monete verifica se il prodotto desiderato è presente nel Contenitore dei Prodotti
La Cassetta delle Monete aggiorna la sua riserva di monete
Il dispositivo di controllo della Cassetta delle Monete informa il Contenitore dei Prodotti che può espellere il prodotto desiderato dalla Parte Frontale della macchina
Si provi, per esercizio, a costruire il Sequence Diagram più complesso che
descrive il caso di situazioni particolari della macchina causati da una
quantità di monete errate o dal prodotto selezionato dall'utente non presente.
Nel collaboration Diagram vedremo in dettaglio anche questi casi.
Collaboration Diagrams
28. Collaboration Diagrams
Utilizziamo
anche i Collaboration Diagrams
I collaboration
diagrams rappresentano un tipo di diagramma molto simile a quello
appena visto nei sequence diagram. Infatti, essi mostrano come interagiscono
gli oggetti tra di loro, mettendo in risalto gli oggetti attraverso i quali
viaggiano i messaggi che gli stessi oggetti si scambiano tra di loro. Sorge
allora spontanea la domanda: Ma se già i sequence diagrams realizzano
tali operazioni, perché l'UML ha bisogno di un altro diagramma dello stesso
tipo? Non svolgono le stesse funzioni?
In effetti, il sequence diagram e il collaboration diagram sono simili. In
particolare, si può dire che essi sono semanticamente equivalenti. Ovvero, i
due diagrammi presentano la stessa informazione ed è facile convertire un
sequence diagram in un collaboration diagram e viceversa. La principale
distinzione tra i due diagrammi, è che il sequence diagram è costruito
seguendo come filo conduttore il tempo mentre il collaboration diagram si basa
sullo spazio.
Un collaboration diagram è un'estensione di un diagramma di oggetti. In più,
oltre alle associazioni tra gli oggetti, esso consente di mostrare i messaggi
che essi inviano per interagire tra di loro.
I messaggi tra gli oggetti sono rappresentati con delle frecce che
puntano all'oggetto che riceve il messaggio stesso. Tali frecce sono
posizionate vicino la linea di associazione tra gli oggetti. Una label vicino
la freccia indica la specifica di un messaggio. Un messaggio, tipicamente,
richiede all'oggetto ricevente di eseguire una delle sue operazioni. Una coppia
di parentesi terminano il messaggio; al loro interno si trovano gli eventuali
parametri con cui le operazioni lavorano.
Come detto, i collaboration diagrams possono essere convertiti in sequence
diagrams e viceversa. Per far ciò, però, si deve tenere presente che è
necessario aggiungere un numero alla label di un messaggio che corrisponda
all'ordine in cui il messaggio appare nella sequenza. Il segno dei due punti
separa il numero dal messaggio
29. Scrivere dei Collaboration Diagrams
Vediamo come
utilizzare un Collaboration Diagrams
È possibile mostrare, in un
collaboration diagram, il cambio di stato di un oggetto. Si possono
mostrare, inoltre, le condizioni allo stesso modo in cui esse sono
rappresentate all'interno di un sequence diagram.
Nel rettangolo che rappresenta l'oggetto si indica lo stato dell'oggetto
stesso. Al diagramma si aggiunge un altro rettangolo che rappresenta l'oggetto
e indica lo stato modificato. I due rettangoli vengono quindi uniti con una
linea recante un'etichetta con uno stereotipo. La condizione va inserita
all'interno di una coppia di parentesi quadre considerato che la condizione
deve precedere l'etichetta del messaggio.
La cosa importante è coordinare le condizioni con una numerazione. Per maggiori
chiarimenti su tale costruzione si veda il paragrafo successivo.
I collaboration diagram permettono anche di modellare la creazione di
oggetti; nel processo di creazione di tali oggetti si inserisce uno
stereotipo <<create>> al messaggio che si occupa della
creazione dell'oggetto.
Ancora, nei collaboration diagrams si possono rappresentare oggetti multipli
e visualizzare i risultati restituiti.
La rappresentazione di oggetti
multipli viene effettuata tramite uno stack (una pila) di rettangoli disegnati
in sequenza inversa (da destra a sinistra). Si aggiunge una condizione
(circondata da parentesi) e preceduta da un asterisco per indicare che il
messaggio deve giungere a tutti gli oggetti.
I risultati restituiti sono scritti come espressioni in cui il nome
dell'espressione è preceduto dal valore di ritorno e seguito dai segni := .
Quindi, si scrivono il nome dell'operazione ed una lista di possibili attributi
che l'operazione può accettare per produrre il risultato finale.
La parte destra dell'espressione appena descritta viene definita firma del
messaggio (message-signature).
In alcune interazioni può accadere che uno specifico
oggetto si occupi del controlli del flusso. Questo oggetto attivo può
mandare messaggi ad oggetti passivi ed interagire a sua volta con altri oggetti
attivi. Inoltre, si potrebbe verificare anche il caso di un oggetto che mandi
messaggi soltanto dopo che parecchi altri messaggi (possibilmente non
consecutivi) siano stati inviati. In altre parole, l'oggetto deve sincronizzare
il suo messaggio con un insieme di altri messaggi.
Il collaboration diagram rappresenta un oggetto attivo allo stesso modo di come
si è visto finora con la differenza che i bordi del rettangolo sono spessi e in
grassetto.
I messaggi sincroni sono preceduti da una lista di messaggi che devono essere
completati prima che il messaggio sincrono possa essere inviato. Una virgola
separa un elemento della lista dall'altro e la lista termina con una barra.
Vediamo ora di mettere insieme tutti i concetti di cui si è parlato e di
definire un collaboration diagram completo.
Collaboration Diagram - Un esempio. Attraverso un esempio proviamo a convertire il sequence diagram in un collaboration diagram
Ancora una volta utilizzeremo
l'esempio della macchina self-service.Nell'esempio sul sequenze diagram si è
già costruito il diagramma per un sistema del genere. Adesso, proviamo a convertire
il sequence diagram in un collaboration diagram.
Lo scenario del caso migliore consiste di diversi passi:
Il cliente inserisce le monete nella macchina ed esegue le selezione di uno o più prodotti presenti sulla macchina.
Quando il dispositivo di introduzione delle monete ottiene la somma dovuta (in questo caso si suppone che il cliente inserisca il corretto numero di monete necessarie) e vi è la disponibilità dei prodotti scelti, allora viene espulso dalla macchina il prodotto scelto.
Il prodotto (o i prodotti) viene espulso dalla parte frontale della macchina in modo che il cliente possa prelevarli.
Ma, quando si esamina in dettaglio questa macchina ed il lavoro che essa
svolge, ci si rende conto che sono possibili ulteriori scenari:
Introduzione di un numero errato di monete
Mancata disponibilità di un prodotto selezionato.
È
possibile utilizzare delle condizioni che aiuteranno a descrivere il lavoro
della macchina. Esse vengono visualizzate tra una coppia di parentesi quadre in
modo tale che la condizione preceda l'etichetta del messaggio. La cosa
importante è tener presente che bisogna coordinare le condizioni con la
numerazione progressiva.
Nello scenario in cui la macchina non abbia a disposizione il prodotto scelto è
necessario che la macchina visualizzi un messaggio all'utente che gli permetta
di selezionare un prodotto alternativo e ripetere, quindi, il processo oppure
di avere restituite le monete. È, naturalmente, possibile descrivere un
collaboration diagram anche per il caso in cui si sia inserito un numero errato
di monete.
Il collaboration diagram seguente illustra entrambi i casi
Come è possibile vedere dallo schema, sono possibili fondamentalmente due
scenari: Alimento Non Presente e Alimento Presente. Se assumiamo che tale
differenziazione avvenga dopo il messaggio 2:
InserimentoMonete(AlimentoSelezionato), il numero identificativo per questi
messaggi sarà 3 per lo scenario Alimento Presente e 5 per lo scenario Alimento
non Presente.
Cosa avviene quando la macchina non ha a disposizione il resto corretto? Essa
deve visualizzare un messaggio, restituire le monete e chiedere al cliente di
inserire la quantità esatta di monete. A questo punto, la transazione è
terminata. Quando la macchina ha la giusta quantità di monete, restituisce il
resto al cliente ed espelle il prodotto selezionato.
I due rami che sono prodotti dal processo annidato per il controllo del resto
sono contrassegnati con 3 e 4.
Activity Diagrams
30. Activity Diagrams
Introduzione
agli Activity Diagrams
Probabilmente, molte persone che in
passato abbiano preso parte a qualche corso introduttivo di programmazione
ricorderanno i diagrammi di flusso (flowchart). Il flowchart mostra una
sequenza di passi, processi, punti decisionali e rami. I programmatori alle
prime armi sono spesso indotti ad utilizzare i diagrammi di flusso per
sviluppare una migliore logica di programmazione e ricavare delle soluzioni ai
problemi software.
L'activity diagram UML è molto simile
ai flowchart. Infatti, esso mostra i passi (chiamati, propriamente, attività),
i punti decisionali e i rami che intervengono nel flusso di un programma. È
utile per mostrare cosa accade in un processo di business o in un'operazione ed
è considerato come parte integrante dell'analisi di sistema.
Un activity diagram viene disegnato per essere una vista semplificata di
cosa accade durante un'operazione o un processo. Potremmo dire che esso è
un'estensione dello state diagram. Quest'ultimo mostra gli stati di un oggetto
e rappresenta le attività come frecce che si connettono agli stati. L'activity
diagram mette in risalto le attività.
Ogni attività è rappresentata da un rettangolo con gli angoli arrotondati - più
stretto e più ovale rispetto alla icona vista nello state diagram.
L'elaborazione di un'attività porta al completamento della stessa e poi avviene
un'automatica trasmissione alla successiva attività. Una freccia rappresenta la
transizione da un'attività alla successiva. Anche l'activity diagram ha un
punto di partenza, rappresentato da un cerchio pieno, ed un punto di fine
rappresentato da un occhio di bue..
Costruzione di un Activity Diagram Le componenti
degli activity diagrams in dettaglio Cerchiamo ora
di capire le varie componenti in dettaglio: le modalità in cui vengono
rappresentate le decisioni, i path concorrenti, i segnali
e le swimlanes.
Decisioni
Un punto di decisione può essere rappresentato in due modi. La scelta sulla
modalità da utilizzare è affidata interamente all'analista.
Il primo modo consiste nel mostrare i possibili cammini che derivano
direttamente da un'attività. L'altro modo, invece, consiste nel rappresentare
la transizione di un'attività con un piccolo rombo e far seguire dal rombo
stesso tutti i possibili cammini di flusso. Un altro modo ancora stabilisce di
indicare la condizione con un'istruzione racchiusa tra parentesi graffe vicino
il path appropriato.
Si immagini di dover recarsi al lavoro. Le fasi che descrivono tale processo
saranno: aprire la macchina, inserire le chiavi nel cruscotto e quindi
scegliere tra le seguenti due situazioni:
La macchina si avvia regolarmente
La macchina non si avvia
Questi due possibili casi produrranno due altre attività:
Guidare la macchina
Recarsi alla fermata del autobus (oppure prendere un taxi, la bicicletta o andare a piedi)
Tale tipo di scenario viene rappresentato nel seguente grafico (si presti attenzione ai due modi di mostrare una decisione):
Path Concorrenti
Quando si esegue il modellamento di attività, molto frequentemente si
verificherà la necessità di dover separare le transizioni in due cammini
separati che vengano eseguiti allo stesso tempo (concorrentemente).
Una tale suddivisione viene rappresentata da una linea continua in grassetto,
perpendicolare alla transizione e che mostri i cammini che avvengono al di
fuori dalla linea stessa. Per rappresentare un "merge" successivo
delle due attività, si fanno convergere i cammini verso un'altra linea in
grassetto.
Segnali
Durante una sequenza di attività, è possible inviare un segnale. Quando viene
ricevuto, il segnale causa la creazione di un'attività.
Il simbolo per inviare un segnale è un pentagono convesso, mentre il simbolo
per rappresentare il segnale ricevuto è un poligono concavo.
Swimlanes
L'activity diagram definisce anche la possibilità visualizzare i ruoli. Per far
ciò, si separa il diagramma in segmenti paralleli, chiamati swimlanes (corsie
di nuoto). Ogni swimlane mostra il nome di un determinato ruolo in cima e
mostra le attività di quel ruolo. Le transizioni possono anche coinvolgere due
swimlane.
È possibile combinare l'activity diagram con i simboli di altri diagrammi e
così produrre un diagramma ibrido.
I Diagrammi per software e hardware
31. Interfacce e Componenti: un approfondimento
Introduzione
ai diagrammi che rappresentano i componenti software e hardware reali
Si è visto, finora, come i diagrammi
descritti abbiano a che fare, in generale, con entità concettuali. Adesso si
vedranno, invece, diagrammi UML che rappresentano entità del mondo reale: i componenti
software (software component).
Innanzitutto: cos'e' un software component? Nient'altro che una parte fisica di
un sistema. Esso risiede in un computer e non nella mente di un analista.
Come si possono relazionare un componente ed una classe?
Basta pensare ad un componente come all'implementazione di una classe. La
classe rappresenterà un'astrazione di un insieme di attributi ed operazioni. Ed
un componente può essere visto come l'implementazione effettiva di una classe.
È importante modellare i componenti e le relazioni che intercorrono tra di
essi, in quanto :
I clienti possono vedere la struttura del sistema terminato
Gli sviluppatori hanno una struttura alla quale rifarsi e attorno alla quale incentrare il loro lavoro
Coloro che si occupano di scrivere la documentazione e i file di help si rendono conto meglio della funzionalità del sistema e quindi riescono a creare dei documenti più efficienti.
Quando si ha a che fare con i
componenti, inevitabilmente si deve avere a che fare con le loro interfacce.
Un'interfaccia, come abbiamo visto, rappresenta la "faccia"
dell'oggetto verso il mondo esterno in modo tale che altri oggetti possano
chiedere all'oggetto che espone l'interfaccia di eseguire le sue operazioni che
sono nascoste dall'incapsulamento.
Per l'analista che si occupa di disegnare il modello questo si traduce nel
fatto che il modo in cui si rappresenta un'interfaccia per una classe è lo
stesso del modo in cui si rappresenta un'interfaccia per un componente. La
relazione tra un'interfaccia e una classe (anche qui allo stesso modo) viene
detta realizzazione (si veda quanto detto nel paragrafo Interfacce e
Realizzazioni).
È possibile rimpiazzare un componente con un altro se il nuovo componente è
conforme alle stesse interfacce del vecchio. Il riutilizzo di un componente di
un altro sistema è possibile se il nuovo sistema può accedere al componente
stesso attraverso le sue interfacce.
Fondamentalmente, dal punto di vista della modellazione UML, ci sono tre tipi
di componenti:
Deployment components. Che rappresentano la base dei sistemi eseguibili (DLL, eseguibili, Controlli Active X, Java Beans).
Work Product Components: dai quali vengono creati i deployment components (e quindi: file di dati e file sorgenti)
Execution Components, creati come risultato del sistema in esecuzione
Infine, diciamo che quando un componente accede ai servizi di un altro componente utilizza un interfaccia di import. Viceversa, il componente che realizza l'interfaccia con dei servizi fornisce una interfaccia di export
Component Diagrams
32. Component Diagrams
I Component
dyagrams: rappresentare interfacce, componenti e relazioni
La principale icona di un component diagram è un rettangolo che, a sua volta, comprende due rettangoli più piccoli incastrati nel suo lato sinistro.Il nome del componente va inserito all'interno del rettangolo principale. Se il componente è un elemento di un package, è consigliabile far precedere il nome del componente dal nome del package.
Un componente e le interfacce che esso utilizza sono rappresentabili in due modi:
Mostrando l'interfaccia come un rettangolo che contiene l'informazione relativa all'interfaccia. Il rettangolo è connesso al componente tramite una linea tratteggiata e un rettangolo che visualizza la realizzazione dell'interfaccia.
Utilizzando un piccolo cerchio connesso al componente tramite una linea continua che rappresenta la relazione di realizzazione dell'interfaccia.
Modo 1: Un'interfaccia può essere rappresentata come un rettangolo, connesso al componente tramite una linea tratteggiata che termina con una freccia.
Modo 2: Un'interfaccia può essere rappresentata anche come un piccolo cerchio, connesso al componente tramite una linea tratteggiata che termina con una freccia
Component Diagrams - Un esempio Come creare un Component dyagram: un player musicale
Si supponga di voler costruire un
software per ascoltare della musica registrata su un CD-ROM. Per la scrittura
di un siffatto programma ci si potrebbe avvalere di un linguaggio di
programmazione visuale come il Visual C++ o il Visual Basic, per esempio. Se il
linguaggio utilizzato supporta dei controlli multimediali, allora potremo
usarli direttamente od eventualmente riprogrammarli se necessario. O, ancora,
potremmo programmare dei nuovi componenti.
Un possibile disegno grafico per il nostro CD-player potrebbe essere:
Come è possibile vedere il programma necessita dei seguente controlli:
play
stop
eject
pause
fast forward
rewind
power
Tali controlli saranno realizzati con l'utilizzo di bottoni, appositamente utilizzati per ciascuno di essi. Se si guarda ad ognuno dei bottoni come dei componenti separati, possiamo ricavarne un component diagram UML.
Come si vede, tutti i componenti mostrati nel diagramma appartengono ad un
unico componente globale, il Bottone, anche se le azioni che essi eseguono sono
differenti. Tali azioni saranno ottenute programmandole una ad una.
Deployment Diagrams
33. Deployment Diagrams
L'ultimo
diagramma UML: come rappresentare l'hardware
Nessun sistema software potrebbe mai
funzionare correttamente se non si basasse su una solida struttura hardware.
Per tale motivo, il Deployment Diagram modella proprio questo aspetto del
sistema.
Riesaminando un attimino il cammino fatto si può notare come siamo partiti da
elementi di analisi, poi siamo passati ai componenti che vivono nei computer ed
ora passiamo all'hardware che vive nel mondo reale.
Come detto, l'hardware è un elemento primario nella composizione di un sistema
a multicomponenti. L'UML fornisce dei simboli che hanno il compito di favorire
la creazione di un quadro chiaro di come il settaggio e la composizione finale
dell'hardware dovrà essere.
L'elemento principale dell'hardware è costituito da un nodo (node),
che costituisce un nome generico per ogni tipo di risorsa hardware.
Sono definiti due tipi fondamentali di nodi:
Il processore, ovvero un nodo che può consentire l'esecuzione di un componente
Un device, un nodo che tipicamente si interfaccia con il mondo esterno, e che non può, invece, eseguire alcun componente.
Vediamo
ora gli elementi grafici UML del deployment diagram.
Un cubo rappresenta un nodo. Un nodo ha un suo nome ed è possibile anche
usare uno stereotipo per indicare il tipo di risorsa che esso rappresenta. Se
un nodo fa parte di un package, allora il nome del package deve precedere il
nome del nodo. Una linea che unisce due cubi rappresenta una connessione tra i
due nodi. È possibile usare anche uno stereotipo anche per fornire informazioni
sulla connessione.
(la rappresentazione di un nodo come avviene nel Deployment Diagram)
Ogni nodo comprende alcuni dei componenti schierati nel sistema. Per indicare tali componenti si inserisce una relazione di dipendenza tra essi e il nodo cui appartengono. Vediamo, per esempio, di costruire un deployment diagram per un sistema informatico domestico. Il computer consiste dei seguenti elementi hardware:
Una CPU
Un monitor
Una stampante
Un mouse
Una tastiera
Per quanto concerne il software potremo avere, ad esempio:
Windows 98
Office 2000
Internet Explorer 5.0
Front Page
Dos,
Norton Commander
Visual C++
Il nodo principale è rappresentato dalla CPU che, a sua volta, è composto di
svariati componenti software collegati tra di loro da opportune relazioni. Gli
altri elementi hardware sono i devices connessi all'unità centrale.
Si può estendere questo diagramma aggiungendo un modem ed una connessione ad
Internet. Si provi, come esercizio a ridisegnare il diagramma con tale
estensione.
I deployment diagram si rivelano particolarmente utili nel disegno e nel
modellamento di reti di calcolatori.
Deployment
Diagram - Un esempio Come creare
un Deployment dyagram: una rete Ethernet Se si ha
familiarità con le reti di calcolatori questi concetti saranno banali. In caso
contrario, sarà utile spendere qualche parola per comprendere meglio l'esempio.
La thin Ethernet è una rete di calcolatori molto comune. Essa viene
utilizzata in luoghi circoscritti, come stanze o palazzi, dove la connessione
dei cavi può essere facilmente realizzata. Ci sono alcuni calcoli matematici
necessari per definire la lunghezza dei cavi di tutta la rete e la lunghezza
dei cavi che connettono due computer. Tali calcoli, comunque, non sono
importanti per la realizzazione del deployment diagram.
I Computer si connettono al cavo di rete tramite dei dispositivi di connessione
chiamati T-connectors. I T-connectors hanno tre punti di connessione e la loro
forma (da cui deriva il nome) è simile alla lettera T (vedi figura accanto).
Il cavo di rete entra da un lato del connector ed esce dall'altro opposto
mentre il terzo punto di connessione va direttamente al computer.
Poiché la lunghezza della rete è limitata, I punti finali del cavo necessitano
di particolari dispositivi denominati terminatori (Terminator).
Una rete locale può, a sua volta, essere connessa ad un'altre rete locale
tramite un ripetitore, ovvero di un dispositivo che amplifica il segnale per
ridurre il rischio di perdita di segnale.
Ora che abbiamo definito I capisaldi di una rete thin Ehernet siamo in grado di disegnarne il relativo Deployment Diagram:
Privacy |
Articolo informazione
Commentare questo articolo:Non sei registratoDevi essere registrato per commentare ISCRIVITI |
Copiare il codice nella pagina web del tuo sito. |
Copyright InfTub.com 2024