Vai alla Home Page About me Courseware Federica Living Library Federica Federica Podstudio Virtual Campus 3D Le Miniguide all'orientamento Gli eBook di Federica La Corte in Rete
 
 
Il Corso Le lezioni del Corso La Cattedra
 
Materiali di approfondimento Risorse Web Il Podcast di questa lezione

Porfirio Tramontana » 6.Class Diagram – parte prima


Class diagram

Il più diffuso diagramma compreso in UML è il diagramma delle classi.
Si tratta di un diagramma statico che può essere utilizzato:

  • Per la modellazione concettuale del dominio di un problema;
  • Per la modellazione delle specifiche richieste ad un sistema;
  • Per modellare l’implementazione (object-oriented) di un sistema software.

I concetti fondamentali di un class diagram sono estensioni dei concetti fondamentali dei paradigmi object-oriented.

Nel seguito verrà presentato il class diagram nella sua accezione più completa, relativa alla modellazione dell’implementazione di sistemi object-oriented.

Aspetti principali

I principali elementi dei class diagram sono:

  • Classi
    • Rappresentanti i tipi di dati presenti in un sistema;
  • Associazioni
    • Rappresentano i collegamenti fra istanze di classi;
  • Attributi
    • Sono i dati semplici presenti nelle classi e nelle loro istanze;
  • Operazioni
    • Rappresentano le funzioni svolte dalle classi e dalle loro istanze;
  • Generalizzazioni
    • Raggruppano le classi in gerarchie di ereditarietà.

Classi

Una classe è semplicemente rappresentata da un rettangolo con il nome della classe all’interno.
Il concetto di classe è lo stesso dell’OO.

La signature completa di un’operazione è:
operationName(parameterName: parameterType …): returnType


Attributi

visibilità nome molteplicità: tipo = default {proprietà}

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.

Il nome dell’attributo é l’unico parametro necessario.

Il tipo dell’attributo può essere un tipo standard (int, double, char, etc…) oppure il nome di una classe definita nello stesso diagramma (in tal caso forse l’attributo andrebbe indicato con un’associazione …).

Default rappresenta il valore di default dell’attributo.

Attributi (segue)

nome molteplicità: tipo = default {proprietà}

La molteplicità indica il quantitativo degli attributi (ad esempio la dimensioni per un array). Tramite la molteplicità è possibile indicare come attributi degli array o matrici. Il valore di default é 1.

Alcuni valori possibili sono:
1 (uno e uno solo). E’ il valore di default;
0..1 (al più uno);
* (un numero imprecisato, eventualmente anche nessuno; equivalente a 0..*);
1..* (almeno uno).

Gli elementi di una molteplicità sono considerati come un insieme.
Se essi sono dotati anche di ordine si aggiunge l’indicazione {ordered}.
Se sono possibili valori duplicati si aggiunge l’indicazione {nonunique}

{proprietà} rappresenta caratteristiche aggiuntive dell’attribute (ad esempio la sola lettura); Esempio: name: String [1] = “Untitled” {readOnly}.

Metodi

visibilità nome (lista parametri) : tipo-ritornato {proprietà}

La visibilità e il nome seguono regole analoghe a quelle degli attributi.

Lista parametri contiene nome e tipo dei parametri della funzione, secondo la forma:
direzione nome parametro: tipo = valore-di-default

direzione: input (in), output (out) o entrambi (inout). Il valore di default é in.
nome, tipo e valore di default sono analoghi a quelli degli attributi.
Tipo-ritornato é il tipo del valore di ritorno: dovrebbe essere un tipo appartenente ad una classe standard.

Esempio:  + balanceOn (date: Date) : Money

Associazioni

Un’associazione rappresenta una relazione (fisica o concettuale) tra classi.
Esempio (fig.1): Persona possiede Automobile

  • Il verso dell’associazione indicato in figura indica in che direzione deve essere letta l’associazione
    • In questo caso indica che è la Persona a possedere l’Automobile e non l’Automobile a possedere la Persona!
  • In alternativa, si può indicare il ruolo di uno dei due estremi dell’associazione (fig.2).
Fig. 1

Fig. 1

Fig. 2

Fig. 2


Verso di navigazione di un’associazione

Il verso di navigazione è un’informazione utile soprattutto in fase di progetto di dettaglio.
Indica in quale direzione è possibile reperire le informazioni.

Nell’esempio in figura, nota una persona è possibile sapere quali sono le automobili che possiede (se ne possiede).

Viceversa, non è possibile conoscere il possessore di una data automobile.

Non ci sono, però, indicazioni sul quantitativo di automobili possedute, nè sul numero di proprietari di un automobile (da questo diagramma non possiamo sapere se si tratti di informazioni non note o di informazioni soppresse).

Di solito, il verso di navigazione rappresenta una scelta di progetto, per cui non è presente nei diagrammi concettuali.


Molteplicità delle associazioni

La molteplicità delle associazioni indica il numero di istanze di oggetti di ogni classe che possono appartenere ad una istanza della associazione.

In figura:

  • una Persona possiede almeno una Automobile
    • evidentemente le persone che non possiedono Automobile non fanno parte del problema in oggetto…. Uno ed uno solo
  • un’Automobile può essere posseduta da una e una sola Persona
    • evidentemente, non è nel problema in oggetto il mantenimento di informazioni riguardo i proprietari di automobili di seconda, terza mano, etc.

Quest’esempio si configura come associazione uno a molti (una Persona, molte Automobili).


Associazioni molti-a-molti

Uno studente può conseguire un numero potenzialmente non limitato di esami;
Un esame può essere conseguito da un numero potenzialmente non limitato di studenti;
Possono esserci studenti che non hanno conseguito esami;
Possono esserci esami non conseguiti (ancora) da nessuno studente;

Se avessimo voluto modellare il caso in cui uno studente era considerato solo dal momento del conseguimento del primo esame, allora sarebbe stato (vedi figura).


Associazioni Uno-a-uno

Ogni studente ha uno e un sol badge

  • Non è possibile modellare, in caso di smarrimento e rilascio di un nuovo badge, l’elenco di tutti I badge avuti da uno studente nel tempo.

Un badge identifica uno e un solo studente.
Se avessimo voluto considerare anche studenti che, magari temporaneamente, non abbiano un badge, allora diventa: (vedi figura).


Codifica delle associazioni

Molti a uno (es.: una Persona, molte Automobili):

  • La classe Automobile ha un attributo Persona;
  • oppure la classe Persona ha un attributo array di Automobile;
  • o entrambe le cose.
  • La differenza tra le tre soluzioni è identificata dai versi della frecce di navigazione;
  • Si è parlato genericamente di array ma in realtà potrebbe trattarsi di una qualsiasi struttura vettoriale.

Codifica delle associazioni (segue)

Molti a molti (es: molti Studente, molti Esame)

  • La classe Studente è implementata avendo anche un attributo array di Esame;
  • La classe Esame è implementata avendo anche un attributo array di Studente;
  • Entrambe le cose.

Uno a Uno (es: uno Studente, un Badge)

  • La classe Badge è implementata avendo un attributo Studente;
  • La classe Studente è implementata avendo un attributo Badge;
  • Entrambe le cose.

Esempio

Associazione uno a uno

class A {
Public: link(B* linkato):ruolo_di_B(linkato) {}
Private: B* ruolo_di_B;
};

Class B {
Public: link(A* linkato):ruolo_di_A(linkato) {}
Private: A* ruolo_di_A;
};

Void main() {
A a;
B b;
a.link(&b);
b.link(&a);
};

Esempio (segue)

Associazione uno a molti

class A {
Public: aggiungi(B* newobj);
rimuovi(B* oldobj);
Private: lista_puntatori_a_B;
};

Class B {
Public: link(A* linkato):ruolo_di_A(linkato) {}
Private: A* ruolo_di_A;
};

Controesempi

A volte le associazioni uno a uno sono inutili. 
Soluzione da Evitare.

A volte le associazioni uno a uno sono inutili. Soluzione da Evitare.

Migliore soluzione!

Migliore soluzione!


Un esempio più complesso

Una prenotazione si riferisce sempre ad un solo passeggero:

  • Non esistono prenotazioni con zero passeggeri
    • Ciò implica che prima di creare una prenotazione deve esistere un passeggero;
  • Una prenotazione non può mai riferirsi a più di un passeggero.

Un Passeggero può avere più prenotazioni

  • Un passeggero potrebbe avere zero prenotazioni;
  • Un passeggero potrebbe avere più di una prenotazione.

Una prenotazione si riferisce ad un volo.

Un volo può avere più passeggeri prenotati.


Classi associative

In alcuni casi, un attributo che si riferisce a due classi collegate non può essere riferito a nessuna delle due.

Può esistere nel caso di molteplicità molti-a-molti.

Prima di creare un’istanza della classe Voto, devono esistere le istanze delle classi collegate.

La classe associativa può avere attributi, metodi, altre associazioni.


Associazioni riflessive

Associazioni che collegano una classe con sè stessa.

Associazioni che collegano una classe con sè stessa.

Permette, per ogni atleta, di risalire al distacco da tutti gli altri atleti.

Permette, per ogni atleta, di risalire al distacco da tutti gli altri atleti.


Aggregazione

Le Aggregazioni sono speciali associazioni che rappresentano una relazione ‘tutto-parti’.

Il lato del ‘tutto’ è spesso chiamato l’aggregato.

La molteplicità dal lato del tutto, quando è sottintesa, vale 0..1


Quando usare una aggregazione

Una associazione diventa una aggregazione se:

  • È possibile affermare che:
    • Le parti sono ‘parte di’ un insieme;
    • L’aggregato è ‘composto da’ parti.
  • Quando qualcosa possiede o controlla l’aggregato, allora esso possiede o controlla anche le sue parti.

Per quanto le aggregazioni siano importante dal punto di vista della espressività del modello, spesso sono implementate in maniera identica rispetto ad associazioni di pari cardinalità.

Una gerarchia di aggregazione

Esercizio proposto: modellare i concetti di file e directory nell’ambito di un file system.

Esercizio proposto: modellare i concetti di file e directory nell'ambito di un file system.


Composizione

Una composizione è una forma forte di aggregazione.

Se l’aggregato viene distrutto, anche le sue parti saranno distrutte (le parti non esistono senza il tutto).

Evidentemente, in questo dominio, non ha senso parlare di stanze fintantochè esse non siano state legate alla casa in cui si trovano. La cardinalità dell’aggregazione, se sottintesa, vale 1.


Esempio di aggregazione

Consideriamo il seguente esempio:

Esso esprime il concetto che l’Automobile (ogni istanza di Automobile) ha una Carrozzeria ed un Motore.

La specifica prodotta indica un contenimento in senso lasco. Per quanto detto scegliamo la traduzione di tale relazione tramite l’uso dei puntatori.


Esempio di aggregazione (uno a uno)

//file Automobile.h
#include "Motore.h"
#include "Carrozzeria.h"
class Automobile {
public:
//il costruttore inizializza Automobile anche in assenza di Motore e Carrozzeria
Automobile(Stringa marca= "", Stringa mod="",..., Motore* mot=0, Carrozzeria* car=0);
...
private:
Carrozzeria* carrozzeria; //traduzione aggregazione
Motore* motore; //traduzione aggregazione
...
};

//file Automobile.cpp
//Costruttore di Automobile

Automobile:: Automobile(Stringa marca, Stringa mod,...,Motore* mot, Carrozzeria* car) :
marca(marca), modello(mod),motore(mot), carrozzeria(car);

Esempio di aggregazione (uno a uno) (segue)

Il programma principale dovrà dapprima creare un oggetto di tipo Carrozzeria e Motore ed infne l’oggetto di tipo Automobile. Ad esempio:

#include "Automobile.h"
main () { //usa classe Automobile
//definisce e inizializza oggetto di tipo Motore
Motore m("AZ123","Ferrari", 6,12,1000);
//definisce e inizializza oggetto di tipo Carrozzeria
Carrozzeria c("12345ASA", "RossoFerrari",1500);
//definisce e inizializza puntatore a motore
Motore* puntatoreMotore=&m;
//definisce e inizializza puntatore a carrozzeria
Carrozzeria* puntatoreCarrozzeria=&c;
//definisce e inizializza oggetto Automobile, fornendo puntatori
Automobile auto1("Ferrari", ..., puntatoreCarrozzeria, puntatoreMotore);

...
} //al termine vengono separatamente distrutti m,c e auto1

Esempio di aggregazione (uno a uno) (segue)

Affinchè si possa parlare di contenimento stretto (composizione) deve essre garantito che la classe Contenitore sia effettivamente l’unica ad accedere al metodo costruttore della classe Contenuto.

Affinchè si possa parlare di contenimento stretto (composizione) deve essre garantito che la classe Contenitore sia effettivamente l'unica ad accedere al metodo costruttore della classe Contenuto.


I materiali di supporto della lezione

Ian Sommerville, Ingegneria del Software, capitolo 8, 14.

Martin Fowler, UML Distilled, capitolo 3, 5 (class diagram).

Carlo Savy, Da C++ a UML, capitolo 34.

  • Contenuti protetti da Creative Commons
  • Feed RSS
  • Condividi su FriendFeed
  • Condividi su Facebook
  • Segnala su Twitter
  • Condividi su LinkedIn
Progetto "Campus Virtuale" dell'Università degli Studi di Napoli Federico II, realizzato con il cofinanziamento dell'Unione europea. Asse V - Società dell'informazione - Obiettivo Operativo 5.1 e-Government ed e-Inclusion