Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ......

37
Progetto Ingegneria del Software Maze di Cerretani Giacomo – Cesca Giacomo – Pazzaglia Mirco

Transcript of Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ......

Page 1: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

Progetto Ingegneria del Software

Mazedi

Cerretani Giacomo – Cesca Giacomo – Pazzaglia Mirco

Page 2: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello
Page 3: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

Indice1. Introduzione..................................................................................................................................12. Descrizione del problema.............................................................................................................13. Requisiti....................................................................................................................................... 1

3.1 Requisiti Funzionali................................................................................................................23.2 Requisiti Non Funzionali........................................................................................................2

4. Analisi........................................................................................................................................... 34.1 Gellish....................................................................................................................................34.2 Alloy.......................................................................................................................................54.3 UML (1)..................................................................................................................................8

4.3.1 Use Case Diagram.........................................................................................................84.3.2 Activity Diagram............................................................................................................11

5. Progettazione.............................................................................................................................135.1 UML (2)................................................................................................................................13

5.1.1 Class Diagram..............................................................................................................135.1.2 Design Pattern..............................................................................................................155.1.3 OCL..............................................................................................................................185.1.4 Sequence Diagram.......................................................................................................205.1.5 Package Diagram.........................................................................................................23

5.2 Petri Net...............................................................................................................................236. Implementazione........................................................................................................................26

6.1 JML......................................................................................................................................266.2 UML (3)................................................................................................................................28

6.2.1 Deployment Diagram....................................................................................................287. Test............................................................................................................................................. 29

7.1 Junit.....................................................................................................................................298. Conclusioni.................................................................................................................................319. Appendice..................................................................................................................................32

9.1 Screenshot del programma..................................................................................................329.2 Programmi utilizzati..............................................................................................................339.3 Fonti.....................................................................................................................................339.4 Ringraziamenti.....................................................................................................................33

Page 4: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello
Page 5: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

1 Introduzione

1 IntroduzioneQuesta è una relazione orientata agli esempi. Lo scopo di questo documento è quello di

fornire una linea guida, seppur di base, sull'esistenza e l'utilizzo di particolari strumenti adatti per l'analisi e lo sviluppo del software. Cercando un approccio più sul piano pratico che su quello teorico abbiamo ripercorso tutte le fasi che hanno portato un software dalla sua nascita alla sua completa funzionalità. Ovviamente per non rendere ripetitiva la descrizione degli strumenti abbiamo selezionato per le fasi di analisi, progettazione, implementazione e test, esclusivamente gli esempi più utili ed educativi, rinunciando quindi a riportare la totalità della documentazione prodotta.

Chiaramente questa relazione non ha la presunzione di voler rimpiazzare nessun manuale su alcuno degli strumenti che andremo ad osservare ma solo di fornire una visione panoramica di questi tool ingegneristici attraverso degli esempi che ne possano rendere più immediata la comprensione.

2 Descrizione del problemaIl progetto che useremo come esempio ci è stato commissionato dal Museo di Camerino.

La richiesta è stata quella di realizzare un programma applicativo che su richiesta dell'utente generasse casualmente un labirinto di dimensioni variabili e con un numero altrettanto variabile di ostacoli. Nel labirinto l'utente deve poter liberamente posizionare un “pedone” (tranne ovviamente che nelle caselle con gli ostacoli). Questo programma ha come scopo didattico quello di mostrare la risoluzione di tale rompicapo in maniera grafica muovendo il pedone in cerca di uscita passo dopo passo, sia che il labirinto presenti o meno l'uscita. Alla fine, il numero di passi impiegati per uscire per ognuno degli algoritmi andava mostrato a video. L'utente infatti avrebbe dovuto scegliere tra tre diversi tipi di algoritmo per cercare l'uscita: un algoritmo sequenziale, uno parallelo ed un goloso (greedy). Lo scopo principale di questo progetto è infatti quello di far comprendere attraverso un modo semplice ed intuitivo la differenza tra i tre algoritmi a bambini e ragazzi di varie età in visita presso il museo.

Ci è stato richiesto che il programma fosse scritto in Java per migliorarne la portabilità, e che il codice fosse “leggero”, veloce e performante anche su computer di medie prestazioni, ma soprattutto con un grafica che non fosse né troppo complicata da comprendere né troppo “vuota” da causare la quasi immediata perdita di concentrazione da parte del pubblico. In ultimo, poiché il computer su cui sarebbe stato mostrato è a diretto contatto anche con i visitatori, vi era la richiesta di inserire una shortcut segreta per chiudere l'applicazione anziché tramite la classica icona “X” sull'angolo in alto a destra della finestra, per evitare l'utilizzo improprio dell'attrezzatura del museo.

3 RequisitiIl primo passo da fare è individuare i requisiti del problema posto. In pratica, una volta che

si ha tutto il materiale in cui è descritto ciò che viene richiesto dal cliente (genericamente questo materiale è effettivamente presente dopo aver sottoposto il cliente ad un operazione chiamata “Intervista”), bisogna individuare precisamente quali sono gli obiettivi che il programma deve raggiungere, quali sono quelli più prioritari e quelli meno (utilizzando la notazione MoSCoW) dividendoli in due macro categorie: i requisiti funzionali e i requisiti non funzionali.

1

Page 6: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

3 Requisiti

3.1 Requisiti FunzionaliEssenzialmente si possono catalogare in questa categoria tutti i requisiti che rispondono a

queste domande: “Cosa il sistema deve e/o non deve fare?”, “Come deve reagire agli stimoli esterni?”. Ecco alcuni requisiti di esempio, sulla base della descrizione del problema fornita sopra.

ID Descrizione MoSCoW0 Il programma deve permettere la scelta della dimensioni del labirinto Must Have1 Il programma deve permettere la scelta del numero di ostacoli del labirinto Must Have2 Il programma deve permettere la creazione di nuovi labirinti casuali Must Have3 Il programma dovrebbe permettere il libero posizionamento del pedone

all'interno del labirinto.Should Have

4 Il programma deve permettere la risoluzione del labirinto attraverso un algoritmo sequenziale, un algoritmo parallelo o un algoritmo goloso

Must Have

5 Il programma deve rappresentare la risoluzione di un labirinto in maniera grafica

Must Have

6 Il programma deve mostrare i passi utilizzati dal pedone per risolvere il labirinto

Must Have

7 Il programma deve avere una scorciatoia di chiusura nascosta al pubblico Must Have… … ...

3.2 Requisiti Non FunzionaliI requisiti che invece definiscono le proprietà del sistema che devono essere soddisfatte

sono inclusi in questo gruppo. Ecco quindi alcuni requisiti di esempio, basati sulla descrizione del problema fornita sopra, per capire meglio questa tipologia di requisiti.

ID Descrizione MoSCoW15 Il programma deve essere sviluppato in Java Must Have16 Le risorse del sistema potrebbero essere limitate Could Have17 Il programma dovrebbe essere veloce Should Have18 Il programma deve avere una grafica “accattivante” Must Have… … ...

Nota: la colonna MoSCoW (must-should-could-would), sia nella tabella dei requisiti funzionali che in quella dei requisiti non funzionali, definisce l'importanza che ogni requisito possiede all'interno del sistema.

2

Page 7: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

4 AnalisiIn questa fase andremo ad utilizzare tre strumenti che ci permetteranno di eliminare le

ambiguità di comprensione dei termini, di iniziare a definire il dominio del programma che si andrà a sviluppare, di stabilire quali sono le attività che l'utente può fare attraverso il sistema e quindi di creare i primi prototipi di algoritmo che verranno successivamente implementati.

4.1 GellishGellish è un “dizionario intelligente”. Attraverso questo strumento, definito in due ISO, è

possibile eliminare le ambiguità del linguaggio specialistico utilizzato nel dominio dell'applicazione. Gellish infatti non è altro che un grande dizionario basato sul linguaggio naturale (per ognuno di esso esiste una variante Gellish). Con i termini definiti al suo interno se ne possono definire altri attraverso la generica tupla <termine1, relazione, termine2> che si può leggere: “il termine1 è collegato al termine2 attraverso la relazione”.

Ogni termine ed ogni relazione presenti nei vari dizionari Gellish sono standard e codificati tramite un codice univoco; questo permette di tradurre ogni nuova definizione espressa come indicato sopra in qualsiasi lingua possieda un Gellish Dictionary. In ultimo, ma non per minor importanza, l'indicizzazione appena descritta e la forma di relazione tra due termini rende le informazioni comprensibili ai computer senza necessità di alcuna codifica.

A seguire, un esempio di utilizzo di Gellish che mostra come abbiamo definito alcuni dei termini del nostro dominio di applicazione.

(l'immagine qui sopra è da considerarsi con l'immagine seguente allineata alla sua destra)

3

Page 8: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

(l'immagine qui sopra è da considerarsi con l'immagine seguente allineata alla sua destra)

(l'immagine qui sopra è da considerarsi con l'immagine seguente allineata alla sua destra)

Notare ad esempio la definizione di “Maze” realizzata in Gellish attraverso quattro diverse relazioni espresse nelle ultime quattro righe della tabella sopra proposta. La definizione del termine “Maze” è data da tutte le righe che lo riguardano. Una di queste quattro, ad esempio, è composta da: <maze> <is made of> <obstacle> : come spiegato sopra la relazione “is made of” collega i due termini “maze” e “obstacle” spiegando in maniera non ambigua che “un labirinto è fatto da ostacoli”; la colonna seguente offre la possibilità di inserire anche una definizione in linguaggio naturale per rendere l'espressione precedente più comprensibile per l'essere umano.

4

Page 9: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

4.2 AlloyAlloy è un linguaggio utilizzato per il controllo di modelli espressi nella forma della Logica

del Primo Ordine (FOL). Lo strumento Alloy viene utilizzato in fase di analisi per generare degli scenari d'esempio (modelli) da somministrare al cliente per verificare se i vincoli ed i domini tratti dalle precedenti interviste sono esatti e completi. Con questo linguaggio è possibile definire delle signature (sig) ossia dei domini di elementi. All'interno di ogni sig si possono specificare le eventuali relazioni con altri elementi di altre signature o, eventualmente, con se stessa. Una volta definiti gli insiemi di elementi che entrano in gioco nel sistema, si possono definire i fatti (fact) ossia dei postulati sempre veri o dei predicati (pred) per vincolare il sistema. Inoltre il sistema offre la possibilità di “verificare” delle asserzioni (assert) specifiche per testare la bontà del modello creato attraverso la direttiva check, la quale cerca dei controesempi (se esistono) per smentire l'asserzione postagli. In questo linguaggio esistono anche numerose parole chiave per modificare la cardinalità delle relazioni e poter creare relazioni multiple (set), o per limitarle ad una singola (one). Offre anche un buon numero di comandi per le operazioni su insiemi come ad esempio la cardinalità (come #( elements )), operazioni relazionali tra numeri (come <, >, =, <=, >=, !=) ed operatori logici (come implies, iff).

Abbiamo quindi modellato la realtà del sistema utilizzando Alloy. Nell'esempio abbiamo lasciato gran parte dei fatti sviluppati per fornire esempi sulla sintassi e sulla modalità di utilizzo di questo strumento. Inoltre sono presenti, sotto forma di commento, anche una assert con relativo comando check.

open util/integer

sig Maze { Map : set Cell, Width : one Int, Height : one Int, nObstacles : one Int, Player : set Pawn}

sig Cell { }

sig Pawn { Position : one Point, State : set Status, Clone : set Pawn}

sig Status { }

sig Point { X : one Int, Y : one Int}

//Fatto A : in ogni Maze la cardinalità di Map deve essere// esattamente uguale al prodotto dei suoi due attributi// Width e Heightfact A { all m : Maze | #(m.Map) = mul [ m.Width , m.Height ] }

//Fatto B : il labirinto deve essere quadratofact B { all m : Maze | m.Width = m.Height }

//Fatto C : in ogni Maze il numero di ostacoli (nObstacles) deve sempre// essere al massimo la cardinalità del rispettivo Map - 2 e al minimo 0fact C { all m : Maze | m.nObstacles > -1 and m.nObstacles < ( #(m.Map) - 2 ) }

5

Page 10: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

//Fatto D : in ogni Maze le rispettive Height e Width non devono// essere minori di 5 e maggiori di 50fact D { all m : Maze | m.Width >= 5 and m.Height >= 5 and

m.Width <= 50 and m.Height <= 50 }

//Fatto E : ogni Cell deve appartenere ad un Map (non devono esistere // elementi di Cell sfusi)fact E { all c : Cell | some m : Maze | c in m.Map }

//Fatto F : ogni Pawn deve appartenere ad un Maze (non devono// esistere elementi di Pawn sfusi)fact F { all p : Pawn | some m : Maze | p in m.Player }

//Fatto G : ogni Point deve appartenere ad un Pawn (non devono esistere// elementi di Point sfusi)fact G { all p : Point | some pa : Pawn | p in pa.Position }

//Fatto H : i valori di X e Y della Position di un Player devono sempre essere// maggiori o uguali a 0 e minori di Width e Height del Maze di riferimentofact H { all m : Maze | all p : m.Player.Position | p.X >= 0 and p.Y >= 0 and

p.X < m.Width and p.Y < m.Height }

//Fatto I : non possono esistere elementi di Status non collegati ad un elemento Pawn// (non devono esistere elementi Status sfusi)fact I { all s : Status | some p : Pawn | s in p.State }

//Fatto L : ogni oggetto Pawn deve avere sempre almeno uno statofact L { all p : Pawn | some s : Status | s in p.State }

//Fatto M : ogni Maze deve avere almeno un pedonefact M { all m : Maze | #(m.Player) > 0 }

//Fatto N : non devono esistere due o più pedoni contemporaneamente sulla stessa cellafact N { all disj p1 , p2 : Pawn |

(p1.Position.X = p2.Position.X implies p1.Position.Y != p2.Position.Y) or (p1.Position.Y = p2.Position.Y => p1.Position.X != p2.Position.X) }

//Fatto O : ogni Pawn non può avere più di 4 clonifact O { all p : Pawn | #(p.Clone) < 5 }

//Fatto P : nessun Pawn può essere clone di se stesso (ne dei suoi cloni)fact PSelf {all p : Pawn | p not in p.Clone }fact Pouter {all p : Pawn | p not in p.^Clone }

//Fatto Q : ogni Pawn non può essere clone di più di un Pawnfact Q { all p : Pawn | #(p.~Clone) <= 1 }

assert Bb{ all m : Maze | m.Width = 0 or m.Height = 0}// check Bb for 7 Int

//Forzo il sistema a costruirmi un labirinto di dimensioni 5x5pred dim{all m : Maze | m.Width = 5 and m.Height = 5 }

run dim for 7 Int , exactly 1 Maze , exactly 5 Pawn , 5 Point , 90 Cell , 5 Status

Notare infine nell'ultima riga l'utilizzo del comando run, con lo scopo di eseguire il predicato “dim” in cui obblighiamo ogni elemento di Maze ad avere dimensione 5x5.

Segue la rappresentazione di un modello risalente agli stadi iniziali dell'analisi in cui mancava il vincolo di dimensione minima pari a 5x5.

6

Page 11: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

7

Page 12: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

4.3 UML (1)Verranno ora presentati alcuni diagrammi dello standard UML (Unified Modeling

Language), basato sul paradigma object-oriented, con lo scopo di agevolare e dare sostegno in fase di analisi sia agli analisti che ai clienti. Si tratta infatti di diagrammi di facile comprensione anche a chi non si muove nel mondo dello sviluppo di un software ma pur sempre formali.

4.3.1 Use Case DiagramIn UML, gli Use Case Diagram (UCD o diagrammi dei casi d'uso) sono diagrammi dedicati

alla descrizione delle funzioni o servizi offerti da un sistema, così come sono percepiti e utilizzati dagli attori che interagiscono col sistema stesso.

Sono impiegati soprattutto nel contesto della Use Case View (vista dei casi d'uso) di un modello, e in tal caso si possono considerare come uno strumento di rappresentazione dei requisiti funzionali di un sistema.

Negli UCD entrano in gioco diverse entità:

• Il sistema che è rappresentato con un rettangolo, il quale definisce i limiti del sistema stesso.

• Gli attori che vengono rappresentati con degli "omini" stilizzati, i quali definiscono chi o cosa interagisce con il sistema (persone fisiche e/o altri software).

• Gli Use case, che vengono rappresentati con degli ellissi etichettati con il nome caso d'uso, i quali definiscono una funzione o un servizio offerto dal sistema.

Nello UCD da noi realizzato possiamo vedere come un utente si interfaccia con il sistema Labirinto. Nello specifico l'utente generico potrà effettuare tutte le operazioni ad esso collegate, ad eccezione della chiusura del programma che, come si può evincere dal diagramma sottostante, è una funzionalità eseguibile esclusivamente dall'amministratore.

8

Page 13: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

9

Page 14: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

10

Page 15: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

4.3.2 Activity DiagramL'Activity Diagram può essere utilizzato durante l'analisi del progetto per dettagliare un

determinato algoritmo definendo una serie di attività o flussi. L'Activity Diagram è spesso usato come modello complementare allo Use Case Diagram, per descrivere le dinamiche con cui si sviluppano i diversi use case e permette di modellare un processo come un insieme di nodi ed archi. La sua lettura va effettuata ponendo un token nel nodo iniziale e seguendo il suo flusso fra gli altri nodi fino a giungere in un nodo finale. I principali tipi di nodo possono essere:

• Nodo di inizio attività, rappresentato da un pallino pieno. E' il punto di partenza per l'attività che si vuole rappresentare con il diagramma.

• Nodo di azione, rappresentato da un rettangolo contenente un'etichetta. Sta a significare l'azione da svolgere quando raggiunto dal token.

• Nodo di decisione, rappresentato da un rombo ed etichettato da una condizione. Stabilisce un set di percorsi possibili per il token che lo raggiunge. Il token fluirà attraverso solo uno degli archi sulla base del condizione imposta.

• Nodo di riunione (merge), rappresentato da un rombo senza etichette. Ricongiunge un percorso precedentemente diviso da un nodo decisionale.

• Nodi di fork e di join rappresentati da una sbarra. Quando vi è un arco entrante e più uscenti, ci si trova in una situazione di fork, nel caso inverso ci si trova in una sitauzione di join. In una fork il token da vita ad un numero di token pari al numero di archi uscenti dal nodo che procederanno l'uno indipendentemente dall'altro sulle proprie linee di flusso in via del tutto parallela. In un join, al contrario, le attività di più token convergeranno sincronizzando l'attività dei vari flussi.

• Nodo finale, indicato da un pallino pieno cerchiato. Quando un token giunge su questo nodo vuol dire che l'intera attività è giunta a conclusione.

Il seguente Activity Diagram fa riferimento alla fase di analisi dell'algoritmo sequenziale. Avendo presenti le definizioni di nodo ed arco scritti in precedenza, questo diagramma risulta di facile lettura per il cliente e come buon punto di riferimento per gli sviluppatori che andranno ad implementare l'algoritmo.

11

Page 16: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

4 Analisi

12

Page 17: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

5 ProgettazioneStabilito nelle fasi analisi e studio dei requisiti quanto più dettagliatamente e chiaramente

possibile quello che il cliente vuole dal software, giunge il momento di porre le basi concrete per lo sviluppo. Si sta infatti passando dalla comprensione della richiesta alla fase di produzione e per far ciò si ricorre all'utilizzo di particolari strumenti, alcuni dei quali presenti nello standard UML. In questa fase si andrà ad espandere il materiale prodotto nelle fasi precedenti con quello specifico della progettazione. Una buona progettazione implica una maggior sicurezza in fase di implementazione, portando alla produzione di codice più robusto, adattabile, scalabile e tollerante a possibili modifiche e/o aggiornamenti, minimizzando al contempo le possibilità di errore e facilitando la collaborazione fra membri del team di sviluppo.

5.1 UML (2)In questa sezione faremo ricorso a nuovi strumenti UML in aggiunta a quelli del paragrafo

4.3 . Questa volta il livello di dettaglio sarà maggiore poiché ci si sta avvicinando sempre di più all'implementazione, in modo tale da poter porre basi migliori per lo sviluppo ed eventualmente poter sfruttare i potenti strumenti C.A.S.E. (per la generazione automatica di codice).

5.1.1 Class DiagramI diagrammi delle classi (class diagram) sono uno dei tipi di diagrammi che possono

comparire in un modello UML. In termini generali, consentono di descrivere tipi di entità, con le loro caratteristiche, funzioni e le eventuali relazioni fra questi tipi. Gli strumenti concettuali utilizzati sono l'idea di classe del paradigma object-oriented e altri correlati (per esempio la generalizzazione, che è una relazione simile al meccanismo object-oriented dell'ereditarietà).

Nel nostro class diagram si possono identificare cinque entità principali che sono:

• Maze, che rappresenta il labirinto con le sue caratteristiche e funzionalità

• Pawn, che rappresenta il pedone che percorrerà il labirinto

• Solver, che è il vero e proprio "cervello" di tutta l'applicazione. In relazione di aggregazione con Solver, si trovano sia Pawn che Maze; entrambi verranno infatti sfruttati nel processo di computazione, muovendo la pedina (o le pedine nel caso di algoritmo parallelo) nello specifico labirinto. Dovendo specializzare il programma nell'esecuzione dei tre algoritmi citati nei requisiti funzionali(sequenziale, parallelo e greedy), abbiamo deciso di creare tre specializzazioni del solver che implementassero appunto i tre algoritmi, aggiungendo quindi le opportune funzionalità rispetto a quelle già presenti nel solver.

• GUI, che rappresenta l'interfaccia grafica che utilizzerà l'utente, è stata pensata e realizzata in modo tale da essere completamente indipendente dal resto del programma anche in visione di future modifiche sul metodo di interazione con l'utente. Questo ci è stato reso possibile dall'uso di uno specifico design pattern (observer) che spiegheremo nel paragrafo successivo.

• Parallel Controller, a cui è assegnato il compito di gestire e controllare la molteplicità di pedoni generati durante l'esecuzione dell'algoritmo parallelo.

13

Page 18: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

14

Page 19: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

5.1.2 Design PatternIn questa fase progettuale abbiamo deciso di sviluppare il nostro programma

implementando quattro design pattern differenti. I design pattern sono infatti delle classi strutturate tra loro in modo tale da ottenere determinate caratteristiche implementative e/o per aggiungere particolari funzionalità al programma, avendo comunque la certezza che non venga compromessa la funzionalità dell'intero sistema. I design pattern si dividono in tre tipologie: creazione, struttura e comportamento. In particolare i design pattern da noi utilizzati sono i seguenti:

Singleton

Questo particolare design pattern di creazione ci ha permesso di rendere la classe Maze a singola istanza ciò significa che durante l'esecuzione del programma non sarà possibile istanziare più di un oggetto di tipo Maze. Questo è stato fatto per impedire l'esecuzione concorrente di più algoritmi su più labirinti cosa che avrebbe reso il sistema instabile e logicamente incomprensibile.

Prototype

15

Page 20: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

Anche questo è un design pattern di creazione (come quello visto sopra). Abbiamo implementato la classe “Pawn” con questa struttura per poter sfruttare la sua funzionalità di clonazione che quindi rende l'istanziazione di un nuovo oggetto di questo tipo molto più leggera e veloce. La clonazione, infatti, annulla i costi di accesso al disco che sarebbero stati necessari per caricare ogni volta la grafica di un pedone clonandola direttamente da un'istanza già presente in memoria.

Template Method

A differenza dei primi due, questo design pattern è di tipo comportamentale. Abbiamo sintetizzato tutti i comportamenti comuni nel processo risolutivo degli algoritmi in un'unica classe astratta implementandoli all'interno di metodi e lasciando invece i “passi risolutivi” differenti di ogni algoritmo in metodi astratti che poi verranno implementati dalla classe che li erediterà.

16

Page 21: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

Observer

Anche questo come il precedente è un design pattern di comportamento. Lo abbiamo implementato per rendere il risolutore indipendente dall'interfaccia grafica. Infatti il risolutore durante la sua esecuzione non deve chiamare al suo interno metodi della GUI ma solo il suo metodo notify() che si preoccuperà di “informare” la GUI (Graphic User Interface) che ci sono degli eventi da visualizzare all'utente. Si noti come il pattern observer è stato utilizzato inglobando al suo interno il pattern Template Method. Questo è un esempio molto importante di utilizzo dei design pattern poiché mostra come possano venire utilizzati gli uni insieme agli altri. L'utilizzo dei design pattern non è infatti mutualmente esclusivo.

17

Page 22: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

5.1.3 OCLL'Object Constraint Language, o OCL, è un linguaggio di specifica formale che fa uso della

logica del primo ordine. Questo permette di imporre vincoli su specifiche operazioni definite in altri diagrammi dello standard UML. E' infatti possibile aggiungere l'OCL direttamente nei diagrammi sotto forma di annotazione o, come nel caso che segue, riportarlo in un documento separato. Normalmente, prima di porre vincoli OCL è bene avere un'idea chiara delle classi che comporranno il progetto, quindi, dei loro metodi ed attributi principali. L'OCL è uno strumento complementare a qualunque diagramma ed è utilizzato per dare un'indicazione di come si comporteranno i metodi, cosa e come andranno a modificare, quali valori potranno assumere gli attributi e così via.

Nel progetto del labirinto diverse informazioni acquisite nel corso dell'analisi hanno avuto necessità di essere espresse come vincolo aggiuntivo ai diagrammi. Riprendendo il codice Alloy del capitolo 4.2 si possono notare delle analogie tra i fatti allora discussi ed i vincoli imposti tramite OCL nell'attuale fase di progettazione.

// Maze

context Maze::Maze( Width : Integer, Height : Integer, Obstacles : Integer ) pre: Width = Height Obstacles >= 0 and Obstacles <= Width * Height - 2

In questo contesto andiamo ad imporre che tratteremo solo labirinti di forma quadrata esattamente come nel Fatto B di Alloy. Imporremo anche che il numero di ostacoli nel labirinto dovrà sempre essere in numero maggiore di zero (sarebbe una situazione inconsistente in caso contrario) e in numero massimo tale per cui ci siano due posti liberi (punto di partenza ed uscita) come definito dal fatto C. Si potrebbe pensare che manchi un vincolo sulla dimensione del labirinto, come definito dal fatto D di Alloy. In realtà non è stato introdotto poiché in fase progettuale, con un occhio rivolto verso possibili future richieste del cliente, si è pensato che fosse opportuno puntare all'adattabilità del software per ogni evenienza.

context Maze::GetStatus( Position : Point ) : Boolean

pre: Position.X >= 0 and Position.X < self.Width Position.Y >= 0 and Position.Y < self.Height

post : if (one(self.field(Position.X,Position.Y)=1) then result = false else result = true

Come espresso dal fatto H, si vincola la ricerca dello stato di una cella del labirinto al range di celle possibili.

Attraverso la keyword post si specifica cosa ci si aspetta restituisca il futuro metodo. In questo caso ci si aspetta che in presenza di un muro (cioè un intero pari ad uno) ritorni un valore booleano di false; al contrario, in presenza di una strada percorribile, ritorni true.

// Pawncontext Pawn::status : Integer init: 0

In questo frammento OCL si va a specificare con quale valore iniziale dovrà presentarsi uno specifico attributo. Nello specifico, l'attributo "status" di Pawn avrà valore zero alla sua istanziazione.

18

Page 23: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

context Pawn inv: status >= 0 and status < icons->size()

In questo frammento di codice OCL si specifica un'invarianza (inv). Una invarianza è un'espressione che deve essere sempre rispettata durante tutta l'esecuzione dell'applicazione. Nel caso del labirinto si è reso necessario specificare che l'attributo status di Pawn non dovrà mai, per alcun motivo, superare in valore la lunghezza di icons. "icons" sarà un vettore di percorsi ad immagini su disco (sotto forma di stringhe), una per ogni stato possibile della pedina (pedina in direzione ovest, sud, est, nord, pedina addormentata e così via). "status" rappresenta invece lo stato corrente in cui si trova la pedina, ed è di fatto, l'indice con cui prelevare il path all'immagine nel vettore di "icons". A seguito di questa breve spiegazione dovrebbe risultare più chiaro il motivo per cui status non può, in quanto indice di un array, essere minore di zero o eccedere la sua dimensione.

context Pawn::Clone() : Pawn post: Pawn::allInstances()->size() = Pawn::allInstances()@ pre ->size()+1 self.position = result.position self.icons = result.icons self.status = result.status self.steps = result.steps

Con questa specifica OCL si vuole definire il comportamento della clonazione di una pedina. Ci si trova nel caso di esecuzione dell'algoritmo parallelo, in cui ogni pedina avanza per mezzo della clonazione. Il codice specifica che il numero di pedine a seguito dell'invocazione del metodo in questione dovrà essere incrementato di uno a partire dal valore che possedeva prima dell'invocazione. Si noti la presenza del suffisso-keyword "@pre" per indicare appunto il valore posseduto da una certa variabile prima dell'invocazione del metodo. Si noti inoltre l'uso di allInstances() per effettuare operazioni sull'intera collezione di istanze di quella classe.Seguono altri esempi di specifiche OCL.

// Solvercontext Solver::nSteps : Integer init: 0context Solver::pause : Boolean init: falsecontext Solver::solved : Boolean init: falsecontext Solver::Solve() : void post: if self.player.position.X@pre <> self.player.position.X or self.player.position.Y@pre <> self.player.position.y then self.nSteps = self.nSteps@ pre + 1 else self.nSteps = self.nSteps @pre

19

Page 24: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

5.1.4 Sequence DiagramUn altro diagramma fondamentale dell'UML è il Sequence Diagram. In questa nuova

rappresentazione vengono generalmente riproposti tutti quei flussi già esaminati negli Activity Diagram ma in maniera molto più approfondita e più vicina a quella che sarà poi la reale stesura dell'algoritmo. Inoltre questo diagramma offre una visione di come differenti oggetti collaborino all'interno di uno stesso flusso per il raggiungimento di uno scopo comune. In esso si riportano tutti gli attori e i sistemi che hanno un “ruolo” nel flusso che si vuole rappresentare. Da questi elementi, che sono disposti l'uno di fianco all'altro, vengono poi fatte partire delle linee tratteggiate perpendicolari che rappresentano le “lifelines” (le linee della vita) di ognuno. Si passa poi a mostrare i “messaggi”, disegnati mediante delle frecce orizzontali orientate che collegano le lifelines di due elementi (non necessariamente distinti), che hanno come descrizione i nomi dei metodi che vengono invocati. Questi messaggi scatenano l'esecuzione dei metodi da loro riferiti sugli elementi puntati: le vite di questi metodi vengono rappresentate mediante dei rettangoli che si sovrappongono alle rispettive lifeline. Chiaramente da ogni rettangolo possono partire altre frecce che a loro volta genereranno altri rettangoli in altri elementi del diagramma o su se stessi in caso che la freccia si riferisca allo stesso elemento che l'ha scaturita. Il fatto che un rettangolo ritorni un valore al rettangolo che l'ha generato si esprime attraverso una freccia tratteggiata di verso opposto a quella che ha dato vita al metodo stesso.

20

Page 25: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

Nel Sequence Diagram seguente, si mostra il flusso rappresentato dall'Activity Diagram del capitolo precedente mostrando l'attore che scatena l'esecuzione dell'algoritmo sequenziale (:User) attraverso la chiamata della funzione Sequential() all'oggetto di tipo GUI. Quest'ultimo, quindi, crea l'oggetto di tipo Sequential attraverso la freccia “«create»” e poi sull'elemento appena creato invoca il metodo Run(). All'interno di questo metodo l'oggetto di tipo Sequential invoca la sua stessa funzione Solve() (notare come il rettangolo rappresentante la vita del metodo Solve si sovrappone al rettangolo rappresentante la vita del metodo Run che lo ha invocato). Viene quindi invocato, dal metodo Solve, il metodo ChooseDirection() dal quale parte un messaggio verso l'oggetto di tipo Maze sul quale scatena la funzione GetStatus(dest: Point) che al termine ritorna, attraverso una freccia tratteggiata, all'oggetto di tipo Sequential. Quest'ultimo invoca il metodo Move(dest: Point) sull'oggetto di tipo Pawn e poi effettua un chiamata su se stesso che sappiamo essere una chiamata ricorsiva.

In UML 1 un Sequence Diagram poteva solo riportare flussi in cui ogni “decisione” era stata presa a priori e quindi non poteva rappresentare “salti” (if-then-else) o “cicli” (do-while). Con l'UML 2 è invece possibile rappresentare anche questo genere di istruzioni. Ad esempio, attraverso l'operatore “alt” si può rappresentare un salto condizionato (il costrutto if-then-else), oppure tramite l'operatore “par” si possono descrivere due porzioni di codice che verranno eseguite in parallelo o ancora con l'operatore “loop” si possono definire i cicli delimitati da guardia (come il costrutto while).

21

Page 26: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

Per mostrare questo nuovo tipo di funzionalità implementate dall'UML 2.0 abbiamo deciso di riportare il Sequence Diagram che descrive ciò che succede quando, durante l'esecuzione di Sequential, l'utente preme il tasto di “Play/Pause” per pausare o riprendere la risoluzione del labirinto. Quando l'attore “:User” lancia il metodo “PlayPause()” sull'oggetto di tipo GUI si entra nel frammento combinato definito dall'operatore “alt” per specificare un costrutto, come detto sopra, di tipo if-then-else. Questo frammento infatti controllerà “se paused = false allora l'oggetto di tipo GUI invocherà il metodo SetPaused(true) sull'oggetto di tipo Sequential altrimenti l'oggetto di tipo GUI invocherà il metodo SetPaused(false) sull'oggetto di tipo Sequential”.

22

Page 27: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

5.1.5 Package DiagramIl Package Diagram in UML descrive le dipendenze che ci sono tra i vari pacchetti che

definiscono il modello. Come per gli altri diagrammi UML anche per il Package Diagram esistono le relazioni che fanno da legame tra un package ed un altro. Nel nostro caso abbiamo legato i tre pacchetti da relazioni di uso e da relazioni di chiamata. Come già detto in precedenza la GUI risulta indipendente rispetto al core del programma, mentre il solver e il labirinto sono strettamente legati tra di loro, perciò risiedono entrambi nello stesso package Core, legati da una relazione d'uso.

5.2 Petri NetLa Rete di Petri è un formalismo utilizzato per descrivere l'evoluzione di un sistema

concorrente. Lo spostamento di unità chiamate “token” da un nodo, detto “piazza”, ad un altro attraverso delle “transizioni” riesce infatti a descrivere l'evoluzione di qualsiasi “processo”, che esso sia semplicemente sequenziale oppure parallelo. In questa relazione presentiamo due esempi di Reti di Petri utilizzate per modellare due aspetti, entrambi con esecuzione concorrente, del nostro progetto.

Nella prima rete (quella nell'immagine seguente) viene modellata la realtà riguardante l'esecuzione di qualsiasi algoritmo di risoluzione contemporaneamente alla gestione del comando di pausa presente nella GUI. In pratica dalla piazza “Start” parte un token che si sdoppia mandando un token alla piazza “Play” (per la gestione della pausa) ed un token alla piazza “Execute” (che rappresenta l'esecuzione di un algoritmo di risoluzione). Grazie alla

23

Page 28: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

transizione “Check Play/Pause” che richiede un token da ognuna delle due piazze definite sopra, obblighiamo il sistema a poter proseguire nella risoluzione e quindi nella rappresentazione solo se, appunto, c'è un token nella piazza di “Play”: infatti se il token dalla suddetta piazza fosse passato alla piazza “Pause” la transizione non potrebbe avere luogo e questo obbligherebbe l'esecuzione a fermarsi fintanto che il token presente nella piazza “Pause” non ritorni nella piazza “Play”. Ogni volta che ha luogo l'esecuzione, l'opzione di mettere in pausa il programma ritorna nuovamente disponibile solo quando dalla piazza di “Draw” il token scatta attraverso la transizione “Next Iterate” riportando quindi la rete nella sua configurazione iniziale. In ultimo quando il token passa dalla piazza “Draw” alla piazza “End” l'esecuzione dell'algoritmo termina.

Nella seconda rete (quella riportata sotto) mostriamo l'interazione tra la classe Parallel e la classe ParallelController durante la risoluzione di un labirinto mediante l'algoritmo parallelo. Dalla piazza “Start” parte un token che attraverso la transizione “Initializing” si sdoppia e va nella piazza “ParallelController” e nella piazza “Thread Creator”. Dalla piazza ParallelController il token, nella sua prima iterazione, è obbligato ad andare nella transizione “Launching Threads” (in quanto per la transizione “Finalizing” sarebbero richiesti due token). Launching Theads manda un token ad ognuno degli N thread nelle rispettive piazze “Thread x Exec”. Da qui in poi, ogni thread dovrà spostarsi dalla piazza di Exec alla piazza di “Thread x Terminate” attraverso la rispettiva transizione “Drawing x”; questa però potrà scattare solo quando la piazza “Graphic Elaborator”, che rappresenta l'unità di elaborazione grafica del computer e che quindi può lavorare ad una sola “stampa” alla volta, possiederà il suo token (che rappresenta la possibilità dell'unità grafica di elaborare); in questo modo abbiamo mostrato la mutua esclusione della risorsa grafica. Ogni volta che un token si sposta nella piazza “Thread x Terminate” può far scattare la rispettiva transizione “Notification x” che restituirà un token alla piazza dell'unità grafica, per permettere l'elaborazione di eventuali altri thread che attendono il loro turno, e manderà un altro token alla piazza comune “Sync Controller”. Soltanto quando tutti i thread avranno terminato, e quindi saranno presenti N token nella piazza suddetta, potrà scattare la transizione “Notification” (questo perchè il peso dell'arco entrante in questa transizione ha valore N) che manderà due token alla piazza ParallelController (perchè il peso dell'arco uscente è 2); a questo punto l'unica transizione che

24

Page 29: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

5 Progettazione

potrà scattare sarà “Finalizing” (perchè la piazza “ParallelController” possiede due token e perchè per far scattare di nuovo la transizione “Launching Threads” sarebbe necessario che in “Threads Creator” fosse presente il token già consumato ad inizio esecuzione) che porterà dunque la rete nella sua piazza finale denominata appunto “End”.

Nota: in questo secondo esempio sono rappresentati soltanto i cicli di tre thread rappresentando tutti gli altri attraverso “......” in ogni loro stato al fine di rendere la rete più comprensibile nella lettura e più chiara nel disegno.

25

Page 30: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

6 Implementazione

6 ImplementazioneDal momento che questa relazione è incentrata sulla dimostrazione delle tecnologie

utilizzabili nell'ingegneria del software l'implementazione, intesa come stesura del codice Java compilabile ed eseguibile, verrà tralasciata. Saranno invece presentati in questo capitolo strumenti “ausiliari” dell'implementazione come il JML ed i Deployment Diagram dell'UML.

6.1 JMLIl Java Modeling Language, abbreviato JML, è un linguaggio di specifica per Java con

comportamento simile a quello di OCL. Tramite le specifiche JML si impone che un certo metodo abbia un ben preciso comportamento, accetti parametri di un certo tipo e che svolga solo determinate operazioni. E' possibile sviluppare codice JML con il fine di lasciare l'implementazione a terzi con la sicurezza che (se le specifiche di partenza erano corrette) il codice sviluppato esegua realmente quanto stabilito in fase di progettazione. JML è quindi sia strumento di controllo che di documentazione sul comportamento delle classi (e loro metodi ed attributi) per i programmatori, siano essi interni o esterni al team di progettazione.

Quelli che dapprima erano fatti Alloy in fase di analisi e successivamente specifiche OCL in fase di progettazione, sono ora specifiche per il linguaggio JML, di facile lettura e comprensione per programmatori Java.

public class Maze{ private /*@ spec_public @*/ int width; private /*@ spec_public @*/ int height; private /*@ spec_public @*/ int obstacles; private /*@ spec_public @*/ int[][] field; private /*@ spec_public @*/ int nSteps;

...

/*@ @ requires Width == Height @ requires Obstacles >= 0 && Obstacles <= Width * Height – 2 @ @ ensures nStpes == 0 @*/

private Maze(int Width, int Height, int Obstacles) { ... }

In questo primo stralcio di codice si forza il metodo Maze a fare controlli sulla validità dei parametri passatigli, secondo quanto già discusso in Alloy ed OCL. Si noti che per accedere a d attributi definiti in Java come private, va modificata la loro visibilità a livello JML tramite la specifica /*@ spec_public @*/. Questo è per il compilatore Java alla stregua di un commento ed in quanto tale, completamente ignorato. Si esplica inoltre che il costruttore dovrà occuparsi della corretta inizializzazione degli attributi. Nello specifico, che nSteps venga inizializzato a zero.

26

Page 31: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

6 Implementazione

/*@ @ normal_behavior @ requires @ Position.X >= 0 && Position.X <= width; @ requires @ Position.Y >= 0 && Position.Y <= height; @ @ assignable \nothing; @ @ ensures @ field[Position.X][Position.Y] == 1 ==> \result == false; @ ensures @ field[Position.X][Position.Y] == 0 ==> \result == true; @ @ exception_behavior @ signals (MazeOutOfBound e) @ e.getMessage != null && @ !(Position.X >= 0 && Position.X <= width) && @ !(Position.Y >= 0 && Position.Y <= height); @*/

public boolean GetStatus( Point Position ) throws MazeOutOfBound { ... }}

Anche in questo caso come prima, si obbliga il programmatore a controllare l'effettiva consistenza dei parametri in ingresso (requires). Si stabilisce inoltre tramite la specifica di assignable che nel corso dell'esecuzione del metodo GetStatus, nel suo corpo, non sarà mai possibile assegnare alcun valore a qualche variabile. Tramite la specifica di ensures si stabilisce cosa si vuole il metodo abbia fatto dall'inizio alla fine della sua esecuzione. In questo caso si vuole che il metodo ritorni true nel caso in cui la cella del labirinto nelle coordinate Position.X e Position.Y (field[Position.X][Position.Y]) presenti un valore pari a 0 o false in presenza di un valore pari ad 1.

public class Pawn{ private /*@ spec_public @*/ int status; private /*@ spec_public @*/ string[] icons; //@ assert status < icons.length; ...}

Nel frammento di codice qui sopra, si stabilisce una sorta di invarianza, che dovrà rimanere sempre vera durante l'intera esistenza di ogni oggetto Pawn. Si sta imponendo che status,in qualità di indice dell'array “icons”, non superi mai la sua lunghezza.

27

Page 32: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

6 Implementazione

public class Sequential extends Solver{ private /*@ spec_public @*/ int nSteps; //@ ensures \modified(player) => nSteps == \old(nSteps) + 1; //@ ensures \not_modified(player) => nSteps == \old(nSteps); public Solve() { ... } ...}

In questo frammento si va a specificare il comportamento del metodo Solve della classe Sequential. Nello specifico, se durante l'esecuzione del metodo la pedina ha avuto modo di spostarsi, il valore dei passi percorsi sarà pari al valore precedente incrementato di uno (un po' come accadeva in OCL con la parola chiave @pre). Se invece la pedina non si è potuta spostare da nessuna parte l'implicazione logica impone che il valore di “nSteps” prima e dopo l'invocazione del metodo rimanga la stessa.

6.2 UML (3)Concludiamo l'utilizzo dello standard UML con gli strumenti che esso ci fornisce per la fase

post-implementativa.

6.2.1 Deployment DiagramIl Deployment Diagram ("diagramma di dispiegamento") è un diagramma di tipo statico

previsto dal linguaggio di modellazione object-oriented UML per descrivere un sistema in termini di risorse hardware, dette nodi, e di relazioni fra di esse. Si utilizza questo diagramma per mostrare come le componenti software siano distribuite rispetto alle risorse hardware disponibili sul sistema.

28

Page 33: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

7 Test

7 TestQuesta è l'ultima delle cinque macro-fasi che descrivono lo sviluppo del software ed è

anch'essa estremamente importante e delicata. Un programma perché possa essere consegnato al committente o immesso nel mercato ha bisogno di essere garantito come funzionante. Testare tutte le possibilità di stati in cui può transitare un programma sarebbe una cosa dispendiosa e difficile per piccoli progetti, pressoché impossibile per programmi di grandi dimensioni. Ecco dunque che diventano indispensabili altri tool specifici per il testing, che possano generare casi di test e dare una mano automatizzando controlli altrimenti eccessivamente lunghi e a loro volta soggetti ad errori.

7.1 JunitJUnit è un unit test framework per il linguaggio di programmazione Java, introdotto per

agevolare il lavoro di manutenzione e configurazione del codice.Con unit testing si intende la procedura usata per verificare le singole parti di un codice

sorgente.Se come nel nostro caso si decide di procedere al test del codice utilizzando JUnit, si

devono creare delle apposite classi di test che controlleranno pezzo per pezzo il corretto funzionamento dei metodi.

JUnit utilizza delle annotazioni per marcare i metodi incaricati di fare i test:@Test

public void method() // Identifica il metodo

@Before

public void method() // Prima di ciascun test

@After

public void method() // Alla fine di ciascun test

@BeforeClass

public void method() // Prima di tutti i test

@AfterClass

public void method() // Alla fine di tutti i test

@Test(expected=Exception.class) // Test che deve generare eccezione

@Test(timeout=100) // Massimo tempo di esecuzione

All'interno del metodo preceduto da @Test si potranno utilizzare diverse asserzioni per verificare il corretto comportamento del metodo:

• assertEquals(e,a) il valore atteso e deve essere uguale al valore attuale

• assertArrayEquals(e,a) i due vettori e ed a devono essere uguali in dimensione e contenuto

• assertTrue(c) richiede che il valore c sia true

• assertFalse(c) richiede che il valore c sia false

• assertNull(o) richiede che o sia un riferimento nullo

• assertNotNull(o) richiede che o sia un riferimento non nullo

29

Page 34: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

7 Test

In riferimento al nostro codice JUnit, abbiamo deciso di testare il funzionamento di tre metodi in particolare:

• il metodo Clone() della classe Pawn, del quale andremo a testare se effettivamente esegue una copia esatta del pedone da cui viene invocatoimport org.junit.*;import static org.junit.Assert.*; public class PawnTest { private Pawn p;

@Before public void setUp(){ p = new Pawn(); } @Test public void testClone(){ assertEquals(p, p.clone()); } @After public void TearDown() { p = null; }}

• il metodo GetStatus() della classe Maze, del quale andremo a testare se passati due punti, che rappresentano uno il punto di partenza è uno l'uscita, ritorni true perchè in base alle specifiche non ci devono essere ostacoli posizionati ne sul punto di partenza ne sull'uscita, inoltre questa classe di test controlla anche se viene lanciata un'eccezione di tipo MazeOutOfBoundpublic class MazeTest { private Maze m;

@Before public void setUp(){ m = new Maze(); } @Test (expected=MazeOutOfBound.class) public void testGetStatus() throws MazeOutOfBound{

Point start = new Point (0,0); Point end = new Point (m.GetWidth-1,m.GetHeight-1): assertTrue(m.GetStatus(start)); assertTrue(m.GetStatus(end));

} @After public void TearDown() { m = null; }}

30

Page 35: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

7 Test

• il metodo CheckDirection() della classe Sequential, del quale andremo a testare se effettivamente ritorna false se invocato su un Maze di dimensioni 5x5 con 23 ostacoli

public class SequentialTest { private Sequential s;

@Before public void setUp(){ s = new Sequential(new Maze(5,5,23),new Pawn(new Point(0,0),0), new OutputPrinter()); } @Test public void testCheckDirection(){ Point destination = new Point (1,1); assertFalse(s.CheckDirection(destination)); } @After public void TearDown() { s = null; }}

8 Conclusioni Sviluppare questo progetto è stato un ottimo modo per imparare ed approfondire,mediante l'utilizzo diretto, le tecniche di analisi e progettazione di un software, nonostante il nostro non era un progetto di grandi dimensioni. Inoltre possiamo aggiungere che il lavoro di gruppo è stato formativo e ha reso la cosa molto simile ad un vero team di sviluppo. In conclusione speriamo di aver reso il più comprensibile possibile tutte le fasi affrontate.

31

Page 36: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

9 Appendice

9 Appendice

9.1 Screenshot del programma

32

Page 37: Progetto Ingegneria del Software Maze - cs.unicam.it Progetto Ingegneria del Software Maze di ... Questa è una relazione orientata agli esempi. Lo scopo di questo documento è quello

9 Appendice

9.2 Programmi utilizzatiLa realizzazione di questo progetto ci è stata resa possibile anche grazie all'aiuto di diversi

strumenti di sviluppo come:

• Alloy v4

• Violet

• Star UML

• Pipe v4

• Microsoft Visio 2010

• Adobe Photoshop Inoltre l'interazione e la coordinazione tra i membri del gruppo è stata facilitata dall'uso di software come:

• Dropbox

• Skype

9.3 Fonti• UML Distilled Third Edition

• Slide del corso

• Wikipedia

9.4 RingraziamentiSi ringraziano il cliente (nonché docente del corso) Rosario Culmone, il docente Roberto

Gagliardi ed il dipartimento di Informatica per i mezzi forniti.

33