Dispensa a.a. 2013/2014 - SisInfLab

Transcript

Dispensa a.a. 2013/2014 - SisInfLab
Ingegneria del software
Politecnico di Bari
POLITECNICO DI BARI
CORSO DI INGEGNERIA DEL SOFTWARE
Prof.ssa Marina Mongiello
A. A 2013/2014
1
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
CORSO DI INGEGNERIA DEL SOFTWARE
Prof.ssa Marina Mongiello
Email: [email protected]
Telefono: 0805963524
Pagina Web: sisinflab.poliba.it/mongiello
Orario di ricevimento: Giovedì mattina 10.00-11.00 II piano del DEI.
Ai fini del corso è necessario svolgere un tema d’anno il cui intento è quello di essere impegnati
costantemente con ciò che si fa in aula. Questo tema d’anno dovrà essere consegnato l’ultimo giorno di
lezione e verrà svolto in gruppo (max 3 persone).
IL TEMA D’ANNO NON INFLUIRA’ IN ALCUN MODO SULLA VOTAZIONE.
Per quanto concerne l’esame, esso è strutturato in :

Una prova scritta che prevede un esercizio di progettazione, uno di
programmazione(linguaggio C) e una domanda di teoria.
I testi di riferimento sono:

Sommerville “Ingegneria del software”

Pressman “Ingegneria del software”
Di volta in volta verranno indicati capitoli e libri specifici per ogni argomento.
2
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
INTRODUZIONE AL CORSO
Il corso di Ingegneria del software si occupa di capire come si arriva al codice. Viene dedicato un intero
corso a ciò poiché si deve entrare nell’ottica di sistemi software che non sono più piccoli programmini, ma
sistemi di grosse dimensioni che prevedono e necessitano di uno studio preliminare. Oltre a ciò però, il
corso si occuperà anche di un approfondita fase di analisi dei costi, analisi del mercato, aspetti temporali,
competenze (team) ecc.. Questo viene fatto perché bisogna avere un quadro completo di tutto ciò che
compone un sistema software.
ARGOMENTI DEL CORSO:

PROCESSO SOFTWARE: in informatica il termine processo ha una sua precisa
connotazione,esso è un’entità dinamica. Il programma è formato da una serie di
esecuzioni,infatti quando si manda in esecuzione il programma, istante per istante, si
verranno a creare varie configurazioni. La serie di queste configurazioni è il processo, per cui
possiamo dire che il processo è il programma in esecuzione.
Il processo software è la dinamica secondo cui le varie fasi che concorrono alla realizzazione di un
sistema software vengono articolate.
Le fasi possono essere articolate secondo vari modelli:

Modello a cascata secondo cui le fasi sono strettamente sequenziali e propedeutiche
(Se non finisce la prima fase non può partire la seconda). Questo modello ha però subito
dimostrato dei limiti e per questo sono stati sviluppati modelli più dinamici.

Sviluppo agile secondo cui il codice andava scritto senza alcuna documentazione, in
modo da essere più snello. Ma anche ciò dimostrò di avere dei limiti perché poteva andare
bene per piccoli programmi.

Modello iterativo;

Modello incrementale.
Ma cosa è un modello?
Un modello è un’astrazione di una realtà, uno schema. Tutto ciò che noi faremo sarà espresso in
termini di modelli.

PROGETTO SOFTWARE: inteso come gestione del progetto e non stesura. Si occuperà
quindi dello studio delle risorse, della tempistica ecc ecc e per tutto l’arco temporale di
realizzazione del progetto si controllerà se ci si sta attenendo alle previsione fatte.

FASI DEL PROCESSO SOFTWARE:

ANALISI DEL DOMINIO: durante questa fase si analizzano e si creano modelli di quel
dominio per sapere cosa il sistema deve essere in grado di fare. Dall’analisi del dominio si
tirano fuori i requisiti. Questi ultimi si possono anche negoziare col cliente. Cosa sono i
requisiti? Sono funzionalità, ma anche altre richieste. Perciò si possono distinguere due tipi di
requisiti, i requisiti funzionali e i requisiti non funzionali. Alla fine di tutto ciò si potrà
estrapolare una modellazione che verrà espressa nel linguaggio che si preferisce. Si utilizzano
3
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
però, linguaggi standardizzati, ossia che utilizzano un certo protocollo. Universalmente è
riconosciuto lo standard UML (Unified Modeling Language).
Conclusa la fase di analisi si prosegue con:

PROGETTAZIONE: In questa fase si sceglie che modello utilizzare, come strutturare il
sistema e in particolare si progetta ogni singolo componente.

IMPLEMENTAZIONE: alla fine di questa fase si ha il programma.

TEST: con il test si può dire se il sistema è funzionante o meno.
Ma sulla base di cosa posso stabilire se funziona o meno? Quanto più è ampio il range di dati su cui
vado a fare il test tanto migliore sarà la probabilità che il programma sia corretto.
LA CERTEZZA NON SI POTRA’ MAI AVERE! Non si potrà mai stabilire al 100% la funzionalità del
sistema semplicemente perché i dati che posso inserire sono infiniti. E’ stato anche sviluppato un
teorema che afferma e dimostra che, il fatto che il programma sia corretto, non è decidibile in
maniera algoritmica.
Dato questo vincolo, quello che si fa con il test è andare a controllare le situazioni di errore previste
durante la fase di analisi.
Alla fine verrà valutata la qualità del sistema.

QUALITA’ DEL SISTEMA: come si stabilisce?
Il programma per essere di qualità deve rispondere alle funzionalità richieste ma anche ai
requisiti non funzionali, i quali a volte possono essere in contrasto tra loro.
Si definiscono delle METRICHE DI PRODOTTO grazie alle quali si danno delle misure alla
manutenibilità e ai principi che compongono essa.

VERIFICA E VALIDAZIONE: se il sistema che si vuole creare è un software che controlla
il traffico aereo e lo si vuole testare, ovviamente non avrebbe senso far partire gli aerei e
accorgersi dopo che c’è qualche errore. Bisogna ricorrere a metodi più affidabili, non ci si può
più basare solo sul test ma bisogna procedere o con simulazioni o con metodi più rigorosi che
assicurino l’assenza di errori. Questi metodi sono detti METODI FORMALI e utilizzano
linguaggi formali. Il linguaggio formale è un linguaggio la cui sintassi e il cui vocabolario sono
limitati, e utilizza regole molto rigorose. Un esempio noto di linguaggio formale è il linguaggio
di programmazione. I metodi formali si usano quindi in sistemi critici ove ad esempio o è a
rischio la vita delle persone, o riguardano problemi economici.

FUNCTION POINTS: quando ci si addentra in contesti di pubblica amministrazione o
azienda bisogna fare un accurato studio dei costi e bisogna valutare quanto vale la
retribuzione per quel sistema software. Per fare ciò vi sono dei modelli di stima dei costi. Tra i
più famosi troviamo il CO.CO.MO.
Negli ultimi anni però si sta utilizzando molto il metodo dei punti funzione, secondo cui non si
valuta più il lavoro in base alle ore che l’uomo impiega nel svolgere l’attività ma in base a ciò
che la persona fa. Per far ciò vi sono metriche non banali da cui poi si tira fuori la valutazione.
Un altro metodo che si affianca alle metriche punti funzione è quello che utilizza le metriche
USE CASE(più in voga negli ultimi anni).
4
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
PROCESSO SOFTWARE
Il processo descrive tutta la sequenza delle varie fasi che si susseguono per arrivare allo sviluppo di un
sistema software che, essendo un sistema complesso, non può avere sviluppo immediato. E’ una
dinamica temporale che decide in che sequenza far susseguire le diverse fasi.
Il processo è talvolta detto “ciclo di vita”.
Ciò che studieremo sono i diversi modelli(schemi) secondo cui le fasi si alternano.
Nel corso degli anni sono stati sviluppati vari modelli, ma si può dire che NON c’è un modello migliore
in senso assoluto rispetto a un altro, poiché va sempre contestualizzato e scelto in base al contesto.
In un contesto di “non-modello” ossia il code-‘n fix, si colloca lo sviluppo dell’ingegneria del software.
Il code-‘nfix era formato da attività casuali, non organizzate, che dava vita a risultati come progetti
non gestibili, caotici, difficilmente modificabili.
I primi modelli che vennero creati rientrano nella categoria detta PROCESSO PRESCRITTIVO, cioè un
processo secondo fasi predefinite.
Il primo è il MODELLO A CASCATA, nato nel 1970, secondo cui le fasi si susseguono in maniera
sequenziale. La caratteristica ed il grande vincolo di questo modello è il non poter ritornare a fasi
precedenti. Ad esempio se si riscontrava un errore in fase di programmazione non si poteva rifare
l’analisi ma si doveva procedere con il rifare da capo tutto il codice.
SCHEMA MODELLO A CASCATA
La prima fase è la studio di fattibilità, che non è una fase informatica, ma è una verifica di costi e
risorse che mi permette di capire ciò che posso o non posso fare. La fase successiva è quella di analisi
e specifica dei requisiti, ossia uno studio del dominio, l’individuazione dei requisiti e l’imposizione di
vincoli. Nella fase di progettazione i requisiti devono essere trasformati in specifiche tecniche.
Successivamente si procede con la programmazione e test di unità, dato che siamo in un’ottica
modulare non ci sarà mai un blocco unico ma tanti blocchi separati per cui si può pensare di testare i
5
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
blocchi uno alla volta e poi unirli e testarli nuovamente nell’insieme. Fare quindi un test di unità e un
test di integrazione. Infine la manutenzione che si svolge nell’arco del tempo. Il sistema deve
presentarsi bene ad eventuali interventi dall’esterno.
Dati i limiti esposti prima, di questo modello si sono proposte due varianti:

CASCATA CON PROTOTIPAZIONE, secondo cui si realizza un prototipo, un esempio
funzionante dall’inizio senza aspettare tutte le fasi.

CASCATA CON RITORNI, che consente al termine di ogni fase di ritornare sulle
precedenti e apportare modifiche.
Dopo lo sviluppo del modello a cascata si trovano il modello incrementale e il modello evolutivo.
Nei modelli incrementali è come se si avesse una cascata con ritorno.
In quelli evolutivi si fa tutto e però poi si possono aggiungere e avere tante versioni diverse del
prototipo fino a quando non si ottiene la versione definitiva.
Tra i modelli evolutivi quello di riferimento è il MODELLO A SPIRALE ideato da Boehm. Il processo
ritorna sempre su se stesso e ogni volta si pianifica la fase successiva. Ci si affida molto alla dinamicità
del sistema.
Tra le caratteristiche vi è una forte interazione col committente e uno studio economico molto più
approfondito e forte.
SCHEMA MODELLO A SPIRALE
6
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Possiamo ancora trovare altri modelli, i modelli specializzati al processo unificato che non sono a sé
stanti ma possono essere integrati con altri modelli. Precisamente lo sviluppo a componenti è una
pratica di progettazione che dobbiamo necessariamente utilizzare quando si realizzano sistemi
distribuiti, per garantire la modularità.
Il PROCESSO UNIFICATO è un modello di processo che definisce le fasi ed è fortemente legato
all’utilizzo dell’UML.
Lo SVILUPPO AGILE(2001) è un modello secondo cui è inutile la documentazione e tende a snellire la
programmazione.
L’EXTREME PROGRAMMING(XP), è una programmazione estrema senza alcuna documentazione e
con un codice estremamente complesso.
7
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
UML
UML = UNIFIED MODELING LANGUAGE.
Questo linguaggio di modellazione deriva dall’unificazione di tre diversi approcci di modellazione che
si sono sviluppati con la programmazione orientata agli oggetti(OOP).
Quali sono i principi delle OOP?

Ereditarietà;

Polimorfismo;

Incapsulamento.
Cosa è l’ereditarietà?
E’ una relazione tra classi. Una relazione è una corrispondenza tra due insiemi.
Una classe è un tipo di dato astratto che in particolare definisce degli attributi e dei metodi.
Parliamo quindi di dati e di funzioni. I dati, ossia le informazioni che vengono gestiti dall’algoritmo,
sono caratterizzati da un tipo e possono essere costanti o variabili. Il tipo di dato è un insieme di
valori che una variabile può assumere e delle operazioni che possono essere eseguite sulla variabile.
Le funzioni sono gli algoritmi, ossia sequenze finite di passi che servono a risolvere un determinato
problema.
Con la programmazione orientata agli oggetti si vuole togliere la separazione tra dati e funzioni per il
principio dell’ Information Hiding (Incapsulamento), ossia per far si che si possa gestire meglio l’uso
delle variabili limitando l’uso solo ad alcune funzioni che hanno bisogno di quelle variabili.
L’information hiding quindi è un principio insito nella definizione stessa di programmazione orientata
agli oggetti.
La differenza tra un oggetto e una classe sta nel fatto che l’oggetto è un’istanza della classe.
Cosa è il polimorfismo?
Il polimorfismo è quella proprietà grazie alla quale è possibile che funzioni con stesso nome possono
svolgere algoritmi diversi a seconda del numero e del tipo di parametri che gli vengono passati.
Ad esempio immaginiamo di avere la funzione che calcola l’area di un quadrato, di un cerchio, di un
triangolo e di un rettangolo. Abbiamo quindi quattro diverse implementazioni di un algoritmo il cui
risultato è sempre l’area. In un programma strutturata dovrei usare quattro metodi diversi con il
vincolo di usare quattro nomi diversi, con la OOP assolutamente no! Avremo una classe “padre”
nominata figura geometrica contenente la funzione che calcola l’area e delle classi “figlie” quali
rettangolo, triangolo e quadrato che ereditano attributi e funzioni dalla classe figura geometrica e in
ogni classe figlia specificherò come va implementata la funzione del calcolo dell’aerea che però avrà
sempre lo stesso nome in tutte le classi.
Qualunque sia il linguaggio utilizzato il compilatore verifica sempre questi tre livelli:

LESSICO, ossia le regole che definiscono il vocabolario.

SINTASSI, regole del linguaggio per scomporre le frasi.(il compilatore controlla che la
frase si attenga alle regole del linguaggio)

SEMANTICA, controllo di corrispondenza tra ciò che è stato dichiarato ed utilizzato,
tipo di dati,ecc ecc, dopodiché genera il linguaggio.
Abbiamo quindi fatto un quadro degli elementi che ci servono per fare questa modellazione in UML.
8
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Che cos’è un caso d’uso?
Prendiamo la definizione che risale al 1995 di uno degli autori del linguaggio stesso secondo il quale è
“una serie di transizioni di un sistema il cui compito è produrre un risultato di valore misurabile per
uno o più attori del sistema”.
Il caso d’uso stabilisce cosa accade nel sistema in seguito ad un evento di attivazione.
Esattamente un caso d’uso è una particolare funzionalità, descritta mediante messaggi scambiati da
un’entità e gli attori.
Cosa è l’entità? E’ un sistema, un sottosistema, una classe ecc.
L’attore è una qualunque entità esterna.
Lo scopo della descrizione dei casi d’uso è di rendere comprensibile il funzionamento, o almeno
l’individuazione delle funzionalità da realizzare, anche a persone che non sono esperte
dell’informatica.
Dove si collocano? Nella prima fase, quindi nella fase di Analisi che risulta essere la fase più astratta,
concettuale, quella in cui si fa lo studio del dominio, poi si procede con l’individuazione dei requisiti,
una volta tirati fuori i requisiti per rendere univoca la comprensione usiamo i casi d’uso. L’aspetto
fondamentale è quello di descrivere il contorno di tutto il sistema.
Tra attore e caso d’uso c’è una qualche relazione di attivazione, per cui quando un attore richiede
una funzionalità si deve attivare il caso d’uso corrispondente. Generalmente i casi d’uso
rappresentano solo una porzione dei requisiti ossia quelli funzionali. Tutti i requisiti detti esterni o
non-funzionali non vengono rappresentati dai casi d’uso.
Di un caso d’uso dobbiamo quindi definire SINTASSI E SEMANTICA. Non abbiamo un lessico perché
come formalismo è elementare.
La sintassi è la seguente:
Nome caso d’uso
SEMANTICAMENTE il caso d’uso ci rappresenta una funzionalità del sistema e quindi un requisito
funzionale. Una volta che ho identificato tutti i requisiti ho trovato tutti i casi d’uso e questi casi
d’uso, gli attori, e le relazioni tra di essi li vado a mettere insieme nel diagramma di casi d’uso dove
ho lo schema di tutta la funzionalità del sistema che mi farà capire in linea di massima quali saranno i
compiti del mio sistema.
Altri elementi che trovo sono gli attori, da non confondere con gli utenti perché l’attore può anche
essere un elemento hardware(es. stampante, tastiera ecc ecc)
La sintassi dell’attore è la seguente:
Studente universitario
9
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Ogni attore ha un nome identificativo scritto sotto la figura dell’omino.
Terzo elemento sintattico sono le frecce di collegamento, che rappresentano le relazioni, ossia le
corrispondenze tra attore e caso d’uso, tra caso d’uso e attore, tra attore e attore o infine tra caso
d’uso e caso d’uso.
Elementi relati
Relazione
Funzione
Attori
Generalizzazione
un attore, specializzato, eredita la
partecipazione a tutti i casi d’uso
con i quali l’attore specializzante
comunica
Esprime la partecipazione di uno
o più attori ad un caso d’uso
Attore - caso d’usoAssociazione
Casi d’uso
Notazione
Estensione
Il comportamento di un caso
d’uso base può, opzionalmente,
essere esteso dal comportamento
definito da un altro caso d’uso
Inclusione
Il comportamento di un caso
d’uso di base incorpora, sempre,
il comportamento dei casi d’uso
di inclusione
Generalizzazione
Un caso d’uso generale ed uno o
più specifici casi d’uso che ne
ereditano ed aggiungono
caratteristiche
Tra attore e attore ho una proprietà di generalizzazione, ossia una relazione il cui significato è
analogo a quello dell’ereditarietà. Ho quindi un attore generico e un attore specializzato,quest’ultimo
ha tutte le proprietà di quello generico con in più delle proprie.
La notazione per questo caso è la seguente :
Attore generico
attore specializzato
Tra attore e caso d’uso l’unica relazione ammessa è lì associazione con la caratteristica che può
essere uni o bidirezionale, dall’attore al caso d’uso, dal caso d’uso all’attore o entrambe o non
specifico nulla. Ho 4 possibilità diverse rappresentate da 4 frecce di collegamento diverse.
10
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Qual è il significato? Esprime la partecipazione di uno o più attori al caso d’uso. Se per esempio
abbiamo il caso in cui bisogna creare una password, il guest richiede l’ inserimento della password e il
caso d’uso si attiva. (vedere esempio slide 22 della presentazione “Introduzione agli use case”)
La cardinalità di una relazione è il numero di entità coinvolte da una parte e dall’altra. Se la
cardinalità è uno a molti significa che a un’ entità ne corrisponderanno dall’altra parte molte.
Esempio: Una persone può acquistare n libri, uno stesso libro può essere acquistato da una sola
persona.
Per quanto riguarda le relazioni tra i casi d’uso ne abbiamo di tre tipi diversi: estensione, inclusione e
generalizzazione.
Il simbolo della relazione di estensione e di inclusione è la freccia tratteggiata.
Prendiamo un esempio di estensione. Ipotizziamo di avere un cliente che deve effettuare un prelievo
da un conto corrente, deve essere fatto quindi un controllo sulla presenza minimo di importo
disponibile. Per fare ciò possiamo pensare di notificare che l’importo residuo vada a zero e attivare
un caso d’uso di notifica azzeramento credito solo nel caso in cui il credito vada a zero. Per questo si
chiama relazione di estensione, poiché è quella parte che viene eseguita solo nel caso in cui si realizzi
una condizione bene precisa che viene detta condizione di estensione.
11
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Il punto di estensione è il dato su cui vado a fare il controllo della condizione che mi potrebbe portare
nel caso d’uso estendente che in questo caso è l’importo prelevato.
Quando l’importo prelevato fa si che si azzeri il credito passo al caso d’uso estendente.
L’altro tipo di relazione è graficamente simile all’estensione ma concettualmente è la duale. Il caso
d’inclusione prevede una parte di codice che viene eseguito sempre, tutte le volte che si esegue il
caso d’uso includente. Lo porto fuori quindi per una questione di visibilità e per garantire la
modularità.
Graficamente è rappresentato così:
Se devo effettuare un prelievo o se voglio richiedere un mutuo, in entrambi i casi, devo controllare se sul
conto c’è un certo importo. E dato che devo controllare la stessa cosa in entrambi i casi, invece di ripetere
la procedura due volte, la porto fuori e ho un caso d’uso che è incluso in entrambi. Qui il verso della
freccia è verso il caso d’uso incluso.
L’ultima relazione è quella di generalizzazione, in cui ho un caso d’uso più ampio e un caso d’uso “figlio”
che specializza quello più ampio. Ad esempio in termini di metodi è il calcolo dell’area del cerchio o del
rettangolo rispetto al calcolo dell’area della figura geometrica. E’ quindi un esempio di polimorfismo, di
over-riding tra classi diverse.
Abbiamo quindi ora un quadro completo per realizzare il modello dei casi d’uso. Attraverso tutte queste
relazioni possiamo esprimere tutto il funzionamento di un intero sistema software a livello astratto, al
termine dell’analisi dei requisiti.
I vari casi d’uso, presi singolarmente, possono essere descritti in maniera più precisa perché bisogna
formalizzare per bene tutta la sequenza di passi che vogliamo realizzare per avere quella funzionalità. E
quindi oltre la rappresentazione grafica possiamo descrivere testualmente ciascun caso d’uso. Si
12
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
utilizzano altre informazioni che l’UML consiglia come ad esempio quali sono gli attori, se ci sono delle
precondizioni o postcondizioni, e ci permette anche di distinguere lo scenario di base da scenari
alternativi che possono essere gli insuccessi dello scenario base.
13
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
DIAGRAMMA DELLE CLASSI
Il diagramma delle classi serve ad illustrare come è strutturato il sistema. Esso contiene le classi e
le relazioni che sussistono tra di esse. Le classi sono formate da attributi e metodi. Il diagramma
delle classi non è altro che un modello di dati oltre che un modello del sistema software che si
vuole realizzare. Non ci dà un modello dinamico sulle specifiche, non vi è nessun algoritmo masolo
una dichiarazione di metodi.
Le principali relazioni fra classi sono associazione, generalizzazione e dipendenza. Studieremo in
modo più specifico la relazione di associazione e quella di generalizzazione.
La relazione di associazione è una relazione semantica tra due o più classi, questa relazione
semantica viene in realtà trasferita tra le istanze delle classi, ossia gli oggetti, e quindi quando si
implementerà quella relazione graficamente tracciata nel diagramma delle classi diventerà a livello
di codice qualcosa che permetterà di legare due o più oggetti, ed è sempre bidirezionale.
L’associazione può essere individuata o assegnando un nome alla relazione o individuando i ruoli
per le entità che sono coinvolte.
Vediamo un esempio:
Azienda
0..1
1..*
Persona
Impiegato
DatoreLavoro
In questo caso abbiamo un’azienda e una persona, due classi con propri attributi e metodi. La
relazione che posso avere tra queste due classi, rappresentata graficamente dalla linea che le
congiunge, è che la persona lavora nell’azienda e l’azienda dà lavoro alla persona. Oppure posso
leggere la relazione in termini di ruoli e quindi la persona è un impiegato o dipendente(ruolo)
mentre l’azienda è il datore di lavoro. La differenza sta nel fatto che la relazione esprime un’azione
che collega le due classi mentre il ruolo caratterizza la classe relativamente all’altra.
Inoltre le relazioni hanno una molteplicità che si esprime sulla linea in prossimità di una o dell’altra
classe. Esempio: L’azienda dà lavoro a una o più persone, la persona è impiegata in 0 o 1 aziende.
Per implementare alcune relazioni, non tutti i linguaggi di programmazione hanno dei costrutti
ben precisi. Per realizzare l’associazione tra due classe devo realizzare un mapping, usando in una
e nell’altra classe un attributo dell’altra classe. Ad esempio in azienda metterò un attributo di
Persona e in persona metto un attributo di Azienda.
Se la relazione è uno a molti metterò una lista di attributi dell’altra classe.
Ovviamente l’associazione si realizza a run-time. A livello statico non avrò mai un collegamento tra
classi!
14
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Ecco un esempio:
IMPLEMENTAZIONE UNO A UNO (C++)
USO DELL’ASSOCIAZIONE UNO A UNO
IMPLEMENTAZIONE ASSOCIAZIONE UNO A MOLTI
15
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
USO DELL’ASSOCIAZIONE UNO A MOLTI(C++)
L’aggregazione come la composizione è un esempio particolare di relazione di associazione, in cui
sostanzialmente abbiamo diverse parti che messe insieme ci danno una classe aggregata. Una
classe contenitore e classi contenute all’interno.
Per l’aggregazione valgono le proprietà transitiva ( se A è parte di B, e B è parte di C, allora A è
parte di C) e antisimmetrica ( se A è parte di B, allora B non è parte di A).
La caratteristica della proprietà è che a run-time l’oggetto contenuto sopravvive all’oggetto
contenitore. Un esempio classico è quello dell’automobile che può essere considerata una classe
aggregata di carrozzeria e motore, posso avere il motore costruito da un azienda e la carrozzeria
da un’altra azienda, esse unite danno vita all’automobile.
Come capisco che si tratta di aggregazione?
Dal fatto che entrambe le parti hanno vita propria anche separate. Se ad esempio durante un
incidente la carrozzeria si distrugge e il motore rimane intatto, il motore potrà essere riutilizzato e
viceversa. Parti distinte con vita propria che messe insieme danno vita a una classe con proprie
caratteristiche.
Come si crea l’aggregazione? Devo definire dei riferimenti alle istanze aggregate nella parte
privata della classe aggregante. Definire riferimenti significa sostanzialmente definire dei puntatori
o un qualcosa che mi possa far ricollegare alla parte aggregata.
Bisogna poi definire delle operazioni per creare il collegamento tra le diverse classi.
Prendiamo l’esempio dell’automobile, abbiamo detto che essa deriva dall’aggregazione tra
carrozzeria e motore , per cui immaginiamo di avere tre classi: automobile, carrozzeria e motore e
di avere nella parte privata della classe automobile i riferimenti alle classi carrozzeria e motore, e
poi un metodo che permetterà di mettere in relazione tra loro le parti provenienti dalle altre
classi. Bisogna poi definire motore e carrozzeria, si definisce il puntatore e si richiama il metodo
che crea,attraverso i puntatori di carrozzeria e motore, l’automobile.
16
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
La differenza sostanziale tra l’aggregazione e la composizione sta nel fatto che le classi componenti
non hanno vita propria al di fuori della classe composta. La classe componente è responsabile
della creazione e della distruzione degli oggetti componenti, e le classi componenti sono ad uso
esclusivo della classe composta.
L’ultima relazione è quella di generalizzazione che rappresenta una relazione gerarchica. Quindi
avremo una superclasse con delle classi figlie poste a un livello inferiore che però ereditano le
proprietà delle classi superiori. Queste classi figlie però, oltre ad ereditare le proprietà della
superclasse, hanno delle loro proprietà specifiche che le specializzano. La relazione si legge come
“è un tipo di”(leggendo dal basso verso l’alto) o “Può essere un”(leggendo dall’alto verso il basso).
Ad esempio, tra gli animali, ho i vertebrati, gli invertebrati e così via. La classe animali è la classe
superclasse , mentre vertebrati, invertebrati e così via sono tutte sottoclassi con una propria
peculiarità. Le classi specializzate ereditano attributi e metodi. La sottoclasse può contenere nuovi
attributi e può ridefinire gli attributi della superclasse. Possiamo pensare alle figure geometriche ,
per tutte si calcola l’area o il perimetro ma in ogni figura geometrica(Triangolo, quadrato ecc)
cambiano le variabili e i calcoli, per cui esso va ridefinito di classe in classe.
La sintassi per la relazione di generalizzazione prevede l’uso della parola chiave <<extends>> .
Esempio:
class Cerchio extends FormaGeometrica.
La classe Cerchio estende la classe FormaGeometrica.
17
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
DIAGRAMMA DI STATO
Il diagramma di stato è la rappresentazione grafica di un grafo.
Cos’è un grafo?
E’ una coppia ordinata di insiemi, l’insieme di nodi e l’insieme di archi. E’ una funzione che ci
permette di creare dei collegamenti tra i nodi mediante delle transizioni.
Il diagramma di stato quindi è una formalizzazione grafica di quelle situazioni in cui l’oggetto che
sto considerando, assume dei comportamenti diversi a seconda degli stati in cui si trova. Per
effetto di vari eventi si passa da uno stato a un altro e quindi il comportamento dell’oggetto di
studio varia.
Lo stato è la condizione che un oggetto ha nel corso della sua “vita”. Nello stato l’oggetto soddisfa
determinate condizioni ed è in attesa di eventi che fanno mutare il suo stato e il suo
comportamento. Finché non si verifica nessun evento, l’oggetto persiste nello stesso stato.
Supponiamo di essere nel contesto di un sistema che gestisce l’ingresso e l’uscita di libri in una
biblioteca.
Il libro può quindi essere disponibile, può essere stato prestato o può essere stato smarrito.
Possiamo rappresentare graficamente la variazione di stati del libro, in seguito ad eventi
innescanti, tramite il seguente diagramma.
Caso 1) Il libro si trova nello stato di disponibilità(Acquisto), viene prestato e passa nello stato di
“Prestito”, cambia quindi il suo stato a seguito dell’evento innescante del prestito. Supponendo
che entro la data utile per la restituzione, l’utente restituisca il libro alla biblioteca, si ha un’altra
transizione che fa sì che il libro ritorni nello stato di disponibilità (Acquisto). Dopo ciò vado verso lo
stato finale solo quando finisce la vita del libro, se ad esempio è ormai troppo rovinato, altrimenti
il libro sarà sempre nello stato disponibile.
18
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Caso 2) Il libro viene prestato, ma non vengono rispettati i termini di consegna. Se l’utente
riconsegna il libro con qualche giorno di ritardo, il libro ritornerà ad essere disponibile.
Se invece, il libro non viene restituito poiché è stato ad esempio smarrito o danneggiato, e quindi
non ritornerà più nella biblioteca, il libro passerà nello stato finale e verrà cancellato dalla
biblioteca.
DIAGRAMMA DI INTERAZIONE
Il diagramma UML che ci permette di rappresentare le interazioni è il diagramma di sequenza. Esso
è la notazione più leggibile delle interazioni tra più oggetti, e rappresenta la sequenza temporale
delle azioni da eseguire. I diagrammi di sequenza derivano dai casi d’uso, per cui per ogni caso
d’uso abbiamo un diagramma di sequenza. E’ caratterizzato da vari oggetti, i quali sono:

Tempo

Oggetti

La linea della vita (LIFELINE)

I messaggi

Eventuali valori di ritorno dei messaggi

Iterazioni
Il tempo riferito all’interazione tra i diversi oggetti è rappresentato orizzontalmente. L’oggetto è in
alto al diagramma rappresentato con un rettangolo contenente il nome. In verticale abbiamo un
rettangolo che rappresenta la LIFELINE dell’oggetto, e si estende dal punto in cui l’oggetto viene
istanziato fino a quando viene distrutto. La linea tratteggiata verticalmente rappresenta il tempo
riferito al singolo oggetto.
Ecco un semplice esempio grafico:
: Cliente
Istanziazione dell'oggetto
Tempo
Distruzione dell'oggetto
Oggetto
19
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Un esempio grafico dei messaggi scambiati tra i vari oggetti è il seguente:
C’è inoltre la possibilità di descrivere il valore di ritorno di un messaggio. Se ad esempio un cliente
invia la richiesta di disponibilità di un prodotto, ci si aspetta un valore di ritorno che quantifica i
prodotti disponibili e viene rappresentato nella maniera seguente:
: Cliente
: Stampante
disponibilita( )
quantità disponibile
È possibile indicare il valore restituito
da un messaggio (mostrato da una
linea tratteggiata)
Si possono rappresentare messaggi di auto delega e di iterazione.
Esempi:
:
CorsodiLaurea
:
Studente
* [per tutti gli studenti iscritti ]
getInfo( )
L'iterazione è indicata dal simbolo *
La condizione di iterazione è
indicata tra parentesi quadre
Ritorniamo ora all’esempio del libro di cui si è parlato nei diagrammi di stato.
20
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Nell’esempio le classi sono stereotipate, ossia non viene usato il rettangolo con il nome come
rappresentazione, ma un simbolo diverso per dare un significato a ciascuna classe relativamente al
livello a cui si trova nell’architettura.
Abbiamo un esempio di uno scenario in cui avviene la richiesta di prestito di un libro.
L’ultimo diagramma UML che studiamo è il diagramma implementativo delle componenti.
Cosa sono le componenti?
Possono essere porzioni di sistema che scriviamo, parti riusabili rese già sostituibili, altri sistemi,
sottosistemi esterni o parti di software.
Per esempio in un’applicazione client-server le componenti sono proprio il client e il server, ossia
parti distinte che interagiscono tra di loro.
Poiché il sistema è complesso, bisogna quindi tracciare un modello che faccia capire quali siano le
componenti, in che relazione sono e come interagiscono, e ciò viene fatto dal DIAGRAMMA DELLE
COMPONENTI.
I Componenti del nostro sistema sono solo entità logiche, ossia che non sono mappabili sulla
macchina direttamente. Il diagramma delle componenti è perciò solo a livello logico. Vediamo un
esempio:
21
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
L’altro tipo di diagramma che rappresentiamo per modellare l’architettura è il diagramma di
configurazione, che raffigura gli elementi così come sono a run-time, ossia in esecuzione.
Esso rappresenterà quindi, non solo le componenti, ma anche i processi.
Non vengono rappresentate le componenti che non esistono a run-time, ad esempio quelle
compilate separatamente.
Graficamente la simboleggiatura è la seguente:
Client-server a tre livelli.
22
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
SISTEMI DISTRIBUITI
Cosa è un sistema distribuito?
Sono dei sistemi per i quali l’elaborazione è distribuita. Non è detto che essa debba essere
distribuita fisicamente, ma la cosa fondamentale è che i componenti di elaborazione siano
distribuiti e quindi non uniti in un unico blocco.
Che vantaggi offre?
 Condivisione delle risorse, che comporta maggiore efficienza, riduzione dei costi, riduzione
di ridondanza, distribuzione del carico.
 Scalabilità, ossia possibilità di variare struttura del sistema senza stravolgere ciò che si ha
già ed è vantaggioso dal punto di vista di manutenibilità.
 Fault tolerance,collegato all’affidabilità, perchè viene garantito che, nel caso in cui un
componente venga meno, gli altri riescano comunque a lavorare.
Per quanto riguarda gli svantaggi abbiamo:
 Maggiore complessità sia a livello di struttura sia a livello di gestione
 Poca protezione, poiché è un sistema aperto e bisogna lavorare per capire e progettare la
sicurezza, la protezione, la riservatezza dei dati e dell’applicazione stessa;
 Non prevedibile, perché ho tante entità che interagiscono quindi è più facile che si inneschi
un meccanismo non previsto dal sistema.
Partiamo con l’analisi delle ARCHITETTURE MULTI-PROCESSORE.
Un’ architettura multiprocessore è fondamentalmente una struttura hardware. Questo implica
che,a differenza del modello classico, ossia a processore singolo, si hanno più processori e la
possibilità di eseguire più processi sui singoli processori.
L’utilizzo di tali architetture è molto comune nei sistemi REAL TIME, ossia quei sistemi in cui
l’aspetto temporale è determinante, sistemi critici dal punto di vista del tempo. In un architettura
multi processore i processi possono essere eseguiti su unico processore, ma ovviamente è
necessario l’uso di uno scheduler, un particolare processo che pianifica l’esecuzione dei diversi
processi su un processore in base ad algoritmi classici. Se si utilizzano processori multipli
ovviamente l’efficienza migliora ma aumenta anche la complessità e si utilizza un dispatcher, un
processo che effettua il controllo del traffico e delle allocazioni tra processi e processori.
Che differenza c’è tra scheduler e dispatcher?
Lo scheduler è la componente del SO che si occupa di allocare il processo al processore, dare
l’ordine. Mentre il dispatcher si occupa solo di controllare il traffico, di gestire le diverse allocazioni
tra processo e processori distinti.
Se abbiamo un sistema formato da processi multipli non è detto che sia un sistema distribuito,
come ad esempio i sistemi operativi.
Nei sistemi distribuiti abbiamo componenti distribuite che interagiscono sfruttando le risorse della
rete.
Le architetture multiprocessore sono una prima categoria dei sistemi distribuiti.
Consideriamo ora il secondo tipo di architettura distribuita,ossia il Client-Server, che è più
semplice da comprendere sia per la modellazione sia per il funzionamento.
Esamineremo in maniera panoramica questi 4 tipi di architetture:
23
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
1.
2.
3.
4.
Politecnico di Bari
Client-Server;
A oggetti distribuiti;.
Peer-to-peer;
A sistemi distribuiti.
In tutti e quattro questi modelli è fondamentale il ruolo del MIDDLEWARE, che è una componente
software finalizzata a gestire la comunicazione delle diverse componenti del sistema stesso. Le
componenti infatti, possono essere scritte con linguaggi diversi, o possono funzionare su
piattaforme diverse, perciò tutte queste incompatibilità vengono gestite dal middleware.
E’ standardizzato e quindi a seconda della tecnologia scelta si sceglierà un middleware piuttosto
che un altro.
Che cos’è una architettura Client-Server?
La caratteristica di una architettura Client-Server è quella di avere appunto un Server che fornisce
dei servizi e un insieme di Client che usufruirà di quei servizi.
Bisogna fare attenzione però alla differenza fra aspetto logico e fisico, perché quando si parla di
Client - Server ci si può riferire sia alla macchina sia al processo, ossia programma in funzione su
quella macchina. Dal nostro punto di vista ci si riferisce ai processi, quindi parleremo di ClientServer sotto l’aspetto logico.
La caratteristica dei Client è che non percepiscono l’esistenza di altri Client mentre conoscono il
Server poiché con esso interagiscono. Diversi processi server possono essere eseguiti su uno
stesso processore, infatti se più client si collegano e chiedono diversi funzionalità, di quel server
vengono eseguiti processi diversi ma su una stessa macchina ed è qui che sta la difficoltà di
gestione.
Sappiamo che una qualunque applicazione deve essere in qualche modo strutturata, bisogna dare
un impostazione al codice in modo che sia leggibile. In generale un’applicazione è organizzata in
tre livelli:
 Presentazione;
 Elaborazione;.
 Parte dati.
Dati questi tre livelli vediamo come un’architettura Client-Server si presta bene a implementare
questo tipo di strutture.
Se stiamo realizzando un sistema distribuito, ogni strato dell’applicazione deve avere una
strutturazione in tre livelli dell’applicazione che andiamo a realizzare.
Le architetture Client-server possono essere a vari livelli.
Posso avere un solo livello Client e un livello server, o tre livelli: client, server e terzo livello,
oppure livelli multipli: Il client ed N livelli con caratteristiche affini ai Server.
Se si ha un’ architettura a due livelli essa può essere di due tipi:
 Thin Client ( A Client leggero)
 Fat Client (A Client Pesante)
Se si ha un’ architettura a Client leggero, il server sarà ovviamente pesante poiché su di esso cadrà
tutta l’elaborazione mentre il Client svolgerà solo l’azione di Interfaccia e di invio dei comandi. Lo
svantaggio è ovviamente l’appesantimento del server e il forte utilizzo della rete che verrà
richiamato ogni qual volta verrà fatta una richiesta dal Client ed inoltre la potenza del Client non
verrà sfruttata al massimo.
Se invece ho un’architettura a Client pesante, l’elaborazione è svolta in parte dal Client oltre al
lavoro di presentazione. Il server oltre al lavoro di elaborazione gestisce le transizioni sul
24
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
DATABASE. Un esempio classico è quello del Bancomat, per un motivo di sicurezza e perché c’è
una continua interazione. Lo svantaggio ovviamente sta proprio nella complessità, infatti una
modifica comporterà un notevole lavoro di adeguamento.
In generale un organizzazione a due livelli avrà svantaggi a livello di scalabilità, prestazioni, e
complessità.
L’altro tipo di architettura client-server è quella a tre livelli che si mappa perfettamente sulla
struttura logica dell’applicazione: la presentazione sarà su client, l’elaborazione sarà sul livello
centrale e la gestione dei dati su un terzo strato. I processi possono essere eseguiti su macchine
distinte, ed alcuni livelli possono essere sulla stessa macchina ma il fatto che si abbia una maggiore
strutturazione fa sì che le prestazioni aumentino.
Ad esempio se ci si trova davanti a un sistema di internet banking,si avrà il database dei clienti e
quindi un mainframe che si occuperà solo della gestione dei dati, poi si avrà un server web che
fornisce i servizi applicativi( login, transazioni, gestione conto ecc) e infine il client dell’utente
finale che grazie al browser interagisce con il resto del sistema.
Vantaggi: Separando il database dal server si possono usare protocolli più veloci, si ha migliore
gestione dei dati soprattutto dal punto di vista della sicurezza e della protezione dei dati perché il
server in tal modo non ha accesso ai dati. Miglior bilanciamento del carico.
Estendendo il modello a tre livelli posso ottenere un architettura a n livelli, quando ad esempio le
applicazioni devono accedere a dati di database diversi o se si struttura il server in più livelli server.
E’ necessario nel caso in cui si abbiano più database server, un server applicativo che lavori per
l’integrazione dei dati, in modo da unirli in un solo formato da inviare al resto dell’applicazione.
Confrontiamo quindi ora le architetture a tre livelli con quelle a due, analizzando i vantaggi e gli
svantaggi dell’una e dell’altra.
Abbiamo già notato come le architetture a tre livelli garantiscano una maggiore scalabilità rispetto
a quelle a due, e un maggiore bilanciamento del carico. Si ha un minore traffico di rete, infatti
quelle a due livelli intasano la rete perché c’è una continua richiesta al server, invece se il server è
su più livelli il traffico è più distribuito.
Più la struttura è a livelli, migliore sarà la manutenibilità, la facilità di aggiornamento e la
modificabilità.
La latenza è minore in una struttura a tre livelli, perché essendoci una divisione dei compiti la
risposta arriva più rapidamente, a differenza di quella a due livelli in cui fa tutto il server.
Quando è preferibile usare l’architettura a due livelli a client leggero, a due livelli a client pesante,
o l’architettura a tre livelli?
Per quanto riguarda le architetture a Client leggero, esse si usano preferibilmente in sistemi
ereditati, di vecchio stampo,realizzati con linguaggi obsoleti. Non avendo strumenti per
modificarli, si usa un interfaccia di connessione per renderli accessibili in rete, senza stravolgere
tutto il funzionamento. Il server è quella che era prima l’applicazione e si pone solo un’ interfaccia
di connessione. Oppure in applicazioni a calcolo intensivo,come i compilatori, in cui nel client ho
solo l’interfaccia, e l’elaborazione, che essendo complessa è difficile da rendere distribuita, in
unico server. Oppure ancora applicazioni in generale che hanno intensa elaborazione sui dati.
E’ preferibile il Client pesante in applicazioni di calcolo grafico, matematico o in ambienti in cui è
necessario che l’utente abbia interazione maggiore con il sistema.
A tre livelli invece quando si hanno dati memorizzati in database o elaborazione intensiva di dati.
Oppure quando bisogna integrare dati provenienti da fonti diversi.
Il modello Client-Server ha però dei suoi svantaggi. Infatti esso è scarsamente flessibile,e la
scalabilità e il bilanciamento del carico non sono impliciti.
25
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Per questo esistono altre architetture, sempre basate su componenti, in cui però il vincolo che ci
sia un componente che fornisce servizi e un componente che richiede servizi, decade. Si avranno
più componenti in grado sia di richiedere che fornire servizi agli altri componenti. Una struttura
abbastanza complessa, con tecnologie di implementazione altrettanto complesse. La caratteristica
è che anche qui è presente un middleware, più complesso di quello presente su un Client-Server,
che in architetture di questo tipo viene chiamato ORB , Object Request Broker.
Si tratta di un’ architettura aperta, molto scalabile, flessibile. Il sistema può essere riconfigurato
dinamicamente. L’aspetto progettuale importante è il fatto che le decisioni su dove devono essere
collocati i diversi servizi, non devono essere stabilite a priori come nel Client-Server. Si può in
corso d’opera aggiungere o modificare le funzionalità.
Studiamo per esempio un’ applicazione di vendita al dettaglio. Essa può essere strutturata in base
a diversi approcci:
 Modello logico di un’architettura a oggetti distribuiti, in cui le funzionalità sono i servizi o la
combinazione di servizi (controllo merci, ordinazione, ecc).
 Modello Client-Server, in cui tutto va sul server e il client si occupa solo dell’interfaccia nei
singoli punti vendita.
Esempi in cui è preferibile usare architetture a oggetti distribuiti: catena di negozi o sistemi data
mining, ossia sistemi in cui a partire da diversi insieme di dati si vogliono ricavare informazioni su
particolari aspetti.
Vantaggi e svantaggi:
 Maggiore complessità rispetto al Client-Server.
 Più efficiente, prestazioni migliori in determinati applicativi
Una caratteristica importante dal punto di vista implementativo è data dalle tecnologie che
devono essere utilizzate. Nell’architettura a oggetti distribuiti possono essere integrate
componenti con linguaggi diversi. Il compito del middleware o il broker ha il compito di integrare
queste differenze ed è proprio un pattern architetturale. In generale il Middleware deve garantire
la comunicazione a livello logico e a livello di componenti.
Passiamo ora ai modelli di calcolo distribuito inter-organizzativo, considerando i due seguenti
modelli di calcolo:


Peer-to-peer;
Architettura orientata a servizi;
Si chiama inter-organizzativo perché, a differenza delle architetture a oggetti distribuiti che
solitamente vengono utilizzate per realizzare applicativi nel contesto aziendale, dove tutti i nodi è
come se fossero circoscritti a livello organizzativo enon c’è un’accessibilità dall’esterno, questi due
modelli sono i modelli più aperti sulla rete, come ad esempio i sistemi che permettono la
prenotazione di un viaggio, in cui servizi diversi, forniti da applicativi diversi che non hanno
nessuna affinità tra di loro, vengono collegati dinamicamente quando l’utente fa la sua richiesta.
Non c’è uno schema predefinito dell’architettura, ma c’è il vincolo che ogni servizio deve
trascrivere le proprie funzionalità in un formato dati conosciuto anche dagli altri, essere
recuperabile da un elenco di tutti i servizi possibili ed esporre un interfaccia facilmente integrabile
negli applicativi che si dovranno ad esso connettere. Queste sono le differenze sostanziali tra un
architettura a oggetti distribuiti e un’architettura a servizi distribuiti.
26
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Vantaggi:




I servizi possono essere forniti da fornitori che sono sia dentro che fuori del sistema. Esiste
una sorta di catalogo pubblico di servizi. Ciò comporta un’elevata affidabilità,perché se in
quel momento richiedo un servizio da un applicativo che non è in funzione posso
immediatamente rimpiazzarlo con un altro, e quindi risulterà sempre minore la situazione
in cui una funzionalità non posso essere fornita, perché il sistema è in grado di individuare
subito un altro applicativo che fornisce la stessa funzionalità.
Il fornitore può riconoscere nuovi servizi, quindi alta adattabilità, scalabilità,
riconfigurabilità.
Vincolo del pagamento, talvolta i servizi sono a pagamento
Le applicazioni sono reattive, quindi si adattano al contesto.
Nel peer-to-peer abbiamo invece una struttura decentralizzata, dove tutte le elaborazioni possono
essere svolte dai singoli nodi della rete, e lo scopo è quello di condividere le risorse di calcolo tra
diversi computer presenti su una rete anche di dimensioni notevolmente ampie. I sistemi p2p
sono utilizzati principalmente per sistemi personali, in cui si vogliono condividere file, messaggeria
istantanea o comunicazione diretta con gli utenti. L’architettura logica della rete è la stessa del
sistema. L’applicazione in genere è comunque basata su componenti che possono essere
distribuiti sui singoli elementi dell’architettura hardware sottostante. L’architettura
logica(software) può essere decentralizzata o semi-centralizzata.
Nell’architettura decentralizzata ogni nodo può essere a conoscenza degli altri nodi e scambiare
direttamente informazioni, i nodi sono organizzati in località e pertanto alcuni nodi fungono da
ponte tra un nodo e un altro. Non solo perciò dei singoli elementi funzionanti ma sono anche dei
commutatori nella comunicazione. Ovviamente si ha ridondanza, che può essere sia un vantaggio
che uno svantaggio, poiché essa protegge il sistema dal verificarsi degli errori, e over-head del
sistema perché la stessa ricerca può essere elaborata da diversi nodi e quindi si ha maggiore
comunicazione e sovraccarico del sistema(Svantaggio).
Nell’architettura semi-centralizzata invece, uno o più nodi svolgono funzioni tipo Server, che
indirizzano la comunicazione verso altri nodi, quindi si ha un minimo di gerarchia ma l’applicazione
funge sempre come se non ci fosse un server.
Rispetto all’architettura a servizi distribuiti il P2P è più efficiente, però essendo in connessione 1 a
1 si ha una maggiore esposizione ai rischi di protezione. E’ preferibile non utilizzarli in ambienti
lavorativi.
Abbiamo quindi categorizzato i sistemi distribuiti da un punto di vista software con questi quattro
modelli, che ci definiscono le caratteristiche generali secondo cui i componenti dell’architettura
del sistema interagiscono.
Conoscere questi quattro modelli però non ci basta perché le architetture e i sistemi software da
realizzare sono molto complessi e quindi ci occorre fornire ulteriori linee guida per integrare i
diversi componenti.
Per questo passiamo ai Pattern architetturali.
Sappiamo che ci sono dei modelli architetturali e a seconda di questi modelli posso scegliere quali
pattern architetturali utilizzare.
Un pattern software è la descrizione strutturata di una soluzione a un problema software
ricorrente. Ad esempio se ho un’architettura a servizi, so che ci sono tante componenti distinti che
comunicano, che ci deve essere un’interfaccia,che ci deve essere un catalogo con relativi servizi
27
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
forniti però l’architettura non mi dice altro e ho bisogno di scegliere pattern architetturali per
capire come integrare questi servizi soprattutto perché l’integrazione avviene dinamicamente.
I pattern possono essere classificati in :
 Pattern architetturali (livello più astratto), che modellano lo schema organizzativo di una
struttura nell’ ambito di un’architettura software. Mi fa capire come i vari componenti
possono interagire tra loro, come far avvenire la comunicazione con il database ecc.
 Pattern di design: prendo ogni componente, in ogni componente abbiamo i package in cui
vi sono le singole classi. Anziché modellarle in maniera empirica posso raggrupparle
utilizzando degli schemi predefiniti(design pattern) che rendono più elegante lo schema
delle classe e che risolvono una determinata problematica.
 Pattern di implementazione(frame work), livello di minore astrazione perché siamo nella
fase di scrittura del codice.
Partiamo dai pattern architetturali.
Ipotizziamo di modellare un sistema software, ipotizzando di utilizzare il processo unificato,
abbiamo concluso la fase di ideazione e quindi abbiamo individuato i requisiti funzionali e non, che
ci permettono di capire che architettura utilizzare e come organizzare i componenti.
In questo ci possiamo avvalere dei pattern architetturali. I pattern non sono tutti uguali ma
possono essere raggruppati a seconda dei problemi che risolvono, ad esempio abbiamo famiglia di
pattern che risolvono i problemi di come il sistema si deve interfacciare al database. Oppure
abbiamo l’insieme dei pattern che gestiscono la comunicazione dei componenti nel sistema
distribuito, ed è l’insieme più ampio ed importante dato che la comunicazione è un aspetto molto
importante nei sistemi a oggetti distribuiti. Poi abbiamo tutti i pattern che si occupano
dell’interfaccia. O ancora i pattern che si occupano di come modellare i componenti sul livello
client, sul livello server, e sull’application server.
Altri pattern importanti sono quelli che gestiscono l’application e l’extend. E poi abbiamo i pattern
che gestiscono i problemi di sincronizzazione, ossia quando si hanno delle risorse condivise
bisogna sincronizzare l’accesso alla risorsa. Pattern per problemi di concorrenza,secondo cui
diversi processi richiedono l’uso di un determinato processo e pertanto bisogna schedulare
l’accesso alle risorse nonché la concorrenza,e poi problemi di gestione delle risorse.
I pattern relativi alla decomposizione del sistemi in sottosistemi sono i più numerosi, partendo dai
requisiti vedo come posso organizzare il sistema avvalendomi di alcuni pattern come ad esempio il
Layer ( modello a strati, esempio: sistema operativo) ,Domain Model, Domain object.
Abbiamo poi una seria di pattern che modellano la comunicazione nei sistemi distribuiti, il più
importante è il PATTERN BROKER. Sul modello Broker è strutturato il middleware.
L’altro gruppo importante è quello dei pattern che supportano l’interazione uomo macchina, e i
più importanti sono il Model View Controller e il Presentation abstraction Control.
I pattern non sono indipendenti, alcuni sono in alternativa, altri lavorano in sinergia, in più si
possono mettere insieme per risolvere problemi più grandi. Se si rappresentano tutti otteniamo
un enorme struttura che collega tutti i pattern in maniera diretta.
Analizziamo quindi in dettaglio alcuni di essi:
LAYERS
E’ il modello che separa le funzionalità dei singoli componenti. Ogni livello fornisce funzionalità a
livelli superiori, ma i livelli superiori sono trasparenti pertanto funziona come una macchina
virtuale. Posso modificare un livello senza modificare gli altri.
28
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
DOMAIN MODEL
Modello concettuale. La prima fase che si realizza è l’analisi del modello di dominio. Lavora
nell’ottica della modularità
DOMAIN OBJECT
Permette di strutturare un modello di dominio in componenti più specifiche.
MODEL VIEW CONTROL
Separa l’interfaccia dall’applicazione. Ci permette di rappresentare il contenuto del Client, del
Server, e dell’application Server . Quindi rappresenta delle Classi di interfaccia, delle classi di
controllo che elaborano la logica di business delle applicazioni, e delle classi entity, che si
definiscono nella prima fase di analisi e restano il nucleo di modellazione dei dati.
Il controllore conterrà dei package delle classi di controllo, il modello sarà costituito dalle classi
individuate in fase di analisi, in vista ci saranno le classi che si occuperanno dell’interfaccia.
PIPE AND FILTER
E’ generalmente utilizzato nel contesto dei sistemi operativi, nei sistemi real-time e in particolare
per sistemi che devono elaborare flussi di dati. L’elaborazione viene scomposta in passi di
decomposizione e ogni passo viene incapsulato in un filtro, un oggetto software, i dati poi sono
trasferiti in filtri adiacenti detti Pipe, che sono immaginabili come tubi, dei canali virtuali dove
29
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
passano flussi di dati. E’ possibile mettere in relazione famiglie di dati correlati, collegando in
maniera adeguata i filtri e i Pipe, creando cosi delle PipeLine.
SHARED REPOSITOR
Utilizzato per applicazioni a intensa elaborazione dati, in cui ci sono interazioni tra i componenti
che non siano guidate da specifici processi, che però possono essere coordinate in base a un set di
dati condivisi, un repository. Ho un repository e tutti i processi che lavorano su quel repository.Il
repository è condiviso, ed è come se fosse a partire dal repository che avviene il coordinamento
dei vari componenti e dei vari processi di elaborazione. L’accesso ai dati deve essere sincronizzato.
DATABASE ACCESS LAYER (DAL)
Serve per separare la logica dell’applicazione dal modello dei dati. Si ha uno strato di interfaccia
tra il sistema e il database management system. Questo strato si occupa delle transazioni di
Query.
BLACKBOARD E REFLECTION
Sono due pattern che permettono la modifica dei requisiti a run time. Il blackboard è utilizzato in
sistemi di intelligenza artificiale, per creare una sorta di “Lavagna” comune su cui tutte l
applicazioni possono comunicare.
Il reflection consente i cambiare la struttura di un sistema in modo dinamico, strutture dati
meccanismi di comunicazione, dividendo l’architettura in due livelli, ossia da una parte i Metadati
e poi un livello base che contiene la logica applicativa stessa del meta livello
BROKER
E’ il pattern principale per la comunicazione nei sistemi distribuiti. Serve per strutturare sistemi
distribuiti con componenti disaccoppiate che devono interagire. Rende possibile l’invocazione di
servizi remoti tra i vari componenti, coordina la comunicazione, gestisce le richieste e le risposte
tra i vari componenti di un sistema distribuito e pertanto è particolarmente utilizzato.
30
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
MICROKERNEL
Consente di sviluppare un insieme di applicazione che siano l’una la variazione dell’altra. Il nucleo
centrale è sempre lo stesso però possono variare dinamicamente a seconda dei requisiti
dell’utente o in base al contesto di utilizzo di funzionamento di quell’applicazione. Si possono
differenziare per l’interfaccia utente a seconda ad esempio del Profilo utente esistente.
Vediamo ora un aspetto un po’ più tecnico che riguarda le tecnologie di implementazione.
TECNOLOGIE DI IMPLEMENTAZIONE
Per tecnologia intendiamo non solo il linguaggio di programmazione ma anche tutti i requisiti ad
esso legati. Se si sceglie di usare un particolare linguaggio, si dovrà adattare la struttura del
sistema, le specifiche nel codice, le piattaforme da utilizzare e tutto il contesto che c’è dietro le
tecnologie di implementazione. Prima di parlare di tecnologie diamo una definizione di
componente. Cosa è un componente? Per dare questa definizione,entriamo nel merito del
modello di processo Component Based, che non è solo un modello di processo perché può essere
usato trasversalmente agli altri.E’ un processo di definizione, implementazione o integrazione di
componenti debolmente accoppiati, ossia che abbiano lasca connessione tra loro. Il Component
Based Software Engineering nasce dal concetto di modularità e riutilizzo, e si basa su componenti
indipendenti e standardizzate, sul middleware e sul processo di sviluppo.
Secondo l’OMG un componente è una parte modulare, utilizzabile e sostituibile di un sistema che
comprende l’implementazione ed espone una serie di interfacce. Sostanzialmente un componente
è un elemento costitutivo del software.
Un componente deve essere standardizzato, indipendente, componibile (si deve poter integrare
nelle interfacce pubbliche del sistema), consegnabile e documentato.
Se abbiamo un sistema basato su componenti abbiamo un middleware, che è lo strato che
troviamo tra il software applicativo e il sistema operativo, e implementa un meccanismo di
comunicazione tra processi.
La comunicazione tra processi è generalmente nota come IPC (Inter Processing Communication).
Essa avviene mediante diversi meccanismi e schemi a diversi livelli. Può avvenire o a basso livello,
o a livello di linguaggio di implementazione, o a livello applicativo o mediante software. A seconda
di dove avviene la comunicazione, cambieranno le primitive e i meccanismi di comunicazione. A
diversi livelli possiamo utilizzare il meccanismo di Pipe (Pipe and Filter), o il socket, che è un
canale di comunicazione a livello più basso di quello applicativo, oppure mediante il memory
mapped file,quindi a livello hardware, oppure mediante chiamata a procedura remota (RPC), a
livello applicativo e sempre a questo livello può essere utilizzato il meccanismo di scambio di
messaggio.
In base alla modalità secondo cui avviene IPC possiamo caratterizzare il middleware secondo
tipologie diverse:
 Remote Procedure Control, quando abbiamo architetture Client- Server;
 Remote data access, simili a RPC, tipicamente utilizzate per accedere a basi di dati;
 Message Oriented middleware;
 Transaction processing monitor;
31
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software

Politecnico di Bari
Distributed object, in cui l’invocazione dell’oggetto avviene tramite il broker.
I modelli di componenti possono essere standardizzati, infatti a parte i nostri componenti, ci sono
componenti standard che vengono acquistati, integrati nell’applicazione e che sono ad esempio
quelli del formato Microft.net, nel formato Corba, o nel formato Java beans.
Tra i componenti Microsoft troviamo i seguenti:
 Com, Component Object Model;
 Dcom, Distributed Component Object Model;
 Com+,
 Soap, protocollo a livello ancora più alto nella comunicazione tra applicazioni ed è basato
su XML, ossia un linguaggio che ci permette di formattare dei dati, e creare dele strutture
nell’ambito dei dati. Linguaggi di mark-up.
 .Net, componente più standardizzato e moderno per eterogeneità di linguaggio.
L’OMG (Object management group) definisce lo standard di oggetti per esempio CORBA per
oggetti distribuiti.
Corba è la tecnologia per implementare architetture a oggetti distribuiti più diffusa,si basa sul
broker e garantisce eterogeneità di linguaggi e di piattaforme, ossia posso realizzare applicazione
in cui i vari oggetti sono realizzati con linguaggi diversi e funzionano su piattaforme diverse, il
middleware Corba permette la comunicazione tra questi oggetti eterogenei e realizzare
l’applicazione distribuita in cui i componenti sono tutti allo stesso livello.
L’altro standard é SUN, infatti se standardizziamo i componenti secondo questo meccanismo, la
comunicazione avviene tramite RMI( Remote method information), ossia gli oggetti possono
essere eseguiti su macchine virtuali diverse e comunicare mediante chiamate a metodi remoti. Gli
oggetti si chiamano Java beans, o enterprise java beans se rientrano in una fascia di componenti
più complessi.
Se invece siamo in un contesto Web e vogliamo realizzare applicazioni Client- server, dobbiamo
partire dalla definizione di applicazione web, ossia “un sistema che permette ai propri utenti di
eseguire la logica di business con un browser” (Conallen, 2000).
In un’applicazione web troviamo una logica di business che può risiedere o sul client o sul server,
un browser che è indispensabile per interpretare parte della logica che verrà eseguita sul Client, e
pagine web che possono essere statiche o dinamiche. L’application server è il server applicativo
che monitora lo stato dell’applicazione, importante per tenere traccia delle operazioni effettuate,
dello stato degli utenti e così via. Ad esempio come monitorare mediante i cookie, rappresenta lo
stato dell’utente collegato, e ci permette di avere traccia delle operazioni svolte dai diversi Client.
Questo è molto utile soprattutto se il numero di utenti è molto elevato. Possiamo rendere
dinamica una pagina web tramite uno script, ossia un programma interpretato dal browser.
L’interprete interpreta ed esegue direttamente istruzione per istruzione, invece il compilatore è un
traduttore che dato un programma sorgente genera un programma eseguibile. Sono due fasi
distinte, solo che in determinati casi, come in Java, si ha un linguaggio che per metà è interpretato
e per metà viene compilato.
Quando invece abbiamo la pagina server, possiamo utilizzare diverse tecnologie come le java
server pages o le servlet se utilizziamo una tecnologia Java.
Abbiamo visto che a livello progettuale il modello logico di un applicazione su un architettura
client server, si realizza con il pattern MVC (Model view Control), simile a questo pattern è il
32
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
pattern BCE, Boundary control entità, e trova anche riferimento nell’UML. Lo scopo è individuare i
confini del sistema, caratterizzare i dati, progettare e implementare la logica di controllo
dell’applicazione stessa.
Il pattern trova una sua diretta configurazione nell’UML perché è possibile utilizzare gli stereotipi
delle classi stesse: <<Boundary>>.
Le classi Boundary sono classi di interfaccia tra l’attore e il sistema, e lo scopo è quello di isolare il
sistema dai cambiamenti che avvengono nell’ambiente esterno e di interfacciare le classi con altri
sistemi. Le classi Control sono quelle che si collocano al centro del modello, e quindi nel lato server
e gestiscono tutte le operazioni di elaborazione e implementano la logica di controllo delle
applicazioni (ad esempio le servlet delle applicazioni Java).sono indipendenti dall’ambiene esterno
e non sopravvivono all’interazione.
Infine le classi entità definiscono il modello dei dati, e nascono già in fase di analisi, sono le prime
che derivano direttamente dai requisiti. Nelle fasi successive saranno sempre presenti ma saranno
affiancate da altre classi (Boundary e Control).
A causa del gap esistente tra il modello dei dati relazionali e il modello dei dati ad oggetto, le classi
entità rappresentano la modellazione dei dati nell’ambito però del nostro sistema, e tramite esse
avverrà l’accesso dai dati da elaborare che saranno presenti nel database, mediante l’utilizzo
dell’ibms o mediante il DAL che implementerà la logica di accesso al database. Eventualmente si
può pensare di inglobare parte di questa elaborazione nel livello entità oppure di aggiungere un
ulteriore livello che nella formalizzazione del modello BCE si formalizza con una D per cui diventa
BCDE, Boundary Control Entity Database ed è l’applicazione di un modello DAL che realizza solo
l’implementazione delle transazione e delle query.
Lo schema grafico è il seguente:
Estendendo l’architettura a tre livelli a una a N-livelli vengono introdotti un livello USER e uno
INTEGRATOR, il primo è molto vicino al livello di presentazione, mentre nel secondo si può
prevedere l’introduzione di un broker in modo che si integrino dati provenienti da database
diversi, e quindi un ulteriore livello in modo da rendere l’applicazione mappabile sull’architettura a
tre livelli.
Le applicazioni ENTERPRISE, sono una categoria di applicazioni il cui nome si riferisce sia alle
applicazioni che le tecnologie , e sono riferite ad applicativi in un contesto ampio di grossa
organizzazione, utilizzate per fornire delle funzionalità di supporto alla logica di business anche per
una grossa impresa, al di là del semplice portale che si realizza si può immaginare la stessa
struttura però proiettata in un contesto molto più grande e quindi si parlerà di applicazione
enterprise. Il meccanismo è lo stesso ma cambia la granuralità e l’ampiezza del contesto,
cambiano le tecnologie e anche i modelli architetturali.
Facciamo ora un piccolo riepilogo di tutto ciò che abbiamo fatto. Ci stiamo occupando di come
ingegnerizzare un processo di sviluppo di software e per fare ciò bisogna sia rendere ingegneristico
il processo, ossia la sequenza delle fasi necessarie per portare a termine il prodotto, sia definire i
criteri secondo cui quel prodotto deve essere realizzato. Per quanto riguarda il processo vi sono
vari modelli che si possono seguire, di cui il più moderno è l’UP (Processo Unificato) che si modella
bene in relazione al linguaggio di modellazione che è l’UML. Per quanto riguarda il software da
realizzare, lo sviluppo non è d’impatto, ma è frutto di un lavoro più o meno approfondito che
33
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
parte dall’analizzare il dominio e il contesto di utilizzo e passo dopo passo arriva ad analizzare le
funzionalità che occorre fornire, tutte quelle che possono essere realizzate, come strutturare il
sistema in un modello component-based e definendo un architettura di massima, cioè come i vari
componenti devono interagire. L’aspetto più complesso è quello di definire l’architettura, sia
perché esistono vari modelli che dipendono dal tipo di sistema che vogliamo realizzare, infatti se
ad esempio l’applicazione è orientata al web si preferisce un modello ad un altro, e poi perchè
dopo aver scelto l’architettura è necessario scegliere delle tecnologie di implementazione. Dopo
ciò va progettato ogni componente, quali sono i package, le classi, e va visto come il sistema deve
funzionare, e quindi la sua dinamicità che deriva in parte dalla prima fase di analisi in cui vengono
individuati i requisiti funzionali, che, di volta in volta, devono essere specificati nel dettaglio e
faranno da tramite per scrivere il codice del sistema in maniera più agile. Una parte molto
importante è tutta la fase di test, in cui il sistema che è stato realizzato, deve essere valutato per
capire se è un sistema di qualità, se risponde a dei requisiti non funzionali,evidenziati nella fase di
analisi, che specificano come il sistema deve realizzare quelle funzionalità, quindi se deve garantire
affidabilità anziché scalabilità e cosi via.
DESIGN PATTERN
Si tratta di soluzioni già pronte, che permettono di realizzare il principio del riuso, uno dei principi
base dell’ingegneria del software, non solo a livello di codice (librerie di classi) ma anche a livello di
progettazione, perché abbiamo dei pattern(schemi vuoti) che possono essere adattati allo schema
delle classi che vogliamo realizzare.
Attraverso questa tabella possiamo classificare i pattern secondo lo scopo (Creazionali, Strutturali
o comportamentali) e il raggio d’azione (per Classi o per Oggetti). Questi qui sotto elencati sono i
più noti e più utilizzati.
Raggio d’azione
Classi
Oggetti
Scopo
Creazionale
Factory method
Abstarct factory
Builder
Prototype
Singleton
Strutturale
Adapter
Comportamentale
Interpreter
Template Method
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Chain of responsibility
Command
Iterator
Mediator
Memento
Observer
State
Strategy
Visitor
34
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Partiamo dai pattern Strutturali, i quali si occupano del problema di come comporre le classi e gli
oggetti per formare delle strutture più complesse. Abbiamo sia pattern basati su classi che basati
su oggetti. La differenza sta nel fatto che quelli basati su classi le interfacce e le implementazioni
vengono composto mediante l’ereditarietà, quelli basati su oggetti descrivono la modalità secondo
cui comporre gli oggetti per realizzare nuove funzionalità, ovviamente in questo modo è possibile
fornire maggiore flessibilità.
L’Adapter è quello più utilizzato in assoluto poiché fornisce la funzionalità di convertire
l’interfaccia di una classe nell’interfaccia di un'altra classe. Supponiamo di avere un editor grafico
in grado di comporre disegni ma anche testo. L’incompatibilità sta nel fatto che testo e linee e
poligoni sono classi con interfacce diverse e quindi per rendere simili uso l’adapter.
Vediamo un esempio grafico:
Supponiamo di avere un editor grafico in grado di disegnare sia grafici sia testo. E’ evidente dove è
l’incompatibilità,infatti essa sta nel fatto che testo e poligoni sono classi con interfacce diverse ma
non del tutto incompatibili. Pertanto bisogna trovare un modo per renderle compatibili.
Supponiamo di avere una Shape astratta, quindi una classe che definisca le caratteristiche degli
oggetti grafici, e l’applicazione definisca una sotto classe di shape per ogni oggetto specifico. Se
volessi implementare una Text shape essa non può essere messa direttamente come sottoclasse di
Shape (ossia della forma geometrica) poiché il testo ha caratteristiche ben diverse. Vorrei quindi
riutilizzare un classe (text view) per visualizzare e modificare il testo. La tentazione sarebbe quella
di modificare la classe, ma ciò è totalmente sbagliato!! E’ sbagliato concettualmente perché si sta
venendo meno al principio della riusabilità,poiché se si ha qualcosa di rigidamente già definito si
può utilizzare in vari contesti, adattandolo ma mai stravolgendolo! Se non è riusabile direttamente
non si deve modificare, ma si deve fare in modo che essa possa essere utilizzata, adattata. Per cui
bisogna utilizzare una nuova classe “Text shape” che vada ad adattare la text view e permetta di
rendere compatibili la shape e la text view senza modificarle.
L’editor grafico può utilizzare la classe text view come se fosse un “figlio” della classe shape.
35
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Quali sono i vantaggi dell’adapter?
Esso fornisce delle funzionalità che la classe adattata in caso contrario, non avrebbe.
Quando utilizzarlo?
La difficoltà dei pattern sta proprio nel capire come e quale pattern utilizzare. In linea di massima
usiamo l’adapter quando abbiamo una classe esistente con interfaccia diversa con un'altra e
vogliamo che esse interagiscono. Oppure quando si vuole creare una classe riusabile che si possa
correlare con classi con interfacce diverse.
La struttura di un adapter in sintesi è di questo tipo:
Nell’Adapter abbiamo una classe Target che definisce l’interfaccia specifica del dominio utilizzato
dal client, che è il resto del sistema. L’adaptee è l’interfaccia che deve essere adattata e l’adapter è
la classe che si occupa appunto di rendere le due interfacce compatibili.
Simili all’adapter vi sono il Bridge,il Proxy e il decorator. Il Bridge ha come obiettivo quello di
separare l’interfaccia dall’implementazione. Disaccoppia l’astrazione dalla sua implementazione.
Esso si usa quando non si vuole un legame permanente tra astrazione e implementazione. Se ad
esempio voglio poter variare dinamicamente l’implementazione di una classe. Oppure quando
voglio estendere sia l’implementazione che l’astrazione usando il meccanismo delle sottoclassi.
Per quanto riguarda la struttura si ha una classe astratta con diverse implementazioni di essa, e la
classe astrazione che non ha nessuna relazione di ereditarietà con le classi concrete
implemenction.
36
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
L’abstraction è l’ interfaccia dell’astrazione che ha un riferimento all’implementor che è il vero e
proprio bridge, e definisce le interfacce per le classi implementatrici e non corrisponde
totalmente all’interfaccia dell’abstraction perchè deve permettere di eseguire una piuttosto
dell’altra tra le implementazioni esistenti .Il concrete implementor definisce le varie
implementazioni con la realizzazione completa di un algoritmo piuttosto che un altro.
Esempio:
Supponiamo di implementare un toolkit per interfacce utente in ambiente Windows che permetta
di scrivere applicazioni che siano eseguite su piattaforme X o IBM. Se usassimo l’ereditarietà
dovremmo stabilire staticamente una sottoclasse per ogni tipo di finestra, e quindi sarebbe piu
difficile seguire le applicazioni su piattaforme distinte mentre con l’implementor scelgo se seguire
l’implementazione su piattaforma X o IBM.
Si spezza la gerarchia dell’ereditarietà, L’aspetto di implementazione è distinto e gestito da un
ulteriore classe.
Il DECORATOR permette di aggiungere dinamicamente responsabilità ad un oggetto, cioè invece di
definire delle sottoclassi per estendere delle funzionalità si aggiunge un decorator che aggiunge
queste funzionalità. Per aggiungere funzionalità a singoli oggetti e non all’intera classe, e ciò fa
capire che si sta parlando di qualcosa che succede a run-time, modifica dell’oggetto
dinamicamente. In caso contrario bisognerebbe creare una sottoclasse staticamente
appesantendo una struttura di ereditarietà con qualcosa che non sempre sarebbe strettamente
necessario. Il decorator ha interfaccia conforme a quella dell’oggetto da estendere in modo di
renderlo trasparente al client (ossia a tutto il resto del sistema, le richieste vengono trasferite al
componente decorato, l’altra caratteristica è che consente l’aggiunta di un numero “illimitato” di
funzionalità e non compromette altre classi.
La struttura ricorda un po’ quella del bridge poiché il decorator fa da tramite tra il componente e
la sottoclasse di esso. Fa da tramite per poi selezionare una funzionalità piuttosto che un'altra,
dinamicamente.
37
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
La struttura è la seguente:
Il Component definisce l’interfaccia comune per gli oggetti ai quali possono essere aggiunte
responsabilità dinamicamente, Il concrete Component definisce un oggetto al quale possono
essere aggiunte responsabilità ulteriori, il decorator è la sottoclasse che mantiene il riferimento al
component e definisce l’interfaccia conforme a quella di component che però faccia da tramite
con il concrete decorator, il concrete decorator sono quelle funzionalità che posso aggiungere
all’oggetto.
IL Proxy ha lo scopo di fornire il surrogato o un segnaposto di un altro oggetto per controllare
l’accesso a tale oggetto. Quando per esempio in documenti di testo inserisco l’immagine in realtà
inserisco un proxy.
La motivazione per cui utilizzare il Proxy è quello di controllare l’accesso a un oggetto. Lo si applica
quando si necessita avere riferimento a un oggetto che sia più versatile e raffinato di un semplice
puntatore. Il proxy è un oggetto vero e proprio che ha una sua caratterizzazione. Esso può essere
remoto,quando fornisce rappresentazione locale di un oggetto in diverso spazio di indirizzamento ,
virtuale, quando si vuole risparmiare in termini di memoria e di tempo di esecuzione, o un proxy di
protezione se voglio controllare l’accesso a un oggetto, quando ad esempio si hanno dei diritti di
accesso su un oggetto.
ll Subject è l’interfaccia comune mentre il real subject è l’elemento duplicato dal Proxy.
38
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Possiamo quindi arrivare a commentare i pattern strutturali.
Essi si basano su un insieme di meccanismi messi a disposizione da linguaggi di programmazione
che possono risolvere problemi di implementazione di aggiunta di funzionalità e cosi via, a run
time. Solo nel caso dell’adapter il problema viene risolto staticamente. I meccanismi sono quelli di
composizione tra gli oggetti.
La seconda categoria di pattern sono quelli COMPORTAMENTALI di cui studieremo l’Observer e lo
Strategy.
Essi in generale si occupano di come attribuire le responsabilità ad oggetti che comunicano tra
loro, a run time, problemi simili a quelli del Bridge. Quando si hanno flussi di informazioni difficili
da seguire, e quando vogliamo studiare le relazioni dinamiche tra oggetti. Quei pochi pattern
basati su classi utilizzano l’ereditarietà, mentre quelli su oggetti utilizzano la composizione. Con
l’uso dei pattern si riesce a comunicare, modificare e uant altro mantenendo molto basso il livello
di accoppiamento.
L’OBSERVER
E’ un pattern di collaborazione tra oggetti, di design.
Lo scopo è quello di definire una dipendenza uno a molti tra oggetti in modo tale che se un
oggetto cambia il suo stato, tutti gli oggetti ad esso legati siano “avvisati” di questo cambiamento
e aggiornati. La finalità è quella di mantenere un buon grado di affidabilità del progetto.
Può essere usato in un’astrazione, una classe che presenta due aspetti tra loro vincolati. Vado a
incapsulare gli aspetti in due oggetti distinti che potranno essere usati indipendentemente. Una
modifica a un oggetto comporta la modifica di altri oggetti e quindi un elevato accoppiamento.
Posso risolvere questo problema con l’Observer, svincolando i vari oggetti in modo tale che gli altri
non debbano essere modificati.
Oppure quando un oggetto deve notificare agli altri determinate situazionio senza conoscere
l’identità precisa degli altri oggetti.
La struttura è la seguente:
39
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Il Subject è l’elemento che conosce i propri observer, può avere un numero qualunque di Observer
che ne controllano i comportamento e pertanto ha un’interfaccia per ciascuno di essi. L’observer
fornisce l’interfaccia di notifica per gli oggetti che devono essere informati dei cambiamenti del
subject. Il concrete Subject fornisce lo stato a cui tutti gli oggetti sono interessati e il Concrete
observer fornisce il collegamento con il Concrete Subject.
Mentre l’observer risolve un problema di comunicazione tra oggetti, lo strategy è importante
perchè ci permette di definire una famiglia di algoritmi senza definire una sottoclasse figlia di una
superclasse. In maniera molto snella e dinamica incapsula in alcuni oggetti determinati algoritmi e
poi sceglie se utilizzarne uno anzichè un altro. L’algoritmo incapsulato è detto strategy e si usa
quando abbiamo classi quasi uguali che differiscono nel comportamento. Ho bisogno di più
varianti dell’algoritmo ma la classe non cambia.
METRICHE DI PRODOTTO
Se si vuole parlare di qualità di un software, bisogna riferirsi a determinati parametri che non sono
cosi espliciti come in altri prodotti. Il problema infatti sta nel fatto che non si ha nulla di tangibile
su cui basarsi e pertanto bisogna usare delle strategie per capire se il prodotto è di qualità o meno.
Come e quando possiamo dire che un software è di qualità? Quali sono gli aspetti che
garantiscono la qualità? Non si può dire in maniera univoca se un software è di qualità poiché esso
va sempre contestualizzato e valutato in base al contesto in cui agisce. Bisogna verificare che il
sistema soddisfi sempre i requisiti. Se ad esempio un software soddisfa i requisiti utente ma non
quelli non funzionali no si può dire che esso sia un sistema di qualità. I requisiti non funzionali
servono proprio a capire la qualità del sistema. E quindi il problema sta proprio nel valutare e
considerare i requisiti non funzionali, ossia gli attributi di qualità. Essi determinano una specifica di
qualità. Si può cercare di mettere ordine tra tutti i possibili attributi di qualità in modo da cpaire
quali sono i più importanti che il sistema deve necessariamente rispettare per essere un sistema di
qualità. Il problema sta nel mettere in relazione i requisiti non funzionali con il sistema stesso. Ad
esempio, un requisito non funzionale può essere la sicurezza. Ma come capisco dal sistema se il
requisito è garantito o meno? IL sistema ha una sua compleeìssità, i requisiti sono parametri
qualitativi e pertanto bisogna creare un rapporto tra questi due. Per fare ciò si utilizzano dei
modelli di qualità e ne esistono diversi tipi.
Diamo però prima la definizione di requisito secondo RUP :
“Un requisito descrive una condizione o una capacità a cui un sistema deve conformarsi; può
essere sia derivato direttamente da esigenze degli utenti, o indicato in un contratto, uno standard,
in delle specifiche o altri documenti o essere formalmente imposto.”
Un requisito architetturale ha importanza nella valutazione dell’architettura software e nella sua
implementazione. Essi possono essere sia impliciti(attributi di qualità) che espliciti(di natura
tecnica).
(Vedere esempi di requisiti sulle slide)
40
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Tra tutti i requisiti non funzionali impliciti, un valido tentativo di mettere ordine è dato dal modello
FURPS+(Funzionalità, Usabilità, Affidabilità,Prestazione, Supportabilità)
Il + rappresenta le diverse categorie di requisiti.
Questo modello categorizza i requisiti non funzionali e li suddivide nelle seguenti quattro macro-categorie:
 Requisiti di progettazione;
 Requisiti di implementazione;
 Requisiti di interfaccia,
 Requisiti fisici.
Si utilizza quindi questo modello per caratterizzare le varie fasi del ciclo di vita del software.
Prendiamo quindi i 5 attributi di qualità che il FURPS+ identifica:
 Funzionalità ad esempio in un sistema di gestione di un magazzino i requisiti funzionali possono
essere il controllo delle scorte o l’elaborazione degli ordini.
Vedere tabella di requisiti funzionali sulle slide.
 Tra gli URPS troviamo:
 Usabilità, l’aspetto di qualità più soft, meno tecnica, è la caratteristica di qualità su come il sistema
si presenta.
 L’affidabilità, sono le caratteristiche come la disponibilità,riguarda come il sistema è preciso,
accurato e come è in grado di ripristinarsi.
 Prestazioni, riguarda aspetti come il tempo di troughput, di risposta, di recupero, di avvio ecc.
 Supportabilità, studia aspetti come configurabilità, adattabilità, scalabilità. L’adattabilità dipende
dall’hardware
 Il + invece raggruppa le quattro categorie di requisiti.
I requisiti di implementazione si occupano di linguaggi, di codifica e vincolano o specificano la costruzione
di un sistema.
I requisiti fisici, sono quelli che specificano come deve essere fatto l’hardware sottostante.
Per esempio se dico che voglio un requisito di persistenza, posso tradurlo in un meccanismo in cuoi voglio
utilizzare il DBMS.
Se voglio un requisito di comunicazione, si traduce dicendo che voglio che la comunicazione si realizzi con
un broker o con un meccanismo di messagging, a livello pratico posso usare due meccanismi.
(Vedere tabelle su usabilità, reliability, performance e supportability da slide)
Il FURPS+ fa parte di una categoria di modelli detti modelli strutturati, tra cui l’ultimo modello più
importante è il modello ISO 9126. Questi tipi di modelli sono strutturati in livelli, al primo livello si trova
sempre l’insieme delle caratteristiche, e poi nei livelli successivi le vado a dettagliare fino ad arrivare
all’ultimo livello dove si trovano sempre le metriche, ossia il meccanismo dove si fanno dei calcoli su alcuni
aspetti del sistema che permettono di valutare la qualità del sistema.
Il modello ISO è quello più importante ed utilizzato, si compone di quattro aspetti.
Nel primo vengono definite le 6 caratteristiche più importanti che poi vengono suddivise in 27
caratteristiche. Nelle altre tre parti abbiamo la definizione di metriche di qualità esterna, interna e in uso.
La qualità pertanto viene scomposta in tre aspetti e anche gli attributi di qualità sono raggruppabili in una
di queste categorie. La qualità in uso o percepita rappresenta l’efficacia del sistema, quella interna misura
come il sistema possiede una serie di attributi che lo caratterizzano, quella esterna valuta il sistema come
una black box da testare.
41
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
Dati i modelli di qualità ci poniamo l’obiettivo di valutare la qualità del sistema. Come faccio? Per esempio
con un modello orientato all’obiettivo. Cominciamo a definire le metriche e a vedere cosa sono. “Una
metrica è una misura quantitativa del grado in cui un sistema possiede un determinato attributo”.
Un modello orientato all’obiettivo è il GQM, ossia un modello che a partire da dei GOAL da raggiungere e
verificare, mediante opportune Question permette di individuare delle metriche che misurano uno o più
parametri che permettono la soddisfazione di alcune specifiche di progetto.Costruisco poi un foglio detto
foglio metrico, diviso in quattro parti che mi serve per organizzare la valutazione che sto facendo.
Oggetto dello studio Scopo
Prospettiva Punti di Vista Contesto
Quality Focus
Variation Factors
descrive la relazione tra i fattori di
contiene i quesiti e le metriche per
variazione e le metriche del quality
la conformità del processo o della
focus
caratterizzazione del prodotto
Baselines Hypothesis
Impact on Baseline Hypothesis
contiene i quesiti e le metriche
descrive la relazione tra i fattori di
dei modelli di conferma e di
variazione e le metriche del quality
validità
focus
Vediamo le metriche più diffuse e conosciute:
 Metriche per il modello analitico
 Metriche per il modello progettuale:
 Metriche dei punti funzione.
 Metriche CK;
 Metriche Mood.
 Metriche per il codice sorgente.
Studiamo nello specifico le metriche Ck e le metriche Mood. Essi sono due insiemi di metriche che ci
misurano gli stessi aspetti, più o meno nove aspetti diversi che secondo Whitmare sono i più rilevanti per
dare una caratterizzazione di un progetto orientato agli oggetti.
Vediamo quali sono queste caratteristiche:
1. Dimensioni;
2. Complessità;
3. Accoppiamento;
4. Sufficienza
5. Completezza, è un parametro implicito. Insieme di caratteristiche rispetto a cui vogliamo
confrontare l’astrazione o il componente.
42
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
6. Coesione, aspetto molto importante misurabile legato in maniera inversa all’accoppiamento. Infatti
quanto più due parti sono lascamente accoppiate tanto più alta sarà la coesione interna di
ciascuno. Se la Classe A ha poche interazioni con la classe B, sicuramente al suo interno è altamente
coesa;
7. Primitività, ci dice quanto un’operazione è atomica;
8. Similarità;
9. Volatilità: misura della probabilità che si verifichi una modifica.
Di queste caratteristiche quelle più significative sono dimensione, Complessità, accoppiamento e coesione.
Vediamo la categoria delle metriche CK, acronimo dei due ideatori.
La prima delle metriche di questo test è quella dei metodi pesati per classe (WMC=Weighted Method per
Class).
La formula corrispondente è la seguente:
WMC = Σ ci
i=1,...,n
Supponiamo di avere n metodi ciascuno di complessità c1…cn , la metrica è ottenuta come sommatoria
delle ci al variare di n. Il problema quindi sta nel valutare la complessità del metodo, e per fare ciò si
utilizzano altre metriche. La metrica utilizzata è quella della complessità ciclomatica (VG(c)), una misura che
ci calcola sul grafo di controllo il numero di link all’interno del grafo. Posso eventualmente utilizzare anche
l’insieme dei metodi implementati nella classe(Mim(c)).
Il valore del WMC deve essere basso.
La seconda misura è il DIT , ossia la profondità dell’albero di ereditarietà, che misura quanto un nodo dista
dalla radice dell’albero di ereditarietà. E’ preferibile che la profondità dell’albero sia bassa.
La terza misura è il numero di figli (NOC), ossia il numero di sottoclassi figlie di una superclasse, può essere
alto ma è sempre preferibile che sia basso. Al crescere di questa misura, cresce anche il numero di casi test
da effettuare.
La quarta misura è data dalle risposte per classe, ossia il numero di metodi che possono essere eseguiti in
risposta ad un messaggio ricevuto da un oggetto della classe. Il suo valore deve essere basso.
La quinta misura è l’accoppiamento, ossia il numero di collaborazioni tra classi. Si può avere
l’accoppiamento anche tra altre parti software. Più il valore è basso, più la classe è indipendente e quindi
riusabile.
Sesta misura: LCOM( Lack of Coesion in Methods), ossia mancanza di coesione nei metodi. Questo
parametro deve essere basso.
La seconda famiglia di metriche ha più o meno metriche che valutano gli stessi parametri, è stata realizzata
nel 1998 e sono le metriche MOOD.
LE metriche sono le seguenti:
1. MIF, fattore di ereditarietà del metodo. Mi da un’indicazione sulla manutenibilità. La sua formula è
la seguente:
MIF 
 M (C )
 M (C )
i
i
a
i
43
Prof.ssa Mongiello
Vinci Federica
Ingegneria del software
Politecnico di Bari
2. Fattore di accoppiamento :
 is _ client (C , C )
i
CF 
i
j
j
Tc  Tc
2
Deve essere basso .
Poi abbiamo le metriche di Laurence e Kidd (1994), basate su quattro grandi categorie: dimensione
della classe (CS) in termini di numero di metodi e/o attributi, e il suo valore non deve essere né troppo
alto né troppo basso; il NOA,ossia il numero di operazioni aggiunte da una sottoclasse e deve avere
comunque un valore contenuto.
Ultima categoria di metriche è quella delle metriche sul codice sorgente.
In questa categoria si hanno misure del tipo lunghezza del programma, linguaggio, volume ecc ecc…
Vedere esempio sulla valutazione di un sistema software dalle slide “TEST” dalla pagina 87 fino alla fine.
La tavola di decisione è la tabularizzazione di un albero decisionale. Cosa è un albero? Un albero è un
grafo orientato privo di cicli. La seconda definizione è quella che richiama il principio di induzione.
Quindi l’albero è una struttura ricorsiva.
Nella tavola decisionale, per ogni condizione, specifico come voglio che siano le soglie rispetto al valore
atteso.
44
Prof.ssa Mongiello
Vinci Federica