Ing. R. Turco
Copyright 2003 – R. Turco
Gli esempi che esamineremo saranno organizzati nel seguente modo:
Il Requirements Model descrive che cosa
fa il sistema. I requisiti funzionali vengono espressi attraverso gli use
case e gli attori. Possono essere espressi anche i requisiti non
funzionali. Con gli use case si ha una vista comportamentale, mentre con
le relazioni tra use case si ha una vista strutturale.
La descrizione testuale è efficace quando sono molti i dettagli in gioco in un use case. La scrittura testuale di uno use case con molti dettagli permette una riduzione del rischio di incomprensione o di omissione di informazioni. Può essere omessa solo nel caso di problemi semplici. La descrizione testuale di uno use case aiuta a capire ed organizzare bene lo scenario d’uso.
L’Analysis Model tende a comprendere il
sistema, identifica gli oggetti del dominio, le informazioni passate.
ü Diagramma
delle classi
Il Diagramma delle classi può essere studiato usando
una miscela di metodi diversi:
§
Use
Case Driven;
§
Schede CRC;
§
Metodo del linguaggio verbale,
individuando nomi concreti, nomi astratti, verbi, specializzazioni (“E’ un”),
contenimenti o aggregazioni (“Ha un” etc);
§
Metodo dei colori di Coad;
o
Object Strutturing
Determina gli oggetti in ogni use case e la loro organizzazione strutturale (package e dipendenze);
L’Object
Structuring identifica e categorizza gli oggetti software.
L’identificazione
avviene da use case e dal modello delle classi; mentre la categorizzazione si
basa su:
§
Oggetti d’interfaccia o di confine (boundary): device, user, system;
§
Entità Object: oggetti che memorizzano informazioni;
§
Control Object: oggetti che fanno coordinamento (coordinatori,
timer, state-dependent);
§
Application logic objects: oggetti algoritmici, busines logic object.
o
Dynamic modeling:
Gli use case sono raffinati per mostrare l’interazione tra oggetti per ogni use case (diagramma delle sequenze, diagramma delle attività, diagramma degli stati).
o
Customizing,
Collapsing, Design Refactoring, Riuso
Se il problema è semplice, oltre al Requirements Modeling e allo Static Modeling, non necessariamente occorre usare anche gli altri modelli. Vanno utilizzati tutti quei modelli che permettono una vista chiarificatrice alla soluzione del problema.
In ogni
caso, grazie all’astrazione, dal modello del dominio del problema di partenza
si arriva al modello del dominio della soluzione.
Se gli
use case sono molti una strategia è quella di riportarli su più “fogli”,
cercando di mettere sullo stesso foglio gli use case e gli attori correlati da
<<include>> ed <<extend>>. Questa strategia permette
anche una parallelizzazione di analisi con più persone.
Inoltre
per gli use case testuali il consiglio è di compilare i template degli use case
e di quelli che da cui i primi hanno una dipendenza dovuta agli
<<include>> e <<extend>>.
La
suddivisione del lavoro per il modello delle classi, i diagrammi delle
attività, i diagrammi degli stati e delle sequenze segue la strategia adottata
per gli use case: ogni persona modella la parte che gli discende dagli use case
fatti.
Esaminiamo il problema di gestione di un sistema ATM
(bancomat) di una banca.
q Una
banca ha diversi sportelli ATM (bancomat).
q Gli ATM
sono connessi via WAN ad un server.
q Il
generico ATM ha un reader, un display/tastiera, una stampante.
q L’uso
dell’ATM permette: prelevare soldi da un account, chiedere l’estratto conto,
trasferire fondi.
q La carta
bancomat è caratterizzata da: card#, data di start, data di scadenza.
Sistema:
ü Valida
la carta bancomat: controlla se scaduto, controlla il PIN, controlla se la
carta è stata persa o rubata
ü Permette
tre tentativi d’inserimento PIN: al terzo fallimento ritira la carta
ü Per
semplicità si suppone che presenta un menù solo tre scelte: prelievo, estratto
conto, trasferimento fondi.
Prelievo:
·
Controlla se esistono sufficienti fondi sul conto, se
esistono contanti nell’ATM
·
Controlla se esiste sufficiente contante nell’ATM
·
Controlla se esiste carta per la stampa delle ricevute
·
Termina fornendo i soldi, la carta e la ricevuta della
situazione dell’account
Trasferimento
fondi:
·
Verifica se nel primo account esistono sufficienti fondi
·
Controlla se esiste sufficiente contante nell’ATM
·
Controlla se esiste carta per la stampa delle ricevute
·
Effettua il trasferimento dei fondi
·
Fornisce la ricevuta della situazione del primo account
·
Restituisce la carta bancomat
Estratto
conto:
·
Controlla se esiste carta per la stampa delle ricevute;
·
Stampa il bilancio dell’account richiesto
·
Fornisce la ricevuta della situazione dell’account
·
Restituisce la carta bancomat
Cliente:
ü Cancella
una transazione per volta;
ü La
transazione termina e ritira la carta
ü Il
cliente ha un account (conto deposito) su cui ha dei soldi;
Server:
ü dati
cliente, dati account, registrazione addebito sulla carta
Operatore ATM:
ü attiva/disattiva
l’ATM per rifornirlo di contanti e per manutenzione.
Per
semplicità facciamo alcune assunzioni:
1. il sistema
che apre/chiude account esiste già, le operazioni di create/update/delete dei
dati del cliente vengono fatti da esso.
2. gli
scoperti (bilanci negativi sull’account) non vengono conteggiati come interessi
3. il
numero di transazioni superiori a 12 non determina un pagamento alla banca
4. un
prelievo con bancomat ad uno sportello di banca diversa non determina un
pagamento alla banca
Figura 1
In
figura 1 gli <<extend>> sono dovuti a:
v Un
Trasferimento da un primo account ad un secondo provoca l’accredito al secondo
account e l’addebito sul primo account ma non varia la quantità di contante
caricata sull’ATM;
v Un
Prelievo provoca l’addebito sull’account del cliente e una diminuzione del
contante caricato sull’ATM da parte dell’operatore.
In
figura 1 gli <<include>> sono dovuti a:
v Verifica
del PIN inserito (il codice)
v Verifica
se il bancomat fa parte di una lista di persi, rubati, scaduti
v Verifica
se l’account ha i soldi richiesti per il prelievo o per il trasferimento
v Verifica
se la somma richiesta supera il Limite di carta
v Stampa
della ricevuta per Prelievo, Trasferimento, Estratto conto
In
figura 1 le generalizzazioni sono dovute alle alternative di
comportamento rispetto allo use case base.
Ad esempio ValidaPIN ha tre alternative, mentre VerificaSoldiAccount ne ha due.
Riportiamo solo gli use case di maggior interesse. Gli
altri dovrebbero essere riportati in analogo modo.
USE CASE: Trasferimento
|
|
Attore che lo attiva
|
Cliente ATM |
Precondizione |
ATM idle con messaggio di benvenuto |
Dipendenze |
Include ValidaPIN, VerificaAccount, VerificaLimiteCarta,
StampadiRicevuta |
Descrizione |
1. Il cliente
chiede il trasferimento di una quantità di fondi da un primo account ad un
secondo 2. il sistema verifica che il primo account deve avere sufficienti fondi per trasferirli 3. il
sistema addebita sul primo account 4. il
sistema accredita sul secondo account 5. il
sistema stampa la ricevuta 6. il
sistema restituisce la carta |
Alternative |
1. carta
rigettata: fondi insufficienti 2. carta
rigettata, per errore del PIN 3. carta
con limite inferiore alla somma 4. carta
sequestrata 5. annullamento
della transazione 6. annullamento
accesso 7. riimposta
somma |
PostCondizione |
Il trasferimento fondi è avvenuto |
Invariante |
|
Note |
|
USE CASE: ValidaPIN
|
|
Attore che lo attiva
|
- |
Precondizione |
ATM idle e mostra un messaggio di benvenuto |
Dipendenze |
Include RiinserimentoPIN, AnnullaAccesso,
CartaSequestrata |
Descrizione |
1. il
cliente inserisce la carta bancomat nel lettore 2. se la
carta è valida (non rubata, persa, scaduta) mostra la form per il PIN 3. il
cliente inserisce il PIN 4. Verifica
che il PIN è corretto |
Alternative |
1.Se la carta è scaduta, rubata, persa il sistema
sequestra la carta. 2. Se il PIN è errato esce di nuovo il form del PIN col
messaggio 3. Se il PIN è errato per 3 inserimenti la carta è
sequestrata |
PostCondizione |
Il PIN è valicato |
Invariante |
|
Note |
|
USE CASE: Prelievo
|
|
Attore che lo attiva
|
Cliente ATM |
Precondizione |
ATM idle con messaggio di benvenuto |
Dipendenze |
Include ValidaPIN, VerificaAccount, VerificaLimiteCarta,
StampadiRicevuta |
Descrizione |
§
Il cliente chiede una certa quantità di soldi in
base a varie scelte impostate a video §
il sistema verifica che l’account ha sufficienti
soldi per darli §
il sistema addebita sull’ account §
il sistema stampa la ricevuta |
Alternative |
1. carta
rigettata: fondi insufficienti 2. carta
rigettata, per errore del PIN 3. carta
con limite inferiore alla somma 4. carta
sequestrata 5. annullamento
della transazione 6. annullamento
accesso 7. riimposta
somma |
PostCondizione |
Il prelievo è avvenuto |
Invariante |
|
Note |
|
Nelle note è possibile inserire requisiti non funzionali o altri particolari.
Vediamo una prima versione del
modello.
Figura 2 – Un primo diagramma delle classi
Nella fig. 2 sono state utilizzate un misto di tecniche: Use Case Driven (secondo RUP), il metodo del linguaggio formale, il metodo a colori di Coad [DR4].
Inoltre si è già guardato ad un’estensione dei comandi dell’ATM con il Pattern Command per gli eventuali ed ulteriori comandi necessari: ricarica telefonino, pagamento bollette, etc. [DR6][DR7].
Il modello delle classi di fig. 2 non è ancora soddisfacente, almeno in termini di contesto e di Collapsing e di individuazione di archetipi [DR4].
Occorre eliminare ciò che non interessa al dominio del problema e stare attenti alla differenza tra classe ed attributo.
Nel nostro caso è inutile tener conto che l’ATM abbia una stampante e un dispositivo per inserire contante.
Nel caso reale, invece, sarebbe utile considerarlo e far uso anche di classi astratte in modo da scrivere driver sostituibili.
E’ necessario, invece, sapere se l’ATM è in manutenzione, se dispone di contante e che sia in grado di leggere la carta bancomat.
In particolare leggiBancomat() accetta il PIN digitato dall’utente, ha la routine di lettura della banda magnetica del bancomat e ritorna un oggetto CartaBancomat valorizzato.
Il metodo getAtm() restituisce un boolean. Esso indica se lo sportello ATM è Busy (false) o disponibile (true).
Lo sportello ATM può essere busy per uno di due motivi: in manutenzione o c’è già un cliente con carta bancomat che lo sta usando.
Per cui setAtm(false) va usato sia nel caso di ATM in manutenzione per inserimento contante, sia per cliente che lo sta utilizzando. Mentre setAtm(true) fa sì che lo sportello ATM presenti il messaggio di benvenuto.
Sono state fatte delle assunzioni: il contante presente sull’ATM iniziale è di 1.000.000 di euro e che il limite di prelievo di una carta è di 1.000 euro.
Per il contesto ha poco interesse la Banca come Party, viste le assunzioni iniziali del problema; difatti la Banca entrerebbe in gioco nel momento che maturasse interessi sugli scoperti, incassasse soldi sul numero di transazioni maggiori di 12 sull’account.
Nel modello sono stati poi introdotti dei metodi assegnando le giuste responsabilità (Pattern GRASP) [DR7].
Bisogna anche ricordare di introdurre un Pattern Singleton sul bilancio (soldi sull’account del cliente) per gestire la concorrenza di accessi ad esso.
Se non lo si fa si avrà che mentre avvengono due decrementi di 1000 euro contemporaneamente, l’account ne conterà solo uno.
La concorrenza sullo stesso account è possibile metterla in evidenza con un diagramma delle attività.
Il diagramma delle classi diventa quello di fig. 3
Figura 3 – Il raffinamento del primo modello
Il package complessivo sarà ATM. Al suo interno avrà i package: Boundary, Control, Entity, DatabaseDAO, DataBaseInterf.
Nel Package Boundary vanno messe tutte le classi che stanno a cavallo del confine tra attore e sistema. Per cui è facile immaginare che nel Boundary vadano Cliente e Operatore che serviranno da GUI. Nel Boundary rientrerebbe anche la Banca eventualmente se non esistessero le assunzioni iniziali fatte.
Nel Package Control vanno le classi di controllo come ATMCommand e le sue derivate.
Nel Package Entity andranno tutte le altri classi che hanno necessità di persistenza sul DB.
Nel Package DataBaseDAO le classi che permettono una separazione (Pattern DAO) tra Entità e Database e il Package DataBaseInterf che effettua il collegamento, le chiamate SQL verso il DB.
Figura 4 – Struttura organizzativa
Oltre ai diagrammi visti conviene almeno vedere dei sequence diagram. Col Sequenze Diagram si ha anche un ritorno sulla sufficienza dei metodi in gioco.
Figura 5 – Un Sequence Diagram
Deve essere installato un prodotto software per il controllo delle ascensori in un edificio.
Il software deve muovere degli
ascensori da un piano all’altro dell’edificio obbedendo ai seguenti costraints:
Figura 6
Lo scenario è del tipo:
q
Un passeggero preme un pulsante di piano che si accende;
q
Il sistema rileva che un pulsante di piano è stato
premuto;
q
L’ascensore viene spostato verso il piano;
q
Le porte dell’ascensore vengono aperte;
q
Il passeggero entra e prema i bottoni dell’ascensore;
q
L’ascensore si muove al piano richiesto;
q
L’ascensore apre le porte;
q
Il passeggero esce;
q
L’ascensore chiude le porte.
I diagrammi in modalità testuale in questo caso semplice
non vengono riportati.
Il controller, quindi, controlla i seguenti oggetti:
q
L’ascensore per spostarlo
q
I bottoni interni all’ascensore ed esterni di piano
q
Le porte dell’ascensore
In particolare i bottoni comunicano con il controller.
Figura 7
Figura 8
[DR1] Martin Fowler – UML
Distilled – Prima edizione italiana
[DR2] Leszeck A. Maciaszek -
Sviluppo di sistemi informativi con UML
[DR3] Rosario Turco – Usabilità
e ripetibilità dei processi produttivi software
[DR4] Rosario Turco – Modellare
con l’UML ed i colori
[DR5] Robert C. Martin – Design Principles and Design
Patterns
[DR6] Gamma, Helm,
Johnson,Vlissides – Design Patterns – Elementi per il riuso di software a
oggetti – Prima edizione italiana
[DR7] Rosario Turco - Pattern e
la “GRASP Oriented Analysis”
INDICE
Requirements and
Analysis Model
Descrizione testuale degli Use Case
Customizing,
Collapsing, Design Refactoring e Riuso
Requirements and
Analysis Model