Sei sulla pagina 1di 6

Laboratorio - Prova Finale

(Ingegneria del Software)

09/04/2019
In rosso ci sono i TODO da eseguire entro il 30/04/2019

GitHub
● Iscriversi a ​https://education.github.com/​ per avere lo ​Student Developer Pack
● Creare ​un repository per team​ ​privato​ chiamato ​ing-sw-2019-​<codice gruppo>
● Aggiungere come collaboratori (Settings → Collaborators) gli altri membri del
team e i responsabili di laboratorio: ​storna​ e ​AlbertoParravicini
● Clonare il repository sul proprio computer con ​git clone <​url repository>​
● Studiare questi (e/o altri) tutorial per diventare confidenti con git:
https://www.youtube.com/watch?v=IyZAYTLQnM8
https://backlog.com/git-tutorial/
● Fare dei test creando un repository personale (diverso da quello usato per il
progetto di Prova Finale) dove poter usare:
git status
git pull
git add -A
git commit -m "<messaggio>"
git push origin master

IntelliJ
● Creare un nuovo progetto basato su ​maven​ scegliendo la versione di java
(consigliata 11), se mancante installare il JDK
● Inserire i seguenti nomi identificativi:
GroupId: ​it.polimi.ingsw
ArtifactId:​ ing-sw-2019-<codice gruppo>
● Scegliere come cartella del progetto quella clonata da git (se ci sono problemi
con file già esistenti nella cartella, ​rinominarli temporaneamente​, poi cancellare i
file doppi e riportare i file originali con il nome corretto)
● Assicurarsi che il ​pom.xml​ del progetto contenga le seguenti linee di codice:
​ <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.language>java</sonar.language>
<sonar.host.url> http://localhost:9000/ </sonar.host.url>

<junit.jupiter.version>5.4.1</junit.jupiter.version>
</properties>

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
<configuration>
<destFile>target/jacoco.exec</destFile>
<dataFile>target/jacoco.exec</dataFile>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
● Installare i seguenti plugin su IntelliJ (File → Settings → Plugins):
Maven Test Support Plugin
SonarLint
● Creare delle ​classi java​ (e.g. per i mazzi di carte) e i relativi ​test​ per fare delle
prove con Intellij e JUnit
● Lanciare i test con IntelliJ (tasto-destro-del-mouse sulla cartella del progetto →
Run “All Test” with coverage) e verificare che si ottenga il 100% di copertura

sonarqube
● Scaricare ed estrarre l'archivio contenente l’ultima versione di sonarqube
● Avviare il server locale e verificare che funzioni: ​http://localhost:9000
● Creare un nuovo progetto con nome e key a piacere (Administration → Projects
→ Managements → Create Project)
● Cliccare sul progetto e procedere con la generazione di un token (basato su Java
e Maven)
● Una volta creato il token eseguire nella console Maven ​di IntelliJ​ (View → Tool
Windows → Maven → Execute Maven Goal) il seguente comando:
clean test sonar:sonar -Dsonar.projectKey=​<key>​ -Dsonar.host.url=http://localhost:9000
-Dsonar.login=​<token>
● Alla pagina ​http://localhost:9000​ appariranno le metriche relative al progetto
● Eseguire il comando ​ogni volta​ che vengono creati nuovi test o nuovo codice
per avere un continuo feedback
● Controllare che l’ultimo report di Sonar caricato su Drive coincida con
quello in locale ​(​mostrare quest’ultimo​ al laboratorio qualora fosse diverso)

Adrenalina
● Imparare le regole del gioco
● Ripassare i ​Design Patterns​ (e.g. MVC, Observer, Decorator, Singleton, etc.)
dalle slide e online (e.g. ​http://www.dofactory.com/Patterns/Patterns.aspx​) e
capire ​se/quando/come usarli
● Estrarre le informazioni dalle regole del gioco e produrre un ​UML​ ad alto livello
(non è necessario indicare tutti i metodi o gli attributi). In aggiunta si suggerisce
di presentare uno o più tra: ​Use Case Diagram​, ​Finite State Diagram​,
Sequence Diagram​, ​etc. ​per spiegare il funzionamento del software modellato
● Suggerimento:​ disegnare un ​Finite State Diagram ​per modellare tutti i possibili
stati all’interno di un turno e gli ​eventi​ (o azioni) che portano da uno stato all’altro
● Completare l’UML ad alto livello ​(se non fatto in precedenza)
● Scrivere codice​ per il Model (e.g. ​almeno​ tutti i dati che indicano lo ​stato di
gioco​ di una qualsiasi partita ​in un singolo istante​) con relativi ​test JUnit​ e
documentazione Javadoc ​(vedere come scrivere la documentazione qui:
https://www.oracle.com/technetwork/java/javase/tech/index-137868.html​)
● Finire il codice​ per il Model e parte del Controller (e.g. ​almeno​ tutta ​la logica
che consente di fare funzionare una partita dalla sua creazione al termine del
gioco) con relativi ​test JUnit​ e ​documentazione Javadoc ​(vedere come
scrivere la documentazione qui:
https://www.oracle.com/technetwork/java/javase/tech/index-137868.html​)
● Iniziare​ la parte di ​Server​ e la parte di ​Client (eg. CLI e/o GUI)​ che gestiscono
la comunicazione ​(e.g. ricezione e invio di messaggi; chiamate a funzioni in
remoto; serializzazione di oggetti; etc.) con ​Socket​ e/o ​RMI
● Pushare il codice con ​git​ sul repository remoto (​assicurarsi di aver capito
come funziona git e cosa sono le branch e fare in modo che i test vengano
eseguiti correttamente, e che sonar mostri le metriche aggiornate​)

Dettagli Implementativi
● Mappe:​ le grafiche di gioco riguardanti le mappe vengono caricate da file (per la
GUI), inoltre è necessario implementate le mappe previste da Adrenalina,
attraverso una struttura dati che descriva la mappa stessa (eg. adiacenza,
passaggi) e ​non riempiendo il codice con una serie di istruzioni condizionali
del tipo "if(mappa==1) if(cella==7) ...." specifiche per ciascuna mappa (i dati per
riempire questa struttura possono essere caricati da un file o, eventualmente,
gestiti da un costruttore o da un metodo, ma i metodi per gestire i dati di una
qualsiasi mappa devono essere i più generici possibili)
● Logica di Gioco:​ i requisiti ​non​ richiedono che tutta la logica di gioco venga
messa in un punto specifico del design del software (inoltre è altamente
sconsigliato​ creare metodi con ​eccessive linee di codice​ che gestiscono
tutto). Sta al buon senso del team (e all’uso delle best practices) il modo di
implementare le “regole di gioco” all’interno del design, tramite appositi metodi.
Se si è in dubbio, la regola è quella di inserire la logica di funzionamento in modo
che l’intero software risulti (almeno): ​Leggibile​, ​Mantenibile​ e ​Scalabile
(estendibile in futuro). ​In ogni caso è importante che la logica di gioco sia
tutta sul Server.
● Parsing di file​: tendenzialmente è sempre possibile usare librerie per il parsing
di file (​previa approvazione​ dei responsabili di laboratorio, dei tutor o dei
professori) qualora siano limitate alla ​sola lettura di dati scritti nel file​, ​SENZA
logica di manipolazione automatica di tipi e valori, SENZA filtri automatici
su tipi e valori, SENZA vincoli automatici di tipi e valori, etc. ​ (e.g. le funzioni
usate possono essere sostituite da operazioni basilari Java su file, stringhe e
sottostringhe e casting di tipi primitivi Java). Ovviamente è possibile che, in caso
di utilizzo di tali librerie, poi vengano ​valutate le conoscenze del team​ su come
eseguire le stesse operazioni di parsing sugli stessi file (che è quindi bene che
siano "human readable") con ​operazioni basilari su file, stringhe e casting di
tipi primitivi Java​.
● Collegamenti tra Model/View/Controller​: esistono diverse versioni del pattern
MVC e tutte sono accettate ​se ben motivate e implementate​. In ogni caso, è
bene che il design sia il più chiaro e pulito possibile e che rispetti le regole di
gioco. ​Esempio di Errore​: ​mettiamo il caso in cui il Model esponga alla View
alcuni dei metodi per avere i dati di gioco direttamente. Se, malauguratamente,
esponesse anche dei metodi che consentono di visualizzare la lista delle carte
coperte in un mazzo (senza necessariamente modificarlo) o di capirne l’ordine,
questo violerebbe le regole di gioco (eg. un utente malevolo potrebbe creare una
View collegata al Server che gli rivela l’ordine delle carte che verranno pescate
nei turni successivi).
● Pre-calcolo di tutte le mosse possibili di un giocatore in un determinato
istante​: è possibile (non obbligatorio) che la View riceva una lista delle sole
mosse possibili al giocatore (a cui è associata) in quel determinato momento
della partita, e che di conseguenza consenta solo quelle mosse all’utente che la
controlla. ​In ogni caso​, è ​obbligatorio​ che la logica di validazione delle mosse
si trovi sul Server e non sul Client (si consideri per esempio il caso in cui un
utente riesca comunque a mandare al Server una mossa che non può fare e che
il Server possa attuare nuovamente la validazione a prescindere, per ​evitare
qualsiasi caso di violazione delle regole di gioco​).
● Branch git​: è ​altamente consigliato​ l’utilizzo di branch git per sviluppare
diverse funzionalità di gioco. La ​valutazione del codice​ ad ogni laboratorio (e
quella finale) sarà però ​relativa solo al codice presente su master​.
● Comunicazione tra Server e Client​: è altamente consigliato anche per la
creazione della parte di comunicazione in Java, l’utilizzo di ​più classi​, l’utilizzo di
gerarchie​ e ​metodi astratti​, l’utilizzo delle ​best practices​ di programmazione,
etc, usate (si spera!) fino a questo momento nel resto del progetto. E’ pertanto
sconsigliato​ creare metodi "chilometrici" o classi "mostruosamente ingombranti"
che gestiscono tutto. Inoltre sarà valutata positivamente la possibilità nel codice
di usare in maniera indistinta (​trasparente​) le diverse implementazioni di
comunicazione (eg. Socket, RMI, etc.) da parte di Server e Client.
● Esempio effetti armi con lambdas​: un approccio per evitare di avere una
miriade di classi con comportamenti hard coded è creare la descrizione degli
elementi elementari (eg. gli effetti delle armi) usando JSON/XML e applicare
lambdas. Un semplice esempio condiviso anche su piazza si trova al link:
https://github.com/ingconti/EffectsUsingLambdas
● Test di metodi che lanciano eccezioni: ​per testare metodi che lanciano
eccezioni vi consiglio di seguire questi due link (usate il modo “nativo”, senza
Hamcrest o AssertJ):
https://blog.goyello.com/2015/10/01/different-ways-of-testing-exceptions-in-java-
and-junit/
https://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-e
xpressions.html
Talvolta Sonar e IntelliJ non riescono a calcolare correttamente la coverage nei
metodi che lanciano eccezioni, ma non preoccupatevi.
● Copertura test: ​i test dovrebbero focalizzarsi sul ​model ​e sulla ​logica ​di gioco.
Non c’è una soglia minima di coverage da raggiungere, e non è nemmeno
necessario il 100%. E’ comunque consigliato di ottenere la ​coverage più alta
possibile​!
I test sulle parti del progetto che hanno a che fare con rete/client non sono
obbligatori, ma se volete farli è consigliabile usare ​Mockito ​(cioè, non avviate un
server vero nei test). ​Un buon unit test dovrebbe durare pochi secondi, non
di più!
● Path a file: ​quando si indica un path relativo ad un file si suppone che parta dalla
root del progetto (ie. la cartella che include il pom.xml). Si ricorda che i path sono
case-sensitive​! Per ​evitare​ che il ​separatore​ usato nel path sia ​dipendente dal
sistema operativo​ esiste quello offerto da Java nella libreria ​java.io.File
per esempio sostituire questi path:
​ ypath1​ =
String m ​ ​ "​ .\\src\\main\\resources\\map.json"​;
String m​ ypath2​ =​ ​ "​ ./src/main/resources/map.json"​;
con questo:
import​ java.io.File;

String ​mypath​ ​=​ ​"."​ + ​File​.​separatorChar​ + ​"src"​ + ​File​.​separatorChar​ + ​"main"


+ ​File​.​separatorChar​ + ​"resources"​ + ​File​.​separatorChar​ + ​"map.json"​;
● Runnare diverse istanze della stessa classe in IntelliJ: ​per lanciare diverse
istanze della stessa classe (contenente un metodo “main”) in IntelliJ (eg. tanti
Client) eseguire il run almeno una volta della classe desiderata, poi cliccare su
Run → Edit Configuration…​ selezionare la classe da runnare e spuntare ​Allow
parallel run​ in alto a sinistra nel menu.
● Input dall’utente nei test: ​è ​considerato errore​ il caso in cui i test aspettano un
input dall’utente (ie. devono testare in automatico tutte le possibilità).