I diagrammi UML possono essere creati in diverse fasi del ciclo di vita, con diversi scopi e livelli di dettaglio.
Quando si sviluppa un domain model si tende a scoprire classi che fanno parte del dominio.
Nel lavorare all’interfaccia utente o all’architettura, si tende ad inventare classi:
Ad una classe dovrebbe corrispondere un’entità del dominio del problema…
Il suo nome ne rispecchia l’intento.
È una astrazione ben definita che modella un elemento del dominio del problema.
Ha un insieme ridotto e ben definito di responsabilità.
Ha una massima coesione interna.
Una classe è tanto più coesa quanto più riesce ad assolvere da sola alle proprie responsabilità.
Semplice tecnica per scoprire le classi del dominio:
Parti con le classi ritenute centrali ed importanti.
Stabilisci i dati ovvi e chiari che esse contengono e le loro relazioni con altre classi.
Procedi con le classi meno importanti.
Evita di aggiungere troppi attributi ed associazioni ad una classe.
Un sistema è più semplice se manipola meno informazioni.
Le classi devono avere poche dipendenze da altre classi.
Una associazione dovrebbe esistere se una classe:
Specificare le molteplicità da entrambi i lati.
Assegnare un nome chiaro all’associazione.
Un errore comune consiste nel considerare azioni come se fossero associazioni.
Meglio: l’operazione presta crea un Prestito e l’operazione restituisci setta la data di restituzione (fig.1).
Nell’implementazione della classe Prestito in C++ compariranno due attributi puntatori a un oggetto SocioLibreria e un oggetto ArticoloLibreria (fig.2).
Cercare le informazioni che devono essere conservate per ciascuna classe;
È possibile che nomi che sono stati scartati come classi, possano ora essere considerati attributi;
Un attributo dovrebbe in genere contenere un solo valore;
È bene non avere molti attributi duplicati. Se un sottoinsieme degli attributi di una classe forma un gruppo coerente, crea una classe distinta per questi attributi.
Due modi per trovare le generalizzazioni:
Crea un interfaccia, invece di una superclasse se:
Una responsabilità è un qualcosa che è richiesto al sistema.
La responsabilità di ogni requisito funzionale deve essere attribuita ad una delle classi, anche se tale requisito potrà essere svolto mediante una collaborazione fra più classi.
Tutte le responsabilità di una classe dovrebbero essere chiaramente correlate.
Se una classe ha troppe responsabilità, valutare l’ipotesi di dividerla in più classi.
Se una classe non ha responsabilità, probabilmente è inutile.
Quando una responsabilità non può essere attribuita a nessuna delle classi. esistenti, dovrebbe essere creata una nuova classe.
Per stabilire le responsabilità:
CRC sta per Class Responsibility Collaboration.
Per ogni classe identificata, porre il nome della classe su una scheda (Card). Man mano che vengono individuati attributi e responsabilità, elencarli sulle Card.
Sistemare le card su una lavagna per creare il Class diagram. Disegnare le linee corrispondenti ad associazioni e generalizzazioni.
Le operazioni saranno necessarie a realizzare le responsabilità di ciascuna classe.
Ci saranno in genere diverse operazioni per realizzare ogni responsabilità, ma una in particolare avrà l’impegno della responsabilità.
Le principali operazioni che implementano una responsabilità sono normalmente dichiarate public
.
Altri metodi che collaborano a realizzare una responsabilità devono essere dichiarate private se possibile.
Una azienda produttrice di prodotti alimentari, vuole organizzare un sistema informativo aziendale. Tutti gli utenti dell’applicazione devono essere in grado di visualizzare informazioni relative al catalogo dei prodotti. Inoltre i dipendenti devono essere in grado di accedere ad informazioni relative alle loro mansioni.
I prodotti sono organizzati in linee di prodotto che accomunano prodotti dello stesso tipo: ad esempio, due linee possono essere pasta e sughi. I prodotti possono essere confezionati in diversi stabilimenti. I dipendenti si suddividono in diverse categorie: i manager, che sono responsabili di una o più linee di produzione (ogni linea é però gestita esattamente da tre manager, per assicurare una gestione equa), i supervisori della produzione che sono responsabili di tutti i prodotti di una specifica linea in uno specifico stabilimento, e gli operai che lavorano su uno specifico prodotto in un determinato stabilimento.
L’applicazione deve consentire ai manager di accedere alle informazioni relative ai dipendenti di cui sono responsabili, e a tutti di accedere alle informazioni sui prodotti.
Vincolo: le azioni possono essere vendute solo negli stessi ’stock’ (gruppi a quantità fissata) che erano stati acquistati, quindi la classe AcquistoAzione andrebbe rinominata in AcquistoStockAzione.
Per poter vendere anche azioni separatamente dagli stock (ad esempio rivendere una per una le azioni comprate in stock) è necessario mettere una nuova classe associativa Vendita, tra Giocatore e SocietàQuotata, con attributo QuantitàVenduta.
Una soluzione equivalente a quella proposta la si poteva ottenere considerando una classe SocietàMonitorata come specializzazione di SocietàQuotata, associata quindi soltanto a Giocatore e a GiornoMonitorato.
MonitoraggioAzione poteva fondersi con GiornoMonitorato, dato che non ci sono specifici attributi/associazioni/responsabilità che rendano necessaria MonitoraggioAzione (in questo caso la responsabilità Monitora viene risolta completamente da Giocatore.
Il Bilancio per giocatore e per squadra non è riportato come attributo perchè è calcolabile (e deve sicuramente essere calcolato nell’ambito di Premio.Assegna. In fase di raffinamento, si può inserire un’operazione CalcolaBilancio in Squadra e in Giocatore.
1. Introduzione
4. Casi d'uso
6. Class Diagram – parte prima
7. Class diagram – parte seconda
8. Class diagram – parte terza
9. Modellazione architetturale
10. Sequence Diagram
14. Progettazione Architetturale
15. Design Patterns – Parte prima
16. Design Patterns – Parte seconda
17. Progettazione dell'interfaccia utente
Martin Fowler, UML Distilled, capitolo 3, 5 (class diagram).