UML 2.5 definisce 14 tipi di diagrammi, organizzati in due famiglie:
| Famiglia | Cosa descrive | Esempi |
|---|---|---|
| Strutturali | Com'è fatto il sistema | classi, oggetti, componenti |
| Comportamentali | Come si comporta il sistema | casi d'uso, sequenze, stati |
Non è necessario usarli tutti: si scelgono quelli utili al problema che si sta descrivendo.
In questa presentazione ci concentreremo sul diagramma delle classi, che è il più usato nella progettazione OOP.
Una classe è un rettangolo diviso in tre scomparti:
+---------------------------+
| Auto | ← nome della classe
+---------------------------+
| - marca: string |
| - velocitaMax: int | ← attributi (campi)
+---------------------------+
| + Avvia(): void |
| + Ferma(): void | ← metodi (operazioni)
| + ToString(): string |
+---------------------------+
Davanti a ciascun membro si mette un simbolo di visibilità:
| Simbolo | Significato | Equivalente C# |
|---|---|---|
+ |
public | public |
- |
private | private |
# |
protected | protected |
Attributo:
visibilità nome : tipo [= valoreDefault]
Esempio: - velocitaMax: int = 0
Operazione:
visibilità nome(par1: tipo1, par2: tipo2): tipoRitorno
Esempio: + Somma(a: int, b: int): int
Se non c'è tipo di ritorno si omette
<<abstract>>+-----------------------------------+
| /Veicolo/ | ← astratta (corsivo)
+-----------------------------------+
| # marca: string |
| - _contatore: int |
+-----------------------------------+
| + Avvia(): void |
| + /Descrizione()/: string | ← astratto (corsivo)
+-----------------------------------+
Le classi non vivono isolate: sono collegate da relazioni. Le principali sono:
| Relazione | Simbolo UML | "Senso" |
|---|---|---|
| Aggregazione | rombo vuoto ◇ |
"ha un" |
| Composizione | rombo pieno ◆ |
"è fatto di" |
| Generalizzazione | freccia vuota △ |
"è un" |
Squadra ◇-------- Giocatore
1 1..*
Se la Squadra viene sciolta, i Giocatore continuano a esistere.
Libro ◆-------- Capitolo
1 1..*
Se si distrugge il Libro, anche il
Capitolo cessa di esistere.
| Aspetto | Aggregazione (◇) | Composizione (◆) |
|---|---|---|
| Ciclo di vita | indipendente | condiviso con il tutto |
| La parte esiste sola | sì | no |
| Esempio | Università - Studente | Casa - Stanza |
Regola pratica: se la "parte" può essere condivisa o sopravvivere al "tutto", è aggregazione.
Veicolo
△
|
+--------+--------+
| |
Auto Moto
Auto è un Veicolo; Moto
è un Veicolo.
Modelliamo un piccolo sistema di gestione di una biblioteca:
Biblioteca è
composta di Libro
(composizione)Biblioteca ha un
insieme di Utente iscritti
(aggregazione)UtenteStandard e UtentePremium (ereditano da Utente)In questo esempio compaiono solo le quattro relazioni viste: composizione, aggregazione, generalizzazione.
/Utente/
# nome: string
+ /TipoTariffa()/: string
△
+-------+-------+
| |
UtenteStandard UtentePremium
+ TipoTariffa() + TipoTariffa()
Biblioteca ◆------- Libro Biblioteca ◇------- Utente
1 1..* 1 *
(composizione) (aggregazione)
| Classe | Tipo | Relazione con le altre |
|---|---|---|
| Utente | astratta | |
| UtenteStandard | concreta | eredita da Utente |
| UtentePremium | concreta | eredita da Utente |
| Biblioteca | concreta | composta di Libro,
aggrega Utente |
| Libro | concreta | parte della Biblioteca
(composizione) |
abstract class Utente
{
public int Id { get; }
protected string nome;
protected Utente(int id, string nome)
{
Id = id;
this.nome = nome;
}
public abstract string TipoTariffa();
}
class UtentePremium : Utente
{
public UtentePremium(int id, string nome) : base(id, nome) { }
public override string TipoTariffa() => "Premium";
}class Libro
{
public string Titolo { get; }
public Libro(string titolo) { Titolo = titolo; }
}
class Biblioteca
{
// Composizione: i Libro nascono dentro la Biblioteca
// e ne condividono il ciclo di vita
private List<Libro> _libri = new List<Libro>();
// Aggregazione: gli Utente esistono indipendentemente,
// la Biblioteca si limita a "conoscerli" come iscritti
private List<Utente> _iscritti = new List<Utente>();
public void AggiungiLibro(string titolo)
=> _libri.Add(new Libro(titolo));
public void Iscrivi(Utente u) => _iscritti.Add(u);
} +------------------+
| Biblioteca |
| |
Utente ----( Cerca libro ) |
\ \------( Prenota libro ) |
\ |
Bibliotecario --( Registra prestito )
| |
+------------------+
:Utente :UI :Biblioteca :Libro
| | | |
|--cerca--->| | |
| |--trova------>| |
| | |--getInfo--->|
| | |<--info------|
| |<--risultato--| |
|<-mostra---| | |
Prestito) [inizio]
|
v
Prenotato --richiedi--> Attivo --restituisci--> Concluso --> [fine]
|
scadenza
|
v
Scaduto
@startuml
abstract class Utente {
# nome: string
+ {abstract} TipoTariffa(): string
}
class UtenteStandard
class UtentePremium
Utente <|-- UtenteStandard
Utente <|-- UtentePremium
class Biblioteca
class Libro
Biblioteca "1" *-- "1..*" Libro : contiene
@enduml
Lo stesso diagramma si ottiene da poche righe di testo, versionabili con il codice.
| Elemento | Notazione |
|---|---|
| Classe | rettangolo a 3 scomparti |
| Classe astratta | nome in corsivo |
Membro public |
+ |
Membro private |
- |
Membro protected |
# |
| Relazione | Notazione |
|---|---|
| Associazione | linea |
| Aggregazione | rombo vuoto ◇ (lato del "tutto") |
| Composizione | rombo pieno ◆ (lato del "tutto") |
| Generalizzazione | freccia piena vuota △ verso la
base |
Specifica ufficiale UML: https://www.omg.org/spec/UML/
PlantUML: https://plantuml.com/