I diagrammi di classe sono diagrammi di struttura all’interno dell’Unified Modeling Language, ab­bre­via­to in UML. Il lin­guag­gio di mo­del­la­zio­ne UML è uno standard ISO. Illustra i sistemi di pro­gram­ma­zio­ne orientata agli oggetti. Si possono re­gi­stra­re in modo chiaro anche i processi aziendali. Con l’ausilio di mezzi visivi, l’UML mostra gli stati dei sistemi e descrive le in­te­ra­zio­ni tra elementi del sistema. Per farlo la notazione sta­bi­li­sce forme e linee per 14 tipi di diagrammi.

Diagrammi di classe nel contesto dell’Unified Modeling Language

La me­ta­mo­del­la­zio­ne descrive sia i singoli elementi del lin­guag­gio di mo­del­la­zio­ne che il lin­guag­gio stesso e definisce le unità lin­gui­sti­che per diversi livelli. Ad esempio, un'unità lin­gui­sti­ca in questo lin­guag­gio visivo è il com­por­ta­men­to. Descrive sia una me­ta­clas­se che un termine generico per tutti i fattori dinamici al­l'in­ter­no di un sistema. Un'altra unità lin­gui­sti­ca è l'oggetto, l'e­le­men­to base della pro­gram­ma­zio­ne orientata agli oggetti. I diagrammi delle classi UML modellano gli oggetti come istanze di classi. Pertanto, il diagramma delle classi è uno dei più im­por­tan­ti e am­pia­men­te usati tipi di diagrammi di UML.

I tipi di diagramma sono divisi in due categorie prin­ci­pa­li in base alla loro funzione: diagrammi di struttura e diagrammi di com­por­ta­men­to. Questi ultimi hanno una sot­to­ca­te­go­ria: i diagrammi di in­te­ra­zio­ne, che non solo modellano il com­por­ta­men­to generale di un sistema, ma si con­cen­tra­no anche sui flussi di in­for­ma­zio­ni tra gli oggetti nel corso di un processo. Questi includono, per esempio, i diagrammi di sequenza. Modellano l'ordine cro­no­lo­gi­co dei messaggi che fluiscono in un caso d'uso det­ta­glia­to. I diagrammi com­por­ta­men­ta­li vi­sua­liz­za­no i processi dinamici. Un esempio è il diagramma di attività, che mostra come le singole azioni in­te­ra­gi­sca­no in un flusso. I diagrammi strut­tu­ra­li, d'altra parte, mostrano stati statici; il­lu­stra­no gli elementi di un sistema e le loro in­ter­di­pen­den­ze.

Il diagramma di classe suddivide le istanze oggetto a seconda delle loro proprietà in diverse classi, che hanno tra loro di­pen­den­ze ge­rar­chi­che. Allo stesso tempo esistono relazioni tra le diverse classi o tra oggetti.

Diagrammi di classe UML: campi di ap­pli­ca­zio­ne

I diagrammi delle classi rap­pre­sen­ta­no gli stati con gli elementi del sistema e mostrano le strutture fino al­l'i­stan­za più piccola. Di con­se­guen­za sono adatti per la pre­sen­ta­zio­ne di ar­chi­tet­tu­re software det­ta­glia­te. Da ciò si possono ricavare passi concreti di pro­gram­ma­zio­ne. Alcuni ambienti di pro­gram­ma­zio­ne basati su software con­ver­to­no questi diagrammi UML di­ret­ta­men­te in frame di codice.

Uti­liz­zan­do la con­di­vi­sio­ne del team, gli svi­lup­pa­to­ri co­mu­ni­ca­no tra loro o con altri re­spon­sa­bi­li delle decisioni al­l'in­ter­no di un'a­zien­da. Per i non spe­cia­li­sti, un diagramma UML fornisce una pa­no­ra­mi­ca delle strutture di sistema pia­ni­fi­ca­te o dei flussi di processo. Inoltre, è possibile formulare i requisiti di sistema, che verranno poi im­ple­men­ta­ti dagli svi­lup­pa­to­ri. Gli esperti IT possono modellare e mo­di­fi­ca­re ef­fi­ca­ce­men­te i diagrammi senza dover pro­gram­ma­re ambienti o processi più grandi nella fase di pia­ni­fi­ca­zio­ne.

Di seguito i campi di ap­pli­ca­zio­ne dei diagrammi delle classi:

  • De­scri­vo­no i tipi all’interno di un sistema. La rap­pre­sen­ta­zio­ne grafica può essere tra­sfe­ri­ta in diversi linguaggi e ambienti di pro­gram­ma­zio­ne. Pertanto esiste in­di­pen­den­te­men­te dall’ap­pli­ca­zio­ne futura.
  • Modellano le ar­chi­tet­tu­re software esistenti. Se i com­po­nen­ti aggiunti devono essere integrati, vi­sua­liz­za­no strutture adeguate in cui è possibile in­cor­po­ra­re nuovi com­po­nen­ti. Per i futuri elementi del sistema, i diagrammi delle classi creano una guida per il codice del programma. A seconda delle esigenze, questo passaggio potrebbe essere ap­pros­si­ma­ti­vo o molto det­ta­glia­to.
  • Rap­pre­sen­ta­no modelli di dati e sono adatti a sistemi di varia com­ples­si­tà.
  • Nelle ap­pli­ca­zio­ni ni­di­fi­ca­te, la do­cu­men­ta­zio­ne e la ma­nu­ten­zio­ne possono essere molto complesse. I diagrammi delle classi for­ni­sco­no una pa­no­ra­mi­ca dello schema.
  • Rap­pre­sen­ta­no i requisiti per un software. Come file immagine, possono essere fa­cil­men­te inoltrati tramite canali aziendali interni. Ciò consente agli esperti di diversi reparti di scam­biar­si idee sull’ar­chi­tet­tu­ra.
  • Lo standard UML utilizza diagrammi di classe per rap­pre­sen­ta­re vi­si­va­men­te la propria notazione.

Diagrammi di classe: la notazione UML

I diagrammi delle classi UML con­si­sto­no in classi e nelle relative istanze (oggetti) e in­ter­fac­ce. Creano relazioni ge­rar­chi­che e as­so­cia­zio­ni tra questi elementi. La notazione di questo tipo di diagramma è l’elemento chiave per la maggior parte degli altri diagrammi di struttura. L’UML 2 definisce i diagrammi di struttura come clas­si­fi­ca­to­ri. All’interno della me­ta­mo­del­la­zio­ne UML ci sono diagrammi di pacchetti, diagrammi di com­po­nen­ti e le stesse sot­to­clas­si del diagramma di struttura, che non è però modellato, in quanto si tratta di una classe astratta. Il diagramma di classe è più adatto come esempio di diagramma di struttura. Altri diagrammi di questa categoria uti­liz­za­no com­po­nen­ti mo­di­fi­ca­ti del diagramma delle classi per la loro notazione.

Fatto

Come clas­si­fi­ca­to­re (in inglese: “clas­si­fier”), l’UML comprende una me­ta­clas­se astratta, che serve per assegnare elementi di modello all’interno del lin­guag­gio di mo­del­la­zio­ne a un concetto comune. Questo processo è chiamato ge­ne­ra­liz­za­zio­ne e lo standard si può formulare in generale. Se la specifica si basa su un par­ti­co­la­re elemento, basta spiegare solo questa par­ti­co­la­re ca­rat­te­ri­sti­ca.

La classe

La classe è un elemento del modello nel diagramma delle classi e una spe­cia­liz­za­zio­ne del clas­si­fi­ca­to­re in­cap­su­la­to (En­cap­su­la­te­d­Clas­si­fier) e del clas­si­fi­ca­to­re del com­por­ta­men­to (Be­ha­vio­re­d­Clas­si­fier). Riunisce una grande quantità di istanze. Le istanze di oggetti all’interno di una classe hanno le stesse ca­rat­te­ri­sti­che (At­tri­bu­tes) e com­por­ta­men­ti (Methods). Inoltre hanno la stessa semantica, il che significa che uti­liz­za­no gli stessi segni con lo stesso si­gni­fi­ca­to. In questo modo la classe è un tipo di modello per i loro oggetti. Crea un’istanza degli oggetti e definisce il loro com­por­ta­men­to nel sistema.

Fatto

L’istanza è un’espres­sio­ne concreta di un elemento astratto. Esegue un com­por­ta­men­to pre­scrit­to all’interno dei parametri spe­ci­fi­ca­ti. Alcune istanze sono de­no­mi­na­te da UML in modo esplicito e in questo modo l’oggetto è un’istanza de­no­mi­na­ta della classe. Le proprietà delle istanze si modellano con diagrammi a livello di istanza. Al posto di un diagramma di classe, si disegna ad esempio un diagramma di oggetti.

I clas­si­fi­ca­to­ri in­cap­su­la­ti ampliano i co­sid­det­ti clas­si­fi­ca­to­ri strut­tu­ra­ti. Questi ultimi sono ca­rat­te­riz­za­ti dal fatto che possono pre­scri­ve­re una struttura interna e possono ac­co­glie­re elementi connessi. Questi elementi (me­ta­clas­si: Con­nec­ta­bleE­le­men­ts) in­fluen­za­no il com­por­ta­men­to dei clas­si­fi­ca­to­ri. Ogni elemento connesso rap­pre­sen­ta un par­te­ci­pan­te al com­por­ta­men­to nel clas­si­fi­ca­to­re. Si dice anche che assumano il ruolo. Il clas­si­fi­ca­to­re in­cap­su­la­to ha inoltre un punto di aggancio (Port). Ciò isola il clas­si­fi­ca­to­re dal sistema senza perdere la con­nes­sio­ne.

Le clas­si­fi­ca­zio­ni del com­por­ta­men­to spesso si con­net­to­no a un’in­ter­fac­cia chiamata In­ter­fa­ce­Rea­li­za­tion. Il clas­si­fi­ca­to­re cor­ri­spon­de im­pli­ci­ta­men­te alle con­di­zio­ni dell’in­ter­fac­cia sup­por­tan­do la fun­zio­na­li­tà dell’in­ter­fac­cia. L’In­ter­fa­ce­Rea­li­za­tion (chiamata anche “Lollipop”) si disegna come un cerchio vuoto, collegato alla classe tramite una linea.

Le me­ta­clas­si men­zio­na­te clas­si­fi­ca­no gli oggetti. La classe è l’espres­sio­ne specifica di queste me­ta­clas­si. Quindi definisce la clas­si­fi­ca­zio­ne più da vicino e con­cre­tiz­za le singole com­po­nen­ti che co­sti­tui­sco­no la struttura e il com­por­ta­men­to degli oggetti. Le classi hanno proprietà che de­fi­ni­sco­no le classi stesse nonché gli oggetti su­bor­di­na­ti. Tra queste proprietà si possono men­zio­na­re:

  • Proprietà (Pro­per­ties o At­tri­bu­tes, se ap­par­ten­go­no alla classe)
  • Ope­ra­zio­ni (Ope­ra­tions, possono essere ri­chia­ma­te per un oggetto)
  • Ri­ce­vi­to­ri di segnale (Re­cep­tions) a partire da UML 2.0
  • Porte (Ports) a partire da UML 2.0
  • Con­net­to­ri (Con­nec­tors)

Quando create un diagramma di classi, ag­giun­ge­te queste proprietà alla notazione. In UML una classe si rap­pre­sen­ta come un ret­tan­go­lo con una linea continua. Il suo corpo è composto da tre com­par­ti­men­ti, che sono disposti uno sopra l’altro. Solo la parte superiore deve essere modellata, poiché è lì che si definisce il nome della classe. Le altre due par­ti­zio­ni si possono op­zio­nal­men­te eti­chet­ta­re con attributi (al centro) e ope­ra­zio­ni (in basso). Assegnate una vi­si­bi­li­tà diversa a questi elementi scrivendo i seguenti simboli davanti ai loro nomi:

  • + = pubblico
  • - = privato
  • # = protetto
  • / = derivato
  • ~ = pacchetto
  • * = casuale

Pro­per­ties (proprietà)

Le pro­per­ties sono elementi collegati. Gli attributi di classe (ow­ne­dAt­tri­bu­tes) sono sempre ruoli. Li si collega tramite con­net­to­ri. Se hanno la proprietà isCom­po­si­te = true (“è composto = vero”), allora sono chiamate parti (Parts).

La proprietà UML è una ca­rat­te­ri­sti­ca strut­tu­ra­le che ha diversi utilizzi. Accanto alla funzione come attributo in una classe, può anche rap­pre­sen­ta­re esten­sio­ni di as­so­cia­zio­ne.

Il Property Type deriva dal nome del clas­si­fi­ca­to­re. Fa­col­ta­ti­va­men­te potete spe­ci­fi­ca­re un valore standard per una ca­rat­te­ri­sti­ca; inoltre i mo­di­fi­ca­to­ri spe­ci­fi­ca­no meglio come si comporta una ca­rat­te­ri­sti­ca:

  • ordinata (notazione: isOrdered = true)
  • unica (notazione: isUnique = true)
  • non unica (notazione: isUnique = false)
  • sola lettura (la ca­rat­te­ri­sti­ca si può leggere ma non mo­di­fi­ca­re, notazione: isRea­dOn­ly = true)
  • sequenza (la ca­rat­te­ri­sti­ca è una raccolta ordinata, notazione: isUnique = false e isOrdered = true)
  • unione (unione derivata da sot­toin­sie­mi, notazione: union)
  • ID (ap­par­tie­ne alla de­fi­ni­zio­ne del suo clas­si­fi­ca­to­re, notazione: id)
  • Vincolo di funzione (un vincolo che influenza la proprietà, notazione: property-con­straint)
  • Ri­de­fi­ni­zio­ne di una proprietà (ri­de­fi­ni­sce una proprietà ereditata e de­no­mi­na­ta, notazione: redefines [no­me­pro­prie­tà])
  • Sot­toin­sie­me della proprietà (sim­bo­leg­gia una proprietà che è un sot­toin­sie­me di una proprietà de­no­mi­na­ta: subsets [no­me­pro­prie­tà])

Ope­ra­zio­ni

Le ope­ra­zio­ni sono funzioni com­por­ta­men­ta­li. Si pre­sen­ta­no sotto forma di classi, ma anche di tipi di dati o in­ter­fac­ce. Ri­chia­ma­no di­ret­ta­men­te l’istanza di una classe. L’ope­ra­zio­ne specifica i seguenti aspetti:

  • Nome
  • Tipo
  • Parametro
  • Vincoli

L’ope­ra­zio­ne ap­par­tie­ne al suo clas­si­fi­ca­to­re prin­ci­pa­le, anche se questo può cambiarlo ri­de­fi­nen­do il tipo o i parametri.

Per le ope­ra­zio­ni ci sono con­di­zio­ni pre­li­mi­na­ri che devono essere sod­di­sfat­te prima che venga eseguita l’ope­ra­zio­ne. Tuttavia, l’UML non definisce come si comporta una chiamata di com­por­ta­men­to se non vengono sod­di­sfat­te le con­di­zio­ni pre­li­mi­na­ri. Si impostano anche post­con­di­zio­ni da sod­di­sfa­re quando si conclude l’ope­ra­zio­ne. Le con­di­zio­ni del corpo della classe limitano il risultato in uscita a un valore calcolato dalle sue spe­ci­fi­che. Questo valore dovrebbe sod­di­sfa­re le post­con­di­zio­ni, ma l’ope­ra­zio­ne può anche originare un’eccezione durante l’ese­cu­zio­ne, quindi pro­ba­bil­men­te non soddisfa le post­con­di­zio­ni.

La notazione per il diagramma di classe sta­bi­li­sce che le ope­ra­zio­ni vengano annotate in un com­par­ti­men­to nel corpo della classe. Secondo lo standard UML, questa in­for­ma­zio­ne è ob­bli­ga­to­ria. Allo stesso tempo, l’UML consente di com­pri­me­re tutte le in­for­ma­zio­ni standard all’interno di una classe. Soltanto il nome va annotato.

Ri­ce­vi­to­re di segnale

Un ri­ce­vi­to­re di segnale indica che un clas­si­fi­ca­to­re è pronto a ricevere un segnale. Definisce anche quali tipi di segnali sono accettati dalle istanze della classe. Il ri­ce­vi­to­re di segnale è chiamato come il suo segnale. Le in­for­ma­zio­ni cor­ri­spon­den­ti devono essere annotate nel corpo della classe in un com­par­ti­men­to sotto le ope­ra­zio­ni.

Port

Le co­sid­det­te “port” sono porte per clas­si­fi­ca­to­ri in­cap­su­la­ti. Rap­pre­sen­ta­no un punto in cui il clas­si­fi­ca­to­re in­te­ra­gi­sce con il suo ambiente. A parte le porte, il clas­si­fi­ca­to­re in­cap­su­la­to è un sistema autonomo. Poiché la sua struttura interna e gli elementi di com­por­ta­men­to sono in­di­pen­den­ti dal resto del sistema, è anche possibile definire tale clas­si­fi­ca­to­re in modo in­di­pen­den­te. Finché un sistema soddisfa i limiti della porta, è possibile riu­ti­liz­za­re il clas­si­fi­ca­to­re in­cap­su­la­to in diversi ambienti.

Inoltre, l’UML consente più punti di aggancio per il clas­si­fi­ca­to­re. È possibile definire le proprie regole per ciascuna porta. La porta è una proprietà del clas­si­fi­ca­to­re, quindi si impostano le sue regole nell’area Pro­per­ties. Esse includono i servizi offerti dal clas­si­fi­ca­to­re al suo ambiente e i servizi di cui ha bisogno. È possibile di­stin­gue­re tra diversi flussi di in­for­ma­zio­ni iden­ti­fi­can­do la porta che si sta uti­liz­zan­do.

Anche le porte stesse hanno proprietà. Quando la porta esegue le funzioni pub­bli­ca­te del clas­si­fi­ca­to­re, indica la proprietà isService. Se si verifica isService = true, la porta è con­si­de­ra­ta un com­po­nen­te in­di­spen­sa­bi­le delle funzioni ester­na­men­te visibili del clas­si­fi­ca­to­re in­cap­su­la­to. Se isService = false, la porta non è una delle fun­zio­na­li­tà es­sen­zia­li e può quindi essere mo­di­fi­ca­ta o can­cel­la­ta, proprio come le altre funzioni interne.

Le porte in­te­ra­gi­sco­no con le in­ter­fac­ce. Ci sono in­ter­fac­ce già pronte e ne­ces­sa­rie (vedi il paragrafo “In­ter­fac­ce”). L’in­ter­fac­cia connessa alla porta specifica le in­te­ra­zio­ni che passano tramite la porta. Poiché il punto di aggancio è una proprietà, ha un tipo. Il valore di isCo­n­ju­ga­ted si interpone tra il tipo e l’in­ter­fac­cia della porta. Se il valore è “vero”, l’in­ter­fac­cia richiesta si può derivare di­ret­ta­men­te dal tipo di porta o dall’insieme di in­ter­fac­ce im­ple­men­ta­te dal tipo di porta. Un’in­ter­fac­cia pronta è derivata in questo caso dall’insieme di in­ter­fac­ce. Se isCo­n­ju­ga­ted è “vero”, l’in­ter­fac­cia fornita deriva dal tipo.

Se un clas­si­fi­ca­to­re in­cap­su­la­to genera un’istanza, vengono create istanze ap­pro­pria­te per ciascuna delle sue porte. Una porta mantiene la ri­spet­ti­va istanza in base al suo tipo e alla sua mol­te­pli­ci­tà (vedi sotto). L’UML chiama le istanze punti di in­te­ra­zio­ne. Ogni istanza ha ri­fe­ri­men­ti univoci che si di­stin­guo­no tra le diverse richieste di fun­zio­na­li­tà com­por­ta­men­ta­li in­di­riz­za­te alle sue porte.

Le porte con la proprietà isBe­ha­vior = true mandano una richiesta all’istanza del clas­si­fi­ca­to­re in­cap­su­la­to. La richiesta assume il com­por­ta­men­to spe­ci­fi­ca­to dall’istanza. Le co­sid­det­te “Behavior Ports” (porte com­por­ta­men­ta­li) non inoltrano richieste all’interno del clas­si­fi­ca­to­re. Se non è impostato alcun com­por­ta­men­to nel diagramma delle classi, i messaggi su queste porte andranno persi.

Potete modellare una porta come un piccolo quadrato sul frame del clas­si­fi­ca­to­re a cui ap­par­tie­ne. Nella porta disegnate l’in­ter­fac­cia ne­ces­sa­ria o già fornita. Se non spe­ci­fi­ca­te alcuna proprietà speciale per la porta, disegnate l’in­ter­fac­cia senza porta.

Con­net­to­ri

I con­net­to­ri de­fi­ni­sco­no le con­nes­sio­ni tra due o più istanze. Le spe­ci­fi­che con­sen­to­no la loro co­mu­ni­ca­zio­ne. A dif­fe­ren­za delle relazioni come l’as­so­cia­zio­ne, i con­net­to­ri non collegano le istanze ar­bi­tra­rie, ma solo le istanze definite come con­net­to­ri. I con­net­to­ri sono modellati come linee con almeno due estremità. Rap­pre­sen­ta­no le istanze par­te­ci­pan­ti che assegnano un tipo agli elementi col­le­ga­bi­li.

Mol­te­pli­ci­tà

Un’altra di­men­sio­ne im­por­tan­te è la mol­te­pli­ci­tà. Questo parametro specifica quante istanze può formare una classe strut­tu­ra­ta e limita gli attributi e le ope­ra­zio­ni. Fa parte della struttura interna (questo è un elemento pre­scrit­to nel corpo della classe). Lo inserite dopo gli attributi e le ope­ra­zio­ni. Questa sezione include anche la topologia. I nodi (istanze dell’oggetto) si collegano alle reti di topologia tramite i percorsi di co­mu­ni­ca­zio­ne (Com­mu­ni­ca­tion­Pa­ths).

Annotate le mol­te­pli­ci­tà come segue:

<molteplicità> : <intervallo di molteplicità> [<indicazione ordine> , <identificatore di unicità>]

L’in­ter­val­lo di mol­te­pli­ci­tà indica un valore fisso o un in­ter­val­lo da-a:

  • 0 = la classe non forma le istanze (accade raramente)
  • 0..1 = o nessuna istanza o un’istanza
  • 1 o 1..1 = esat­ta­men­te un’istanza
  • 0..* o solo * = nessuna istanza o più istanze con valore aperto
  • 1..* = una o più istanze con valore aperto

L’ordine e l’unicità si possono esprimere come un set (insieme) o per singoli termini separati da una virgola. A seconda che i nodi del set siano unici o ordinati, al set viene fornita una de­scri­zio­ne del tipo. Nella notazione de­scri­ve­te ogni di­men­sio­ne come ordered/unordered (ordinata/non ordinata) o unique/not unique (unica/non unica).

Tipo di set Unico Ordinato
Sequenza No Sì
Multiset (Bag) No No
Set ordinato Sì Sì
Set Sì No

Vincoli

Bisogna men­zio­na­re anche il vincolo (Con­straint): nelle versioni pre­ce­den­ti di UML, questo elemento rientrava tra le relazioni. L’UML definisce il vincolo come un elemento im­pac­chet­ta­bi­le, il che significa che può ap­par­te­ne­re di­ret­ta­men­te a un pacchetto. Entra anche in tali relazioni con altri elementi, ad esempio con classi o proprietà, ma ciò non influisce sulla notazione. La re­stri­zio­ne è una con­di­zio­ne o garanzia per il suo pro­prie­ta­rio e può in­fluen­za­re uno o più elementi.

L’elemento pro­prie­ta­rio deve avere accesso al vincolo, in modo da poter con­trol­la­re se il vincolo è valido e se è stato sod­di­sfat­to. La pos­si­bi­li­tà che ciò accada dipende dal pro­prie­ta­rio. Alcuni elementi, come l’ope­ra­zio­ne, ve­ri­fi­ca­no i vincoli prima dell’ese­cu­zio­ne, durante e/o in seguito. Hanno pre­con­di­zio­ni, con­di­zio­ni nel corpo della classe e post­con­di­zio­ni. La specifica di quando un elemento debba ve­ri­fi­ca­re il proprio vincolo viene indicata come contesto dall’UML. Si distingue tra il contesto e le spe­ci­fi­che effettive: queste ultime de­scri­vo­no quale elemento tracci la re­stri­zio­ne, quale aspetto venga valutato e quale risultato ci si aspetta. Alla specifica esatta viene assegnato un Con­straint at­tra­ver­so una specifica di valore booleano

La notazione consiste in una stringa di testo nel seguente formato:

<Nome dell’elemento vincolato> ::= { <Nome del vincolo> : <espressione booleana> }

L’UML non prescrive alcuna lingua specifica: nel creare un diagramma delle classi potete scegliere le re­stri­zio­ni che volete nella lingua che preferite. Potete uti­liz­za­re un lin­guag­gio di pro­gram­ma­zio­ne come Java, una lingua naturale o un lin­guag­gio leggibile da una macchina come XML. L’Object Ma­na­ge­ment Group, che sta­bi­li­sce gli standard UML, pubblica l’Object Con­straint Language (OCL). Questa lingua definisce i vincoli com­pa­ti­bi­li con UML. Il loro vantaggio è che si adatta per­fet­ta­men­te alla notazione.

Alcuni elementi vincolati in UML sono scritti come testo, ad esempio un attributo di una classe nel diagramma delle classi. Indicate la re­stri­zio­ne dopo l’elemento di testo tra parentesi graffe. Se si tratta del pro­prie­ta­rio di un elemento che rap­pre­sen­ta­te come un’icona, po­si­zio­na­te il vincolo il più vicino possibile all’icona; in questo modo dovrebbe essere evidente che i due elementi hanno una relazione semantica. Per rendere ancora più chiara la con­nes­sio­ne, scrivete la re­stri­zio­ne in un’icona di nota e col­le­ga­te­la al pro­prie­ta­rio con una linea trat­teg­gia­ta.

Se la re­stri­zio­ne si applica a due elementi, con­net­te­te i pro­prie­ta­ri con una linea trat­teg­gia­ta. Scrivete il vincolo in parentesi graffe. Se po­si­zio­na­te una freccia ad un’estremità, essa segnala la posizione del pro­prie­ta­rio all’interno di un campione di elementi vincolati (con­strai­ne­dE­le­men­ts). La freccia mostra il percorso dalla prima posizione verso la seconda. Se più di due elementi hanno la re­stri­zio­ne, uti­liz­za­te l’icona della nota e associate ciascun elemento al vincolo.

Anche le linee ap­par­ten­go­no agli elementi che possono essere vincolati: se state mo­del­lan­do più di due linee dello stesso tipo, tra­sci­na­te la linea del Con­straint at­tra­ver­so tutte le linee che rap­pre­sen­ta­no gli elementi coinvolti.

Ste­reo­ti­pi

Gli ste­reo­ti­pi de­fi­ni­sco­no le esten­sio­ni delle me­ta­clas­si. Secondo la specifica UML ap­par­ten­go­no ai profili. Se uno ste­reo­ti­po descrive proprietà ag­giun­ti­ve di più me­ta­clas­si, può de­scri­ve­re solo un’istanza della me­ta­clas­se alla volta in fase di ese­cu­zio­ne. Tra le me­ta­clas­si lo ste­reo­ti­po assume un ruolo specifico, perché non può mai stare da solo. Modellate sempre uno ste­reo­ti­po in com­bi­na­zio­ne con il clas­si­fi­ca­to­re che lo amplia. Con­net­te­te la me­ta­clas­se allo ste­reo­ti­po mo­del­lan­do un’esten­sio­ne (Extension).

N.B.

A partire dall’UML 2.4 la specifica si definisce così: l’etichetta di uno ste­reo­ti­po si scrive all’inizio con una lettera maiuscola, come <<Type>>. Le altre etichette, come ad esempio le proprietà alle esten­sio­ni delle as­so­cia­zio­ni, si scrivono ge­ne­ral­men­te in minuscolo.

Si di­stin­guo­no due tipi di relazioni tra (meta)classi e ste­reo­ti­pi. L’esten­sio­ne richiesta (notazione: isRe­qui­red = true) definisce che uno ste­reo­ti­po si associa a ciascuna istanza della me­ta­clas­se nel diagramma delle classi. L’esten­sio­ne non ne­ces­sa­ria (notazione: isRe­qui­red = false) consente di associare li­be­ra­men­te le istanze della me­ta­clas­se a uno ste­reo­ti­po. Potete anche can­cel­la­re lo ste­reo­ti­po. Tuttavia, una par­ti­co­la­re istanza può essere associata ad un de­ter­mi­na­to ste­reo­ti­po solo una volta durante il runtime.

Se volete rimuovere uno ste­reo­ti­po, eliminate il profilo che lo definisce dalla sezione profili applicati (ap­plied­pro­fi­les) nel pacchetto so­vraor­di­na­to. In al­ter­na­ti­va, si elimina l’istanza che esso estende.

L’UML definisce alcuni ste­reo­ti­pi di classe (sei dei quali sono standard) che ampliano il vostro diagramma di classe UML. Anche se non stan­dar­diz­za­ti, spesso sono uti­liz­za­ti tre ste­reo­ti­pi che traducono il pattern “modello-pre­sen­ta­zio­ne-gestione” (Model-View-Con­trol­ler, ab­bre­via­to in MVC) in UML. I tre ste­reo­ti­pi non stan­dar­diz­za­ti sono:

  • L’entità (notazione: <<Entity>>): lo ste­reo­ti­po Entity definisce una classe o un oggetto. L’istanza cor­ri­spon­den­te rap­pre­sen­ta una raccolta di dati. Spesso si tratta di dati di sistema che devono essere ar­chi­via­ti per un lungo periodo di tempo. L’entità assume il ruolo di modello dal pattern MVC. L’UML conosce questo ste­reo­ti­po, ma lo assegna per im­po­sta­zio­ne pre­de­fi­ni­ta ai diagrammi dei com­po­nen­ti. La notazione usata più fre­quen­te­men­te non elenca le spe­ci­fi­che. In questo caso l’entità è indicata con un cerchio che poggia su una linea corta.
  • Il confine (notazione: <<Boundary>>): il confine è uno ste­reo­ti­po per una classe o un oggetto. Cor­ri­spon­de ap­pros­si­ma­ti­va­men­te all’elemento View nel pattern MVC. Il confine modella il limite del vostro sistema, ad esempio un’in­ter­fac­cia utente. Di solito è rap­pre­sen­ta­to come un cerchio, dal quale parte a sinistra una linea che incontra una linea verticale.
  • L’elemento di controllo (notazione: <<Control>>): l’elemento di controllo rap­pre­sen­ta gli stessi elementi del con­trol­ler nello schema MVC. Le classi o gli oggetti con questo ste­reo­ti­po modellano elementi che regolano il com­por­ta­men­to del sistema o i flussi di controllo. Nello standard UML lo ste­reo­ti­po <<focus>> assume compiti simili. Un’istanza di controllo si disegna come un cerchio con una punta della freccia aperta sulla linea.

Questi tre ste­reo­ti­pi si possono anche designare come una semplice classe. Nel ret­tan­go­lo annotate il nome dello ste­reo­ti­po cor­ri­spon­den­te. Prin­ci­pal­men­te i mo­del­li­sti usano queste forme nei diagrammi di sequenza. Se volete saperne di più sui diagrammi Entity-Boundary-Control, leggete il nostro articolo sui diagrammi di sequenza con UML.

Per i diagrammi di classe sono adatti i seguenti ste­reo­ti­pi stan­dar­diz­za­ti:

  • focus (<<Focus>>)
  • au­si­lia­rio (<<Auxiliary>>)
  • tipo (<<Type>>)
  • classe di im­ple­men­ta­zio­ne (<<Im­ple­men­ta­tion­Class>>)
  • me­ta­clas­se (<<Metaclass>>)
  • utility (<<Utility>>)

Focus

La classe focus definisce la logica aziendale di base o il flusso di controllo delle classi au­si­lia­rie. Esse sup­por­ta­no la classe focus che raccorda uno o più ausiliari. Definisce im­pli­ci­ta­men­te le classi di supporto am­met­ten­do una relazione di di­pen­den­za (vedi “la relazione diretta”). Se utilizza le classi di aiutanti, le definisce espli­ci­ta­men­te. Lo standard UML rac­co­man­da questo ste­reo­ti­po spe­cial­men­te per la fase di pro­get­ta­zio­ne, quando si mostrano i flussi di controllo tra i com­po­nen­ti o si imposta la logica di business.

Fatto

La logica aziendale, chiamata anche logica di ap­pli­ca­zio­ne, descrive la logica di un sistema che gestisce l’ese­cu­zio­ne di requisiti aziendali reali. È diversa dalla logica che determina l’ese­cu­zio­ne tecnica. Nella pro­gram­ma­zio­ne orientata agli oggetti, la logica aziendale ha prodotto il concetto dell’oggetto business, che modella i processi concreti e i valori reali in un sistema di in­for­ma­zio­ni.

Au­si­lia­rio

La classe helper (au­si­lia­rio) di solito funziona in com­bi­na­zio­ne con la classe focus. In genere supporta classi di im­por­tan­za critica per il sistema. A tale scopo esegue flussi di controllo secondari e definisce la logica sus­si­dia­ria. Se la classe helper supporta una classe focus, la de­fi­ni­zio­ne risulta esplicita. Uti­liz­za­te una relazione di di­pen­den­za per definire im­pli­ci­ta­men­te la classe sup­por­ta­ta.

Tipo

La classe di tipi definisce un’area per gli oggetti di business. Inoltre specifica gli operatori di questi oggetti. Lo ste­reo­ti­po del tipo può pre­sen­ta­re attributi e as­so­cia­zio­ni. Tuttavia non descrive l’ese­cu­zio­ne fisica dell’oggetto.

Classe di im­ple­men­ta­zio­ne

Alcuni linguaggi di pro­gram­ma­zio­ne (ad esempio Java o C++) con­sen­to­no solo una classe per ogni istanza. Con UML tuttavia potete associare un’istanza a più classi. La classe di ap­pli­ca­zio­ne crea un ponte tra questi due mondi. Questo ste­reo­ti­po limita la classe UML. Sta­bi­li­sce che un’istanza da lui di­pen­den­te possa rea­liz­za­re solo una classe. In compenso la classe di im­ple­men­ta­zio­ne può im­ple­men­ta­re diversi tipi. Per eseguire cor­ret­ta­men­te un clas­si­fi­ca­to­re ad essa associato, deve sod­di­sfa­re due con­di­zio­ni: deve fornire tutte le ope­ra­zio­ni del clas­si­fi­ca­to­re ed esse devono pre­sen­ta­re il com­por­ta­men­to definito per il clas­si­fi­ca­to­re. Gli attributi fisici e le as­so­cia­zio­ni non devono per forza cor­ri­spon­de­re.

Me­ta­clas­se

Poiché le forme della classe e della me­ta­clas­se sono in­di­stin­gui­bi­li, l’etichetta Metaclass indica che si tratta dello ste­reo­ti­po della me­ta­clas­se. Le istanze di questa classe sono esse stesse classi. Con questo ste­reo­ti­po lavorate perciò ad un livello più alto di astra­zio­ne.

Utility

La classe Utility non ha istanze, ma iden­ti­fi­ca sem­pli­ce­men­te una raccolta di attributi e ope­ra­zio­ni de­no­mi­na­ti, che sono sempre statici. Gli attributi statici non cambiano quando vengono ri­chia­ma­ti e le ope­ra­zio­ni statiche sono applicate a entità o tipi di entità. Se si utilizza la classe utility, dovete spe­ci­fi­ca­re i valori e le ope­ra­zio­ni ap­pro­pria­te sin dall’inizio, poiché non variano più. Questi elementi sono segnalati dalla sot­to­li­nea­tu­ra.

N.B.

L’UML specifica ulteriori ste­reo­ti­pi pre­de­fi­ni­ti per altri tipi di diagramma, le cui aree di ap­pli­ca­zio­ne e notazione si possono trovare nelle spe­ci­fi­che dell’UML 2.5.1, capitolo 22: profili standard, tabella 22.1, pagina 680.

In­ter­fac­ce

Le in­ter­fac­ce sono clas­si­fi­ca­to­ri. Nella loro notazione sono simili alle classi. A dif­fe­ren­za della classe, tuttavia, sono di­chia­ra­zio­ni, cioè di­chia­ra­no molte delle funzioni e degli obblighi pubblici lo­gi­ca­men­te coerenti. Per questo usano un contratto. Se un’istanza esegue l’in­ter­fac­cia, deve sod­di­sfa­re questo contratto. In quanto di­chia­ra­zio­ne, l’in­ter­fac­cia stessa non forma istanze.

A questo punto si situa la classe, poiché produce istanze. La sua istanza utilizza spe­ci­fi­che dell’in­ter­fac­cia e per questo deve ri­spet­ta­re il contratto dell’in­ter­fac­cia. In cambio utilizza l’in­ter­fac­cia come scenario pubblico. Inoltre un clas­si­fi­ca­to­re può uti­liz­za­re più in­ter­fac­ce, mentre un’in­ter­fac­cia può servire anche più clas­si­fi­ca­to­ri. Nel diagramma delle classi UML, le notazioni di in­ter­fac­cia e classe sono simili: un ret­tan­go­lo, op­zio­nal­men­te suddiviso in tre aree at­tra­ver­so delle linee.

Per di­mo­stra­re che una classe utilizza un’in­ter­fac­cia, usiamo la notazione In­ter­fa­ce­Rea­li­za­tion (nota dai clas­si­fi­ca­to­ri del com­por­ta­men­to). Essa rap­pre­sen­ta un’in­ter­fac­cia già fornita (Provided Interface), cioè un’in­ter­fac­cia che esegue di­ret­ta­men­te un’istanza. Quest’ultima si applica anche alle classi di livello superiore come i com­po­nen­ti. Se la classe ha una porta pubblica, questa fornisce l’in­ter­fac­cia. L’In­ter­fa­ce­Rea­li­za­tion è rap­pre­sen­ta­ta da un cerchio collegato al clas­si­fi­ca­to­re tramite una linea.

Ci sono anche in­ter­fac­ce richieste (Required In­ter­fa­ces), che vi­sua­liz­za­no una relazione di di­pen­den­za (vedi “Relazioni”). Un elemento richiede un altro elemento per eseguire l’intera esten­sio­ne delle proprie funzioni. In questo caso un clas­si­fi­ca­to­re (o una delle sue istanze) ha bisogno di un’in­ter­fac­cia. L’In­ter­fa­ceU­sa­ge (utilizzo dell’in­ter­fac­cia) specifica i requisiti per l’in­ter­fac­cia. Per questo una linea continua collega il clas­si­fi­ca­to­re a un se­mi­cer­chio aperto che sim­bo­leg­gia l’in­ter­fac­cia. Annotate il nome dell’in­ter­fac­cia in entrambi i rap­pre­sen­tan­ti sotto il (semi)cerchio.

Se una classe eredita un’in­ter­fac­cia per una classe su­bor­di­na­ta, modellate il col­le­ga­men­to dell’in­ter­fac­cia alla classe o all’istanza su­bor­di­na­ta. Mostrate la relazione ge­rar­chi­ca con il cir­con­fles­so (^), ad esempio come ^in­ter­fac­cia 1.

Se uti­liz­za­te la notazione con le in­ter­fac­ce ret­tan­go­la­ri, tracciate una linea tra i due nodi. Nel diagramma delle classi le linee modellano le relazioni tra classi, istanze o com­po­nen­ti. L’UML prescrive linee o frecce diverse per funzioni e relazioni diverse. In questo caso collegate una classe con l’in­ter­fac­cia richiesta tramite una freccia trat­teg­gia­ta con una punta aperta. Date alla freccia l’etichetta <<use>>. Un’in­ter­fac­cia pronta si connette a una classe tramite una freccia trat­teg­gia­ta con una punta chiusa non piena. La freccia punta sempre nella direzione dell’in­ter­fac­cia.

Tipi di dati

I tipi di dati combinano un insieme di oggetti con le loro ope­ra­zio­ni. Uti­liz­za­no in­ter­val­li di valori concreti e li combinano con le loro ope­ra­zio­ni spe­ci­fi­che. Gli oggetti possono avere diversi tipi. I loro valori numerici vanno da tipi primitivi a enu­me­ra­zio­ni più lunghe.

I tipi di dati sono clas­si­fi­ca­to­ri. Le vostre istanze vi iden­ti­fi­che­ran­no solo in base al loro valore. I tipi di dati vi­sua­liz­za­no i tipi di valore, i tipi primitivi e i tipi strut­tu­ra­ti nel diagramma di classe UML. Se si copia un’istanza del tipo di dati o se si modellano due istanze dello stesso tipo di dati con lo stesso valore, vengono con­si­de­ra­te le stesse istanze.

Se il tipo di dati ha attributi, l’UML lo assegna come un tipo di dati strut­tu­ra­to. Le sue istanze sono con­si­de­ra­te uguali solo se la loro struttura e i valori dei loro attributi sono gli stessi.

I tipi primitivi non hanno una struttura su­bor­di­na­ta ma rap­pre­sen­ta­no valori atomici di dati. Vengono applicati nel diagramma di classi anche in caso di re­stri­zio­ni. Molti di questi tipi hanno una semantica complessa al di fuori delle spe­ci­fi­che UML. Nell’UML, tuttavia, non hanno alcuna identità, motivo per cui sono in­di­stin­gui­bi­li nel caso dello stesso valore. Questi sono alcuni tipi primitivi nell’UML:

  • Boolean (variabili booleane)
  • Integer (numero intero)
  • Un­li­mi­ted­Na­tu­ral (il­li­mi­ta­to, numero naturale)
  • Real (numeri reali)
  • String (catena di caratteri)

I tipi primitivi si annotano con l’etichetta <<primitive>> sopra il nome del ri­spet­ti­vo tipo di dati.

L’Enu­me­ra­tion (enu­me­ra­zio­ne) è un tipo di dati. Esse rap­pre­sen­ta­no il valore dell’enu­me­ra­zio­ne come un co­sid­det­to simbolo di lettera di enu­me­ra­zio­ne. Come si vede nella figura sopra, si tratta sem­pli­ce­men­te di un nome che sim­bo­leg­gia un valore specifico, che potete scegliere voi. Ad esempio nell’elenco “tipi di rose”, il nome “rosa Bourbon” sta per il numero di rose Bourbon che un negozio di fiori ha nel proprio as­sor­ti­men­to. Nel diagramma di classe indicate questo clas­si­fi­ca­to­re con il simbolo per la classe, un ret­tan­go­lo. Il nome così come l’etichetta <<enu­me­ra­tion>> si in­se­ri­sco­no nell’in­te­sta­zio­ne di­vi­den­do­la dal corpo del testo con una linea oriz­zon­ta­le.

Come con altre classi, l’enu­me­ra­zio­ne riserva i reparti superiori per attributi e ope­ra­zio­ni. Se questi rimangono vuoti, lasciate entrambe le sezioni fuori dal diagramma. Nella parte inferiore inserite il simbolo della lettera di enu­me­ra­zio­ne. Ad esempio l’enu­me­ra­zio­ne dei tipi di rose in un negozio di fiori consiste nell’in­te­sta­zio­ne “tipi di rosa” e il corpo del testo con una lista dei singoli tipi: rosa indica fragrans, rosa Noisette, rosa gallica, rosa Bourbon, rosa majalis.

Relazioni

I diagrammi delle classi rap­pre­sen­ta­no le relazioni tra gli elementi del sistema: l’os­ser­va­to­re dovrebbe quindi vedere di quali com­po­nen­ti necessita il sistema e come si in­fluen­za­no a vicenda. La relazione tra gli elementi UML è una classe astratta. Rap­pre­sen­ta l’idea di una relazione tra i com­po­nen­ti del sistema. Pertanto questo elemento non ha una notazione separata. Le sue ca­rat­te­ri­sti­che, tuttavia, hanno dettagli specifici che li con­trad­di­stin­guo­no.

Le relazioni in UML sono intese come linee che collegano i nodi. In questo modo si modellano in generale le relazioni con una linea o con delle linee mo­di­fi­ca­te, come ad esempio una freccia.

La de­fi­ni­zio­ne UML per le sot­to­clas­si e le istanze di relazione in alcuni casi è cambiata dra­sti­ca­men­te nel passaggio da UML 1 a UML 2. Ad esempio c’erano ori­gi­na­ria­men­te relazioni se­man­ti­che, strut­tu­ra­li e di­re­zio­na­li. Tre relazioni concrete (as­so­cia­zio­ne, vincolo e di­pen­den­za) sono state assegnate alle relazioni se­man­ti­che. Nell’UML 2 i vincoli sono ora elementi com­po­ni­bi­li, le as­so­cia­zio­ni de­fi­ni­sco­no alcune fonti come una relazione strut­tu­ra­le e semantica. La di­pen­den­za è ora in relazioni di­re­zio­na­li.

Resta da vedere come cambierà lo standard nelle versioni future. Di seguito con­ti­nuia­mo a spiegare i diagrammi delle classi nell’UML 2.5. Pertanto la relazione me­ta­clas­se ha due sot­to­clas­si: la relazione diretta e l’as­so­cia­zio­ne.

L’as­so­cia­zio­ne

L’as­so­cia­zio­ne è una relazione che collega le tuple. Nell’in­for­ma­ti­ca, le tuple sono raccolte di valori ordinati. Anziché la quantità, giocano un ruolo la con­nes­sio­ne logica e l’ordine. Pertanto non è sbagliato assegnare all’as­so­cia­zio­ne anche un com­po­nen­te strut­tu­ra­le, oltre alla de­scri­zio­ne ufficiale come relazione semantica. L’as­so­cia­zio­ne è un col­le­ga­men­to tra i clas­si­fi­ca­to­ri. Gli elementi in questa relazione hanno una pros­si­mi­tà logica o fisica. A seconda del numero di membri, l’as­so­cia­zio­ne è chiamata binaria (due istanze), ternaria (tre istanze) o n-aria (a partire da quattro istanze).

Le estremità dell’as­so­cia­zio­ne con­net­to­no nei diagrammi di classe UML le as­so­cia­zio­ni con le istanze. L’estremità dell’as­so­cia­zio­ne ha un nome finale che esprime il ruolo dell’istanza nella relazione. Sup­po­nia­mo che uno studente realizzi diverse versioni di un cor­to­me­trag­gio per un seminario di cinema. Quindi il ruolo dello studente di cinema nel film sarebbe quello di “artefice”. Il ruolo del film sarebbe quello di “lavoro per il seminario”. Scrivete il nome sotto la linea di col­le­ga­men­to, in ogni caso presso il simbolo dell’istanza che lo descrive. L’estremità ap­par­tie­ne all’as­so­cia­zio­ne stessa o al clas­si­fi­ca­to­re dell’estremità. In caso di più di due estremità, il ruolo ap­par­tie­ne all’as­so­cia­zio­ne.

La freccia accanto ai nomi di as­so­cia­zio­ne nel diagramma di classe sopra mostra la direzione della relazione. Nel diagramma sotto il punto sull’istanza “Film” indica che l’estremità dell’as­so­cia­zio­ne è “lavoro per il seminario” dell’istanza “studente di cinema”. Poiché il termine “artefice” dell’as­so­cia­zio­ne non ha alcun segno, ap­par­tie­ne all’as­so­cia­zio­ne stessa: la mol­te­pli­ci­tà “1” indica che esiste esat­ta­men­te un’istanza “studente di cinema”. L’istanza “Film” ha almeno tre im­po­sta­zio­ni.

La na­vi­ga­bi­li­tà è una proprietà finale (End Property). Indica se un’istanza a questa estremità dell’as­so­cia­zio­ne è rag­giun­gi­bi­le dall’altra estremità dell’as­so­cia­zio­ne. Se l’istanza B è rag­giun­gi­bi­le per l’istanza A, tracciate una punta della freccia aperta sulla linea dell’as­so­cia­zio­ne nella direzione dell’istanza B di­ret­ta­men­te sul simbolo dell’istanza B. Se l’istanza D non è rag­giun­gi­bi­le per l’istanza C, tracciate una X sulla linea dell’istanza D. Se non de­si­de­ra­te nessun tipo di na­vi­ga­bi­li­tà, non disegnate notazioni separate.

Ci sono due varianti dell’as­so­cia­zio­ne: il col­le­ga­men­to (link) e l’ag­gre­ga­zio­ne.

  • Il col­le­ga­men­to (link) è un’istanza dell’as­so­cia­zio­ne. Ha almeno due estremità, ognuna con una mol­te­pli­ci­tà. Questo valore deve essere un’istanza del tipo di dati delle estremità. Nella nostra immagine di esempio sopra uno studente di cinema filma tre film durante i propri studi. Il valore per l’istanza “studente” è “1”. Il valore per l’istanza “film” è “3”. Si modella la con­nes­sio­ne come linee continue tra par­te­ci­pan­ti re­la­zio­na­li. A dif­fe­ren­za dell’as­so­cia­zio­ne, il link collega le istanze e non i clas­si­fi­ca­to­ri.
  • L’ag­gre­ga­zio­ne è un’as­so­cia­zio­ne binaria, perciò ha sempre due par­te­ci­pan­ti. A dif­fe­ren­za del link, non crea relazioni sullo stesso livello, ma mostra le relazioni tra una parte e il tutto. Rap­pre­sen­ta­te l’ag­gre­ga­zio­ne con una proprietà all’estremità dell’as­so­cia­zio­ne: modellate un rombo sull’istanza che rap­pre­sen­ta il tutto.

Un tipo di ag­gre­ga­zio­ne è l’ag­gre­ga­zio­ne composita (Composite Ag­gre­ga­tion), che descrive la relazione tra una com­po­si­zio­ne di parti e una singola parte di esse. Se il sistema cancella il tutto (la com­po­si­zio­ne), distrugge anche la singola parte. Ad esempio se un albero rap­pre­sen­ta il tutto, allora la foglia è una parte di esso. Se l’albero è vittima di un incendio boschivo, il fuoco distrugge anche le foglie. Se si vuole creare per esempio un diagramma di classe e rap­pre­sen­ta­re tale relazione, tracciate una linea continua tra le istanze. Disegnate un rombo colorato di nero dalla parte della com­po­si­zio­ne (in questo caso, l’istanza “albero”). Questo lato è anche chiamato estremità dell’ag­gre­ga­zio­ne.

Un secondo tipo di ag­gre­ga­zio­ne è l’ag­gre­ga­zio­ne condivisa (o sem­pli­ce­men­te ab­bre­via­ta in ag­gre­ga­zio­ne). Questa relazione asim­me­tri­ca esiste tra una proprietà e un’istanza che rap­pre­sen­ta un insieme di istanze. La con­nes­sio­ne dovrebbe essere diretta. Al­tri­men­ti un’istanza di com­po­si­zio­ne potrebbe essere in­ter­pre­ta­ta come parte di se stessa. Ciò può accadere se modellate la relazione di di­pen­den­za in modo ciclico. La proprietà condivisa può ap­par­te­ne­re a più com­po­si­zio­ni. Allo stesso tempo la loro istanza può esistere in­di­pen­den­te­men­te dalla com­po­si­zio­ne. Se il sistema dovesse in questo caso eliminare una com­po­si­zio­ne (o tutte), l’istanza se­con­da­ria può con­ti­nua­re ad esistere. Pertanto questa relazione è con­si­de­ra­ta debole rispetto alla com­po­si­zio­ne.

Inoltre l’as­so­cia­zio­ne offre un’altra ca­rat­te­ri­sti­ca speciale: la classe di as­so­cia­zio­ne, che è allo stesso tempo classe e relazione. Ciò consente di assegnare attributi alla classe di as­so­cia­zio­ne nel diagramma di classi.

La relazione diretta

La relazione diretta è una classe astratta. Descrive le relazioni tra un’origine e una de­sti­na­zio­ne. Entrambe le estremità della relazione possono avere più elementi. Come l’as­so­cia­zio­ne, anche la relazione diretta non ha una notazione fissa. Le loro sot­to­clas­si co­sti­tui­sco­no forme spe­ci­fi­che che si basano su una linea dall’origine alla de­sti­na­zio­ne. Le seguenti istanze de­fi­ni­sco­no una relazione diretta:

  • ge­ne­ra­liz­za­zio­ne (Ge­ne­ra­li­za­tion)
  • di­pen­den­za (De­pen­den­cy)
  • vincolo del modello (Template Binding)
  • in­clu­sio­ne (Include): fa parte della notazione per i diagrammi dei casi d‘uso
  • esten­sio­ne (Extend): fa parte della notazione per i diagrammi dei casi d‘uso

La ge­ne­ra­liz­za­zio­ne è una relazione binaria tra le classi. È orientato da una sot­to­clas­se a una su­per­clas­se, cioè da una classe specifica a una classe più generale. La classe de­ter­mi­na­ta (ad esempio dalia) ha la ge­ne­ra­liz­za­zio­ne. Una freccia con la punta chiusa ma non riempita punta da questa origine alla de­sti­na­zio­ne, che è la classe generale (ad esempio la famiglia delle aste­ra­ceae).

La sot­to­clas­se specifica la classe generale. Ciò significa anche che la sot­to­clas­se condivide alcune delle sue proprietà, sia di contenuto che di struttura, con la su­per­clas­se, di solito gli elementi di base. Questa cir­co­stan­za viene chiamata ere­di­ta­rie­tà. Ad esempio la classe “dalia” dell’esempio condivide l’in­fio­re­scen­za a forma di coppa con la su­per­clas­se della famiglia delle Aste­ra­ceae. Una ca­rat­te­ri­sti­ca specifica del genere “dalia” sono le sue otto coppie di cromosomi (le piante di solito hanno soltanto due coppie di cromosomi). Le diverse specie di dalia hanno ca­rat­te­ri­sti­che che con­fe­ri­sco­no aspetti diversi.

Fatto

Nel lin­guag­gio col­lo­quia­le, le ge­ne­ra­liz­za­zio­ni sono anche indicate dalla relazione “è un…”. Per esempio si può dire “una dalia è un’asteracea”.

Im­pli­ci­ta­men­te l’UML consente l’ere­di­ta­rie­tà multipla. In questo modo modellate diverse sot­to­clas­si che hanno sia su­per­clas­si comuni che diverse. In al­ter­na­ti­va ci sono diversi livelli di ge­ne­ra­liz­za­zio­ne. Potete rap­pre­sen­ta­re queste relazioni con la notazione a freccia o ni­di­fi­ca­re le sot­to­clas­si nelle loro su­per­clas­si. Per fare ciò, modellate tutte le sot­to­clas­si nel corpo della su­per­clas­se.

Il set di ge­ne­ra­liz­za­zio­ne (Ge­ne­ra­li­za­tion Set) vi aiuta a tenere traccia del diagramma delle classi. Il set è un elemento im­pac­chet­ta­bi­le. I pacchetti in UML sono con­te­ni­to­ri per elementi de­no­mi­na­ti che hanno so­mi­glian­ze se­man­ti­che e possono cambiare insieme. Un pacchetto è uno spazio dei nomi e non una classe. È possibile associare il set di ge­ne­ra­liz­za­zio­ne a un clas­si­fi­ca­to­re. Ciò prende il nome di powertype.

Modellate il powertype come stringa sulla linea di ge­ne­ra­liz­za­zio­ne in questa forma: {[isCo­ve­ring Property] , [isDi­sjoint Property]} : [nome del tipo powertype]. La proprietà isCo­ve­ring descrive se il set è completo. I valori sono complete (completi) o in­com­ple­te (in­com­ple­ti). La proprietà isDi­sjoint dice ai clas­si­fi­ca­to­ri di con­di­vi­de­re istanze comuni. I valori sono o disjoint (non so­vrap­po­sti) o over­lap­ping (quando si verifica una so­vrap­po­si­zio­ne).

N.B.

La stan­dar­diz­za­zio­ne UML 2.5 fornisce poche in­for­ma­zio­ni sull’ere­di­ta­rie­tà. Tuttavia è possibile fare ri­fe­ri­men­to alle versioni pre­ce­den­ti. L’UML 2 afferma ge­ne­ral­men­te che le classi spe­cia­liz­za­te assumono le ca­rat­te­ri­sti­che e i limiti delle loro su­per­clas­si. L’UML 1.4 specifica che gli attributi di­chia­ra­ti so­vra­scri­vo­no gli attributi ereditati in una sot­to­clas­se.

La di­pen­den­za (De­pen­den­cy) è una relazione tra “fornitore” e “cliente” (supplier-client re­la­tion­ship). Questa relazione diretta descrive che un elemento dipende da un altro elemento. Si può trattare anche di molti elementi. Il cliente ha bisogno di un altro elemento per una più corretta spe­ci­fi­ca­zio­ne o per eseguire il proprio compito. Senza il fornitore al cliente manca la com­po­nen­te strut­tu­ra­le o semantica. Pertanto le modifiche al fornitore po­treb­be­ro influire sui clienti. Nell’UML 2.5, la semantica influenza sempre l’elemento de­no­mi­na­to, ma non le sue istanze. Le di­pen­den­ze hanno un ruolo non solo nel diagramma delle classi UML, ma anche in altri diagrammi strut­tu­ra­li come il diagramma dei com­po­nen­ti o il diagramma di di­stri­bu­zio­ne.

La di­pen­den­za ha tre sot­to­ca­te­go­rie:

- astra­zio­ne (Ab­strac­tion)

- di­stri­bu­zio­ne (De­ploy­ment)

- uso (Usage)

L’astra­zio­ne collega elementi a diversi livelli. In al­ter­na­ti­va, mostra pro­spet­ti­ve diverse. Gli elementi de­no­mi­na­ti in questa relazione rap­pre­sen­ta­no lo stesso concetto. Secondo lo standard UML l’elemento più specifico è il client, che dipende dal provider, l’elemento più astratto. Pertanto l’estremità della freccia dovrebbe ap­par­te­ne­re alla sot­to­clas­se e la punta alla su­per­clas­se. L’UML consente anche una notazione inversa. Se ritenete che abbia più senso che l’elemento astratto dipenda dalla sua sot­to­clas­se, disegnate la punta della freccia sull’elemento più specifico.

L’astra­zio­ne ha due sot­to­clas­si: rea­liz­za­zio­ne (Rea­li­za­tion) e ma­ni­fe­sta­zio­ne (Ma­ni­fe­sta­tion).

La rea­liz­za­zio­ne è già stata in­tro­dot­ta nell’ambito delle in­ter­fac­ce. La rea­liz­za­zio­ne dell’in­ter­fac­cia (In­ter­fa­ce­Rea­li­za­tion) è una specifica della rea­liz­za­zio­ne. Descrive una relazione tra clas­si­fi­ca­to­re e in­ter­fac­cia. Il clas­si­fi­ca­to­re utilizza l’in­ter­fac­cia per fornire un servizio alla propria clientela. L’in­ter­fac­cia esegue questo servizio. Per fare ciò, il clas­si­fi­ca­to­re deve sod­di­sfa­re il contratto stabilito dall’in­ter­fac­cia. La notazione per le in­ter­fac­ce fornite e richieste è di­spo­ni­bi­le nella sezione “In­ter­fac­ce”.

La so­sti­tu­zio­ne (Sub­sti­tu­tion) è un’altra relazione che specifica la rea­liz­za­zio­ne. Consiste in un clas­si­fi­ca­to­re so­sti­tu­ti­vo e un clas­si­fi­ca­to­re del contratto. Il clas­si­fi­ca­to­re so­sti­tu­ti­vo soddisfa il contratto dell’altro clas­si­fi­ca­to­re. Durante il runtime le istanze del clas­si­fi­ca­to­re di so­sti­tu­zio­ne possono po­ten­zial­men­te so­sti­tui­re le istanze del clas­si­fi­ca­to­re del contratto. Con­tra­ria­men­te alla spe­cia­liz­za­zio­ne, non vi è alcuna so­mi­glian­za strut­tu­ra­le tra gli elementi della so­sti­tu­zio­ne. Con­tras­se­gna­te la so­sti­tu­zio­ne come linea di di­pen­den­za (freccia trat­teg­gia­ta con punta aperta) nel diagramma delle classi e ag­giun­ge­te la parola chiave <<sub­sti­tu­te>> sulla linea.

La ma­ni­fe­sta­zio­ne descrive una relazione tra un artefatto e uno o più elementi del modello. L’UML definisce gli artefatti come clas­si­fi­ca­to­ri. Sim­bo­liz­za­no istanze concrete e fisiche come cartelle di archivio. La ma­ni­fe­sta­zio­ne rap­pre­sen­ta un artefatto che esegue di­ret­ta­men­te un elemento connesso. D’altra parte può sim­bo­leg­gia­re che gli elementi sono coinvolti nella creazione dell’artefatto. La ma­ni­fe­sta­zio­ne è un elemento del diagramma di di­stri­bu­zio­ne ed è men­zio­na­ta qui solo per motivi di com­ple­tez­za. Richiede la stessa notazione delle so­sti­tu­zio­ni e la parola chiave è <<manifest>>.

L’astra­zio­ne definisce anche alcuni ste­reo­ti­pi, i quali ap­par­ten­go­no ai profili UML. Se una me­ta­clas­se esistente per un progetto deve essere estesa, si definisce per essa un profilo. La classe ste­reo­ti­po si utilizza sempre insieme alla me­ta­clas­se, poiché un profilo cambia solo uno esistente o aggiunge una ter­mi­no­lo­gia. A partire da UML 2.4.1., l’UML con­tras­se­gna gli ste­reo­ti­pi all’inizio in maiuscolo. Gli ste­reo­ti­pi standard per un’astra­zio­ne sono:

  • Derivare (<<Derive>>): un elemento è derivato da un altro elemento. Per lo più sono dello stesso tipo.
  • Affinare (<<Refine>>): un elemento fornisce in­for­ma­zio­ni più det­ta­glia­te per una classe che esiste anche nell’altro elemento. Gli elementi sono a diversi livelli di astra­zio­ne. Ad esempio un modello a livello esecutivo per­fe­zio­na la classe “impiegato” relativa alla classe “impiegato” a livello di pro­get­ta­zio­ne.
  • Tracciare (<<Trace>>): diversi modelli esprimono aspetti diversi di un sistema. Per tracciare elementi che rap­pre­sen­ta­no lo stesso concetto in diversi modelli uti­liz­za­te mapping o tracing. Con Trace potete tenere traccia delle modifiche agli elementi e alle spe­ci­fi­che.
N.B.

Con l’aiuto di questi ste­reo­ti­pi di astra­zio­ne mappate la relazione tra client e provider. Questo processo può essere bi­la­te­ra­le o uni­la­te­ra­le e formale o informale. Client e provider sono in diagrammi diversi, ad esempio in un diagramma di classe e in un diagramma dei casi d’uso.

La di­stri­bu­zio­ne mostra la relazione tra un artefatto e la sua missione. Nel diagramma UML, la linea di di­stri­bu­zio­ne di uno o più artefatti punta alla missione (De­ploy­ment Target). La parola chiave per la linea è <<deploy>>. Potete anche applicare questa di­pen­den­za a livello delle istanze. In al­ter­na­ti­va modellate l’artefatto nel corpo del fine della missione. Per farlo potete disegnare l’artefatto come simbolo o elencare gli artefatti forniti. Questa di­pen­den­za fa parte della notazione del diagramma di di­stri­bu­zio­ne.

L’uso descrive una relazione in cui il client ha bisogno del provider per com­ple­ta­re le sue attività o eseguire le ope­ra­zio­ni. L’uso im­ple­men­ta quindi la di­pen­den­za generale come un’istanza. Questa di­pen­den­za forma alcune relazioni concrete:

  • Uti­liz­za­re (<<use>>): un elemento utilizza un altro elemento, ma la relazione esatta e il beneficio preciso non sono spe­ci­fi­ca­ti in dettaglio.
  • Creare (<<create>>): un clas­si­fi­ca­to­re del client o uno dei suoi elementi strut­tu­ra­li o com­por­ta­men­ta­li crea una o più istanze del clas­si­fi­ca­to­re del provider.
  • Ri­chia­ma­re (<<call>>): un’ope­ra­zio­ne richiama un’altra ope­ra­zio­ne. La de­sti­na­zio­ne può essere qualsiasi ope­ra­zio­ne intorno all’ope­ra­zio­ne di origine, inclusi i clas­si­fi­ca­to­ri so­vraor­di­na­ti.
  • Inviare (<<send>>): un’ope­ra­zio­ne è l’origine, ovvero il client. Il suo obiettivo è un segnale. La di­pen­den­za fa quindi in modo che l’ope­ra­zio­ne invii il segnale di de­sti­na­zio­ne.
  • In­ter­fac­cia richiesta (Required Interface ­­­-----C): con­tra­ria­men­te all’in­ter­fac­cia fornita, l’in­ter­fac­cia richiesta non esiste nel clas­si­fi­ca­to­re. Determina i servizi di cui necessita un clas­si­fi­ca­to­re per il proprio client. La di­pen­den­za sussiste tra clas­si­fi­ca­to­re e in­ter­fac­cia. Nella sezione “In­ter­fac­ce” troverete maggiori in­for­ma­zio­ni sull’argomento.

Il vincolo del modello (Template Binding) è l’ultima relazione diretta uti­liz­za­ta nel diagramma delle classi. Quando create un diagramma di classe, a volte è utile creare modelli per le classi. I modelli nelle classi con­si­sto­no di parametri del modello, cioè parametri che ap­par­ten­go­no alla firma del modello. La firma a propria volta determina l’insieme ordinato di parametri all’interno del modello. Se modellate classi che non hanno bisogno di avere proprietà in­di­vi­dua­li, la­vo­re­re­te in modo più ef­fi­cien­te se uti­liz­za­te i modelli. Ma se una classe dovesse ricevere parametri fissi, uti­liz­za­te il Template Binding. La relazione sussiste tra un elemento associato e la firma del modello in un modello di de­sti­na­zio­ne.

L’elemento associato è in grado di creare modelli, il che significa che può diventare un modello o si può legare ad altri modelli. L’oggetto è legato perché ha una con­nes­sio­ne a un modello. Questa con­nes­sio­ne descrive la struttura dell’elemento so­sti­tuen­do i parametri del modello formale dal modello con parametri di valore.

In sintesi

Il diagramma di classe è uno dei diagrammi UML più popolari perché presenta strutture di sistema in modo det­ta­glia­to e chiaro. Come diagramma strut­tu­ra­le mostra il sistema in stato statico. Ciò offre agli spet­ta­to­ri una pa­no­ra­mi­ca degli elementi necessari in un sistema. Inoltre, rap­pre­sen­ta­no relazioni tra i blocchi co­sti­tu­ti­vi dell’ar­chi­tet­tu­ra di sistema: dagli oggetti reali alle classi astratte con profili espan­di­bi­li, è possibile uti­liz­za­re il diagramma di classe UML per modellare in­di­pen­den­te­men­te dal lin­guag­gio di pro­gram­ma­zio­ne. In tal modo pro­muo­ve­te la com­pren­sio­ne tra i di­par­ti­men­ti nella rea­liz­za­zio­ne di un progetto.

Vai al menu prin­ci­pa­le