# **Report** ## **Indice** 1) [Introduzione](#Introduzione) 2) [Modello di dominio](#Modello_di_Dominio) 3) [Requisiti specifici](#Requisiti_Specifici) 3.1 [Requisiti funzionali](#funzionali) 3.2 [Requisiti non funzionali](#non_funzionali) 4) [System Design](#System_Design) 4.1 [Cos'è il System Design?](#Introduzione_SD) 4.2 [Stile architetturale](#Stile_architetturale) 5) [OO Design](#Design) 5.1 [Decisioni Effettuate](#Decisioni) 6) [Manuale Utente](#Manuale) 7) [Processo di sviluppo e organizzazione del lavoro](#Processo) 8) [Analisi retrospettiva](#Analisi) 8.1 Sprint 1 (Domande): - Cosa vi ha fatto sentire soddisfatti e vi ha reso contenti; - Cosa vi ha fatto sentire insoddisfatti e vi ha deluso; - Cosa vi ha fatto "impazzire" e vi ha reso disperati. <br/> ## **Introduzione** <a id="Introduzione"></a> <br/> ### **Informazioni sul Progetto** Il progetto di questo corso consiste nello sviluppo di un programma che proponga le stesse funzionalità dell'app "Wordle". Il programma deve permettere che l'utente (Giocatore) che utilizza il programma possa creare una nuova Partita; inoltre, deve gestire un "Paroliere" che permetta di stabilire nuove parole da mostrare all'utente. <br/> ### **Obiettivi di Progetto** - Imparare a lavorare tramite la progettazione "SCRUM" al fine di coordinare il gruppo nella progettazione; - Imparare il funzionamento del Servizio di Hosting per progetti Software "Github"; - Imparare a lavorare in gruppo secondo un Codice di Condotta; - Rappresentare tramite linguaggio UML il Modello Concettuale di Dominio e il Modello Software del progetto; - Programmare un nuovo Programma "Wordle" utilizzando il linguaggio Java; - Praticare nell'analisi e nel debug degli errori tramite JUnit; - Apprendere il funzionamento del container Docker e tramite esso rendere eseguibile il nostro applicativo su diverse piattaforme; - Interfacciarsi con i comandi basilari di Gradle; ### **Configurazione del Team** Il team è composto da 7 studenti che lavorano sullo stesso progetto. Ogni gruppo deve soddisfare gli obiettivi di ognuno dei 3 Sprint entro una durata limite determinata dal Professore. <br/> ## **Modello di Dominio** <a id="Modello_di_Dominio"></a> <br/> La realizzazione di un modello di dominio ha come obbiettivo quello di creare una semplificazione della realtà di riferimento. Dunque abbiamo utilizzato tale rappresentazione per individuare i componenti fondamentali presenti in Wordle. La rappresentazione implementata fa uso di frecce che rappresentano la tipologia di associazione e di relazione che sussiste tra le varie entità presenti nel progetto. L'obbiettivo ultimo di questa rappresentazione è quello di fornire una panoramica dal punto di vista concettuale, che deve fornire un punto di partenza per la realizzazione del progetto. Le entità individuate durante il meeting di analisi sono: - Giocatore, che rappresenta l'entità che partecipa al gioco; - Partita, la quale rappresenta l'entità che gestisce il gioco; - Paroliere, l'entità che fornisce le parole per ogni partita; <br/> ![Modello_di_dominio](./img/Modello_di_dominio.png) <br/> Le relazioni sono rappresentate tramite dei segmenti, ognuno dei quali presenta un rombo che se vuoto indica una relazione di aggregazione, mentre se pieno rappresenta una relazione di composizione. Aggregazione: è una relazione tra due componenti nella quale l'entità contenente non esiste senza l'entià contenuta. Composizione: è una relazione tra due componenti nella quale l'entità contenente non esiste senza l'entità contenuta e l'entità contenuta non esiste senza l'entità contenente. <br/> ## **Requisiti specifici** <a id="Requisiti_Specifici"></a> <br/> ### **Requisiti funzionali** <a id="funzionali"></a> <br/> #### *Codice caso d’uso*: CDS01 *Nome*: Impostare parola segreta\ *Attore*: Paroliere\ *Obiettivo*: Permette al paroliere di impostare una nuova parola segreta per la partita\ *Pre-condizioni*: Nessuna parola segreta è già stata impostata\ *Post-condizioni*: La parola segreta è stata impostata <br/> #### *Codice caso d’uso*: CDS02 *Nome*: Mostrare parola segreta\ *Attore*: Paroliere\ *Obiettivo*: Permette al paroliere di mostrare la parola segreta\ *Pre-condizioni*: La parola segreta è già stata impostata\ *Post-condizioni*: Il sistema stampa a video la parola segreta <br/> #### *Codice caso d’uso*: CDS03 *Nome*: Mostrare menù dei comandi\ *Attore*: Partita\ *Obiettivo*: Mostra l'elenco dei comandi per giocare la partita\ *Pre-condizioni*: Nessuna pre-condizione\ *Post-condizioni*: Il sistema stampa a video l'elenco dei comandi per poter giocare la partita <br/> #### *Codice caso d’uso*: CDS04 *Nome*: Iniziare una partita\ *Attori*: Giocatore\ *Obiettivo*: Permette al giocatore di poter iniziare una partita\ *Pre-condizioni*: Non c’è nessuna partita in corso\ *Post-condizioni*: La partita inizia <br/> #### *Codice caso d’uso*: CDS05 *Nome*: Abbandonare una partita\ *Attori*: Giocatore\ *Obiettivo*: Permette al giocatore di abbandonare una partita\ *Pre-condizioni*: Deve esserci una partita in corso\ *Post-condizioni*: L’app comunica che il parolere vince la partita per l'abbandono del giocatore <br/> #### *Codice caso d’uso*: CDS06 *Nome*: Effettua tentativo\ *Attori*: Giocatore\ *Obiettivo*: Permette al giocatore di effettuare un tentativo\ *Pre-condizioni*: Deve esserci una partita in corso\ *Post-condizioni*: Il tentativo è comunicato alla partita <br/> #### *Codice caso d’uso*: CDS07 *Nome*: Chiudere il gioco\ *Attori*: Giocatore\ *Obiettivo*: Permette al giocatore di uscire dal gioco\ *Pre-condizioni*: Nessuna pre-condizione *Post-condizioni*: Il gioco si chiude restituendo un messaggio all'utente ### **Requisiti non funzionali** <a id="non_funzionali"></a> *RNF1*: (Portabilità) L’applicazione deve funzionare sui seguenti prompt dei comandi: Linux: - Terminal Mac OS: - Terminal Windows: - CMD - Powershell - Terminal del sottosistema Linux per Windows Git Bash *RNF2*: (Efficienza) Ad ogni comando l’applicazione rilascia un feedback istantaneo *RNF3*: (Robustezza) L’esecuzione dell’applicazione non deve essere interrotta se non sotto casi previsti. ## **System Design** <a id="System_Design"></a> ### **Cos'è il System Design?** <a id="Introduzione_SD"></a> Il System Desing è uno stile di progettazione ad alto livello che evidenzia la comunicazione fra le componenti e delle loro relazioni all’interno della realtà esaminata. Ogni cambiamento effettuato deve rispettare i seguenti principi: - Principio di information hiding - Obiettivo di alta coesione - Obiettivo di basso accoppiamento - Presentazione separata #### **Principio di information hiding** Ogni componente deve custodire dei segreti al proprio interno, ovvero i dettagli della implementazione: - #### *Sottosistemi* Nei sottosistemi solo l’interfaccia delle operazioni è pubblica. L'implementazione invece risulta privata. - #### *Package* Solo le classi strettamente necessarie sono pubbliche, tutte le altre risultano private. - #### *Classi* Solo le operazioni necessarie sono pubbliche, tutte le altre sono private. Tutte le variabili sono private (incapsulamento dei dati). #### **Obiettivo di alta coesione** La *coesione* misura il grado di dipendenza tra elementi di uno stesso componente, i componenti possono avere coesione differente: - Un componente ad alta coesione ha una responsabilità ben definita. - Un basso grado di coesione è indidice di una responsiabiltà non ben definita rendendo difficile riusare, comprendere e modificare. **Obiettivo: assegna le responsabilità in modo tale da ottenere componenti con responsabilità ben definite** `` Una bassa coesione si risolve delegando le responsabilità ad altri componenti. `` #### **Obiettivo di basso accoppiamento** L'accoppiamento misura il grado di dipendenza fra componenti diversi, come per la alta coesione anche qui abbiamo una distinzione: - Alto accoppiamento, un cambiamento a un componente si propaga facilmente a tutti i componenti che dipendono da esso. - Basso accoppiamento, un cambiamento a un componente non si propaga ad altri componenti. **Obiettivo: assegna le responsabilità ai componenti in modo tale da limitare l’impatto dei cambiamenti** `` Un alto accoppiamento si risolve applicando il principio di information hiding. `` #### **Presentazione separata** La logica di presentazione e la logica di dominio sono più facili da capire se tenute separate. È possibile esporre la logica di dominio come API/servizio ed è anche possibile supportare presentazioni differenti senza duplicare il codice. Senza parti grafiche è possibile scrivere i casi di test con asserzioni testuali. <br/> #### **Come vengono rispettati tali principi** - ``L'information hiding viene rispettato tramite l'utilizzo dell'incapsulamento ed è rappresentato con la struttura Layered, esplicitato a breve.`` - ``L'alta coesione e il basso accoppiamento vengono rispettati entrambi tramite l'utilizzo dei GoF Patterns: Proxy. (COMMENTATO NELLA SEZIONE DI OO DESIGN)`` - ``La presentazione separata è visibile grazie al MVP (Model-View-Presenter) esplicitato a breve nella sezione "Model-View-Presenter".`` <br/> ### **Stile architetturale adottato** <a id="Stile_architetturale"></a> Gli stili architetturali utilizzati sono i seguenti: - *Layered*, per osservare la relazione fra i package. - *Model-View-Presenter*, per visionare l'interazione fra l'utente e il sistema considerato. #### **Layered** Nello stile architetturale layered ogni strato espone un’interfaccia (API) che è utilizzata da un componente dello strato superiore, nel nostro caso si utilizza una stratificazione lasca, in maniera tale da permettere ai layer superiori di comunicare con tutti quelli inferiori. I package presenti nella nostra realtà sono: - App, ovvero il package dove l'esecuzione del gioco ha inizio, contiene tutti i cicli principali del gioco, permettendo all'utente di effettuare le scelte. - Controller, dove sono presenti tutte le classi che contengono logica del gioco. - Boundary, permette all'utente di visionare i risultati delle varie operazioni effettuate, durante la partita. - Entity, salva la parola inserita dal Paroliere, permettendo di utilizzarla in una partita. Fortunatamente nel nostro caso lo svantaggio principale, ovvero, prestazioni degradate in presenza di molti strati, non è molto evidente. **Diagramma dei package:** <p align="center"> <img src="./img/layered.png"/></p> #### **Model-View-Presenter** Lo stile architetturale Model-View-Presenter separa la logica di presentazione da quella di dominio: - View, dove rappresenta i dati e le molteplici viste; - Model, dove sono presenti gli oggetti che rappresentano il dominio; - Presenter, gestisce la sequenza di iterazioni con l’utente, accetta l’input e lo trasforma in comandi per il modello o la vista, inoltre media tra gli oggetti del Model e le viste (View) che li rappresentano. Questo stile a differenza del Model-View-Controller, il model non notificano le view dopo delle possibili modifiche e le view non conoscono l’implementazione del model. **Diagramma delle componenti:** <p align="center"> <img src="./img/MVP.png"/></p> <br/> <br/> ## **OO Design** <a id="Design"></a> <br/> ### **Diagrammi delle classi e diagrammi di sequenza** <br/> Il diagramma delle classi a prospettiva software è utilizzato per descrivere i legami statici che sussistono tra i vari oggetti presenti all'interno del sistema di riferimento. Diagramma delle classi a prospettiva software: <br/> ![Diagramma_delle_classi](./img/Diagramma_delle_classi.png) <br/> ### **Diagrammi di sequenza per le user story più importanti** <br/> - Diagramma di sequenza per il comnando "/nuova": <br/> ![comando_nuova](./img/nuova.png) <br/> - Diagramma di sequenza per il comnando "/esci": <br/> ![comando_esci](./img/esci.png) <br/> - Diagramma di sequenza per il comnando "/abbandona": <br/> ![comando_abbandona](./img/abbandona.png) <br/> - Diagramma di sequenza per il comnando "/gioca": <br/> ![comando_gioca](./img/gioca.png) <br/> - Diagramma di sequenza per la gestione di un tentativo per indovinare la parola (si presuppone che questo è il caso in cui la porala viene indovinata): <br/> ![tentativo](./img/tentativo.png) <br/> ### **Decisioni Effettuate** <a id="Decisioni"></a> Abbiamo deciso di inserire le funzioni abbandona, esci e gioca all’interno della classe Main per i seguenti motivi: - La chiamata ai metodi esci ed abbandona porta eventualmente alla modifica dello stato di alcune booleane le quali comportano la modifica dello stato del programma (terminazione nel caso in cui si richiami la funzione esci, e termine della partita nel caso in cui si richiami il metodo abbandona). - La modifica dei booleani su citati potrebbero negano l’esecuzione del metodo gioca dunque tali variabili devono essere visibili anche dal metodo gioca. La seconda scelta effettuata e quella di utilizzare due metodi per la stampa della matrice. Tale considerazione è stata necessaria dato che l’utilizzo dei colori è possibile esclusivamente tramite l’utilizzo di codici, i quali sono dipendenti dal sistema operativo utilizzato. Dunque, abbiamo implementato due funzioni che permetto al programma di essere eseguito sia su Windows sia su Linux. <br/> Abbiamo in oltre modificato con la issue#77 l'intera struttura del progetto dato che ci siamo resi conto che essa non era compatibile con la tassonomia ECB. Nello specifico siamo andati a modificare maggiormente la classe Partita, dato che quest'ultima portava a delle gravi incongruenze rispetto alla struttura ECB. Tale modifica ha poi portato inevitabilmente ad alcuni cambiamenti all'interno delle classi App e Controllore (quest'ultima classe è poi diventata ControlloreStringhe). ## **Manuale Utente** <a id="Manuale"></a> Per poter avviare il gioco è necessario: - Scaricare ed avviare Docker sul proprio pc; - Effettuare il login su Docker; - Avviare il terminale; - Inserire il comando “docker pull ghcr.io/softeng2122-inf-uniba/wordle-newell:latest” per poter scaricare l’ultima versione del gioco; - Inserire il comando “winpty docker run --rm -it ghcr.io/softeng2122-inf-uniba/wordle-newell:latest” per poter avviare il gioco; - Avvio del gioco. ### **Come giocare**: All’avvio del gioco, appaiono dei comandi da digitare a seconda della scelta del giocatore: - Il comando `“/nuova”` permette di inserire la parola segreta da indovinare; - Il comando `“/mostra”` mostra la parola segreta inserita; - Il comando `“/gioca”` permette di iniziare una nuova partita; - Il comando `“/help”` stampa i comandi utilizzabili al di fuori della partita; - Il comando `“/esci”` permette di terminare l’esecuzione del gioco. Se il giocatore sceglie di iniziare una nuova partita, innanzitutto si deve inserire la parola da indovinare tramite il comando `“/nuova”`, successivamente inserendo il comando `“/gioca”` la partita ha inizio. All’avvio del gioco, appariranno dei comandi utilizzabili solo durante la partita corrente: - Il comando `“/help”` che stampa i comandi utilizzabili; - Il comando `“/abbandona”` che permette di abbandonare la partita in corso; - Il comando `“/esci”` che permette di terminare l’esecuzione del gioco; Il giocatore ha 6 tentativi per riuscire ad indovinare la parola segreta: la parola scritta ad ogni tentativo, viene inserita all’interno delle righe di una tabella e le lettere assumeranno tre colori differenti in base alla loro posizione all’interno della parola segreta affinché il giocatore riesca ad indovinarla. Una lettera assume colore verde se si trova nella stessa posizione in cui è presente all’interno della parola segreta, assume colore giallo se è presente nella parola ma non in quella posizione e infine assume colore rosso se la lettere è sbagliata e non appartiene alla parola segreta. La partita si conclude quando il giocatore indovina la parola segreta. ## **Processo di sviluppo e organizzazione del lavoro** <a id = "Processo"></a> Il processo di sviluppo e l'organizzazione del lavoro è stato reso possibile grazie all'utilizzo del framework Scrum, costituito dai ruoli, dagli eventi, dagli artefatti di Scrum e dalle regole che li legano insieme. Dando più flessibilità ai ruoli, abbiamo suddiviso il progetto nei seguenti Sprint: - Sprint 0, inizializzazione del progetto; - Sprint 1, sviluppo del codice e scrittura della relazione tecnica (parziale); - Sprint 2, completamento relazione tecnica e fix delle problematiche riscontrate; i quali non erano interrompibili ed ogni timeboxing era all'incirca di 14 giorni. I requisiti desiderati in ogni iterazione sono stati analizzati, progettati, realizzati e testati durante ogni sprint. Il Product Backlog seguito per sviluppare il gioco è il seguente: ``` 1) Come paroliere voglio: - impostare una parola segreta manualmente - mostrare la parola segreta 2) Come giocatore voglio: - mostrare l'help con elenco comandi e regole del gioco - iniziare una nuova partita (mostrare la matrice dei tentativi vuota ma senza mostrare la tastiera) - abbandonare una partita - effettuare un tentativo per indovinare la parola segreta - chiudere il gioco ``` In origine, il Product Backlog era molto più esteso, ma tutte le altre funzionalità non presenti nella lista non sono state implementate per decisione del Project Manager. Successivamente al lancio di ogni Sprint, il gruppo si riuniva per discutere e capire quali fossero i requisiti da realizzare e di seguito avveniva l'assegnazione delle issue in modalità videochiamata oppure ibrida. In generale, la realizzazione delle issue è avvenuta individualmente, ma in situazioni dubbiose o critiche il gruppo è stato sempre propenso nell'aiutare i colleghi in difficoltà, ad esempio sfruttando lo strumento Visual Studio con il plugin LiveShare. In determinati giorni prefissati, durante gli Sprint, il gruppo si riuniva per chiarire eventuali dubbi di qualsiasi genere, per confrontare il lavoro svolto e per mettere a fuoco gli aspetti principali delle issue da svolgere. Al termine di ogni Sprint il team si riuniva per effettuare il testing e per controllare il lavoro svolto, se tutto avesse funzionato correttamente avremmo comunicato il completamento dello Sprint. ## **Analisi Retrospettiva** <a id="Analisi"></a> Durante un incontro di gruppo su teams, abbiamo discusso delle emozioni provate nel corso delle diverse parti che costituiscono il progetto e le abbiamo raggruppate all'interno di un modello retrospettivo. <br/> ![modello_retrospettivo](./img/modello_retrospettivo.png)