diff --git a/.gitignore b/.gitignore
index e9476bf801209d6d7e931b6c8b91fd8026cb83d1..a8f434c9d8689b974ecd9113ecb82028f5a16419 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,7 @@ resized/
 .vscode/
 uml/
 book
+
+# PlantUML plugin
+mdbook-plantuml-img/
+.mdbook-plantuml-cache/
diff --git a/_posts/2022-10-24-Progettazione.md b/_posts/2022-10-24-Progettazione.md
deleted file mode 100644
index 75847d3c25757f82ebaf3f15a608343b98ece682..0000000000000000000000000000000000000000
--- a/_posts/2022-10-24-Progettazione.md
+++ /dev/null
@@ -1,555 +0,0 @@
----
-layout: post
-title: "[07] Progettazione"
-date:   2022-10-24 14:30:00 +0200
-toc: true
----
-
-# Progettazione
-
-## Introduzione
-
-Durante le lezioni, per discutere di progettazione siamo partiti da un esempio di programma in C che stampa una canzone.
-Il [codice considerato](https://paste.studentiunimi.it/paste/JS+VOUKO#Rj3CMN-TmbNu3zeTleTTM0JdjjROWeVySXTgzG6aWKY) è talmente illeggibile che Jekyll rifiuta di compilare se lo si prova ad includere in un file Markdown.
-
-Successivamente abbiamo scomposto il codice per renderlo logicamente più sensato e facilmente modificabile, sono state __estratte le parti comuni__ e spostate in una funzione apposita, mentre le __parti mutabili sono state salvate in alcune strutture dati__; la canzone viene così stampata tramite un ciclo. 
-In questo modo scrivendo un codice più semplice siamo stati in grado di creare una soluzione più generale e più aperta ai cambiamenti.
-
-```java
-public class TwelveDaysOfChristmas {
-    static String[] days = {"first", "second", ..., "twelfth"};
-    static String[] gifts = { "a partdrige in a pear tree", "two turtle doves", ... };
-
-    static String firstLine(int day) {
-        return "On the " + days[day] +
-               " day of Christmas my true love gave to me:\n";
-    }
-
-    static String allGifts(int day) {
-        if (day == 0) {
-            return "and " + gifts[0];
-        } else {
-            return gifts[day] + "\n" + allGifts(day-1);
-        }
-    }
-
-    public static void main(String[] args) {
-        System.out.println(firstLine(0));
-        System.out.println(gifts[0]);
-        for (int day == 1; day < 12; day++) {
-            System.out.println(firstLine(day));
-            System.out.println(allGifts(day));
-        }
-    }
-}
-```
-
-È importante quindi __adottare la soluzione più semplice__ (che __non è quella più stupida__!) e una misura convenzionale per dire quanto una cosa è semplice - almeno in Università - si esprime in termini del tempo dedicato dal programmatore all'implementazione.
-Tale misura si sposa bene con il __TDD__, che richiede __brevi iterazioni__ di circa 10 minuti: se la feature attuale richiede più tempo è opportuno ridurre la portata scomponendo il problema.
-
-## Refactoring
-Durante il refactoring è opportuno rispettare le seguenti regole:
-- le __modifiche al codice non devono modificare le funzionalità__:
-il refactoring DEVE essere invisibile al cliente;
-- __non possono essere aggiunti test aggiuntivi__ rispetto alla fase verde appena raggiunta.
-
-Se la fase di refactoring sta richiedendo troppo tempo allora è possibile fare rollback all'ultima versione verde e __pianificare meglio__ l'attività di refactoring, per esempio scomponendolo in più step.
-Vale la regola del _"do it twice"_: il secondo approccio a un problema è solitamente più veloce e migliore.
-
-### Motivazioni
-
-Spesso le motivazioni dietro un refactoring sono:
-- precedente __design molto complesso e poco leggibile__, a causa della velocità del passare ad uno _scenario verde_;
-- __preparare il design di una funzionalità__ che non si integra bene in quello esistente; dopo aver raggiunto uno _scenario verde_ in una feature, è possibile che la feature successiva sia difficile da integrare. 
-In questo caso, se il _refactoring_ non è banale è bene fermarsi, tornare indietro e evolvere il codice per facilitare l'iterazione successiva (__design for change__). 
-- presenza di __debito tecnico__ su lavoro fatto in precendenza, ovvero debolezze e "scorciatoie" che ostacolano notevolmente evoluzioni future: _"ogni debito tecnico lo si ripaga con gli interessi"_.
-
-## Design knowledge
-
-La design knowledge è la __conoscenza del design__ architetturale di un progetto. 
-È possibile utilizzare:
-- la __memoria__: non è efficace perché nel tempo si erode, specialmente in coppia;
-- i __documenti di design__ (linguaggio naturale o diagrammi): se non viene aggiornato di pari passo con il codice rimane disallineato, risultando più dannoso che d'aiuto.
-- le __piattaforme di discussione__ (version control, issue management): possono aiutare ma le informazioni sono sparse in luoghi diversi e di conseguenza difficili da reperire e rimane il problema di mantenere aggiornate queste informazioni.
-- gli __UML__: tramite diagrammi UML si è cercato di sfruttare l'approccio ___generative programming___, ovvero la generazione automatica del codice a partire da specificazioni di diagrammi.
-Con l'esperienza si è visto che non funziona.
-- il __codice__ stesso: tramite la lettura del codice è possibile capire il design ma è difficile rappresentare le ragioni della scelta.
-
-È bene sfruttare tutte le tecniche sopra proposte __combinandole__, partendo dal codice. \
-È inoltre importante scrivere documentazione per spiegare le ragioni dietro le scelte effettuate e non le scelte in sé, che si possono dedurre dal codice.
-
-### Condivisione
-
-Per condividere tali scelte di design (il _know how_) è possibile sfruttare:
-- __metodi__: con pratiche (come Agile) o addirittura l'object orientation stessa, che può essere un metodo astratto per condividere scelte di design.
-- __design pattern__: fondamentali per condividere scelte di design, sono utili anche per generare un vocabolario comune (sfruttiamo dei nomi riconosciuti da tutti per descrivere i ruoli dei componenti) e aiutano l'implementazione (i pattern hanno delle metodologie note per essere implementati). 
-I pattern non si concentrano sulle prestazioni di un particolare sistema ma sulla generalità e la riusabilità di soluzioni a problemi comuni;
-- __principi__: per esempio i principi SOLID.
-
-## Conoscenze preliminari di concetti e termini
-
-Prima di proseguire è bene richiamare concetti e termini fondamentali presumibilmente visti durante il corso di Programmazione II.
-
-### Object orientation
-
-Per essere definito _object oriented_, un linguaggio di programmazione deve soddisfare tre proprietà:
-- __ereditarietà__: ovvero la possibilità di poter definire una classe ereditando proprietà e comportamenti di un'altra classe.
-- __polimorfismo__: quando una classe può assumere diverse forme in base alle interfacce che implementa. 
-Il prof fa l'esempio del _tennista scacchista_: in un torneo di tennis è poco utile sostituire una persona che gioca a tennis ed è brava con gli scacchi (quindi una classe che implementa entrambe le interfacce) con una che gioca a scacchi.
-Il collegamento tra capacità e oggetto è fatto __a tempo di compilazione__: non è importante quindi se la capacità non è ancora definita;
-- __collegamento dinamico__: in Java il tipo concreto degli oggetti e quindi il problema di stabilire _quale metodo chiamare_ viene risolto durante l'esecuzione. 
-In C++ occorre esplicitare questo comportamento utilizzando la keyword `virtual`.
-
-### <a style="color: darkgreen">SOLID</a> principles
-
-Ci sono 5 parti che compongono questo principio:
-1. __<span style="color: darkgreen"><big>S</big></span>INGLE RESPONSIBILITY__: una classe, un solo scopo.
-Così facendo, le classi rimangono semplici e si agevola la riusabilità.
-2. __<span style="color: darkgreen"><big>O</big></span>PEN-CLOSE PRINCIPLE__:
-le classi devono essere aperte ai cambiamenti (_opened_) ma senza modificare le parti già consegnate e in produzione (_closed_).
-Il refactoring è comunque possibile, ma deve essere preferibile estendere la classe attuale.
-3. __<span style="color: darkgreen"><big>L</big></span>ISKOV SUBSTITUTION PRINCIPLE__:
-c'è la garanzia che le caratteristiche eredidate dalla classe padre continuinino ad esistere nelle classi figlie.
-Questo concetto si collega all'aspetto __contract-based__ del metodo Agile: le _precondizioni_ di un metodo di una classe figlia devono essere ugualmente o meno restrittive del metodo della classe padre.
-Al contrario, le _postcondizioni_ di un metodo della classe figlia non possono garantire più di quello che garantiva il metodo nella classe padre.
-Fare _casting_ bypassa queste regole.
-4. __<span style="color: darkgreen"><big>I</big></span>NTERFACE SEGREGATION__:
-più le capacità e competenze di una classe sono frammentate in tante interfacce più è facile utilizzarla in contesti differenti.
-In questo modo un client non dipende da metodi che non usa. 
-Meglio quindi avere __tante interfacce specifiche__ e piccole (composte da pochi metodi), piuttosto che poche, grandi e generali. 
-5. __<span style="color: darkgreen"><big>D</big></span>EPENDENCY INVERSION__:
-il codice dal quale una classe dipende non deve essere più __concreto__ di tale classe.
-Per esempio, se il _telaio della FIAT 500_ dipende da uno specifico motore, è possibile utilizzarlo solo per quel specifico motore.
-Se invece il telaio dipende da _un_ concetto di motore, non c'è questa limitazione.
-In conlusione, le classi concrete devono tendenzialmente dipendere da classi astratte e non da altre classi concrete.
-
-### Reference escaping
-
-Il _reference escaping_ è una violazione dell'incapsulamento. 
-
-Può capitare, per esempio: 
-- quando un getter ritorna un riferimento a un segreto;
-```java
-public Deck {
-    private List<Card> cards;
-        
-    public List<Card> getCards() {
-        return this.cards;
-    }
-}
-```
-- quando un setter assegna a un segreto un riferimento che gli viene passato;
-```java
-public Deck {
-    private List<Card> cards;
-
-    public setCards(List<Card> cards) {
-        this.cards = cards;
-    }
-}
-```
-
-- quando il costruttore assegna al segreto un riferimento che gli viene passato;
-```java
-public Deck {
-    private List<Card> cards;
-
-    public Deck(List<Card> cards) {
-        this.cards = cards;
-    }
-}
-```
-
-### Encapsulation e information hiding
-
-__Legge di Parnas (L8)__.
-> Solo ciò che è nascosto può essere cambiato liberamente e senza pericoli.
-
-Lo stato mostrato all'esterno non può essere modificato, mentre quello nascosto sì.
-
-Questo principio serve per __facilitare la comprensione del codice__ e renderne più facile la modifica parziale senza fare danni.
-
-### Immutabilità
-
-Una classe è immutabile quando non c'è modo di modificare lo stato di ogni suo oggetto dopo la creazione.
-
-Per assicurare tale proprietà è necessario:
-- __non fornire metodi di modifica__ allo stato;
-- avere tutti gli __attributi privati__ per i tipi potenzialmente mutabili (come `List<T>`);
-- avere tutti gli __attributi final__ se non già privati;
-- assicurare l'__accesso esclusivo__ a tutte le parti non mutabili, ovvero non avere reference escaping.
-
-## Code smell
-
-I _code smell_ sono dei segnali che suggeriscono problemi nella progettazione del codice. 
-Di seguito ne sono elencati alcuni:
-- __codice duplicato__: si può fare per arrivare velocemente al verde ma è da togliere con il refactoring. 
-Le parti di codice in comune possono quindi essere fattorizzate.
-- __metodi troppo lunghi__: sono poco leggibili e poco riusabili;
-- __troppi livelli di indentazione__: scarsa leggibilità e riusabilità, è bene fattorizzare il codice;
-- __troppi attributi__: suggerisce che la classe non rispetta la single responsability, ovvero fa troppe cose;
-- __lunghe sequenze di _if-else_ o _switch___;
-- __classe troppo grande__;
-- __lista parametri troppo lunga__;
-- __numeri _magici___: è importante assegnare alle costanti numeriche all'interno del codice un nome per comprendere meglio il loro scopo;
-- __commenti che spiegano cosa fa il codice__: indicazione che il codice non è abbastanza chiaro;
-- __nomi oscuri o inconsistenti__;
-- __codice morto__: nel programma non deve essere presente del codice irraggiungibile o commentato. Utilizzando strumenti di versioning è possibile riaccedere a codice precedentemente scritto con facilità.
-- __getter e setter__: vedi principio di __tell don't ask__.
-
-## <a href="https://martinfowler.com/bliki/TellDontAsk.html">Principio Tell-Don't-Ask</a>
-
-{% responsive_image path: 'assets/07_tell-dont-ask.png' %}
-
-> Non chiedere i dati, ma dì cosa vuoi che si faccia sui dati
-
-Il responsabile di un'informazione è anche responsabile di tutte le operazioni su quell'informazione.
-
-Il principio _Tell-Don't-Ask_ sancisce che piuttosto di __chiedere__ ad un oggetto dei dati e fare delle operazioni con quei dati è meglio __dire__ a questo oggetto cosa fare con i dati che contiene. 
-
-#### Esempio
-
-Se desideriamo stampare il contenuto di tutte le carte in un mazzo possiamo partire da questo codice.
-
-```java
-class Main {
-    public static void main(String[] args) {
-        Deck deck = new Deck();
-        Card card = new Card();
-
-        card.setSuit(Suit.DIAMONDS);
-        card.setRank(Rank.THREE);
-        deck.getCards().add(card);
-        deck.getCards().add(new Card());    // <-- !!!
-
-        System.out.println("There are " + deck.getCards().size() + " cards:");
-        for (Card currentCard : deck.getCards()) {
-            System.out.println(
-                currentCard.getRank() + 
-                " of " + 
-                currentCard.getSuit()
-            );
-        }
-    }
-}
-```
-
-All'interno del ciclo reperiamo gli attributi della carta e li utilizziamo per stampare le sue informazioni.
-Inoltre, nella riga evidenziata viene aggiunta una carta senza settare i suoi attributi. 
-La responsabilità della gestione dell'informazione della carta è quindi __erroneamente delegata__ alla classe chiamante.
-
-Per risolvere, è possibile trasformare la classe `Card` nel seguente modo:
-
-```java
-class Card {
-    private Suit suit;
-    private Rank rank;
-
-    public Card(@NotNull Suit s, @NotNull Rank r) {
-        suit = s;
-        rank = r;
-    }
-
-    @Override
-    public String toString() {
-        return rank + " of " + suit;
-    }
-}
-```
-
-l'informazione viene ora interamente gestita dalla classe `Card`, che la gestisce nel metodo `toString()` per ritornare la sua rappresentazione testuale.
-
-## Interface segregation
-
-Le interfacce possono _"nascere"_ tramite due approcci: 
-- __up front__: scrivere direttamente l'interfaccia;
-- __down front__: scrivere il codice e quindi tentare di estrarne un'interfaccia.
-
-L'approccio down-front si adatta meglio al TDD ed è illustrato nel seguente esempio.
-
-## Esempio con gerarchia Card / Deck
-
-In questo esempio sono trattati numerosi principi, come l'_interface segreagation_, _linking dinamico/statico_, _implementazione di interfacce multiple_ e il _contract based design_ vs la _programmazione difensiva_.
-
-### Interface segregation all'opera
-
-```java
-public static List<Card> drawCards(Deck deck, int number) {
-    List<Card> result = new ArrayList<>();
-    for (int i = 0; i < number && !deck.isEmpty(); i++) {
-        result.add(deck.draw());
-    }
-    return result;
-}
-```
-
-Consideriamo il metodo `drawCards` che prende come parametri un `Deck` e un intero. \\
-Le __uniche competenze__ riconosciute a `Deck` sono l'indicazione _se è vuoto_ (`isEmpty()`) e il _pescare una carta_ dal mazzo (`draw()`).
-`Deck` può quindi __implementare un'interfaccia__ che mette a disposizione queste capacità.
-
-È possibile modificare il metodo in modo da accettare un qualunque oggetto in grado di eseguire le operazioni sopra elencate, ovvero che implementi l'interfaccia __`CardSource`__. 
-
-<a id="cardsource" style="display:none;"></a>
-
-```java
-public interface CardSource {
-    /**
-     * @return The next available card.
-     * @pre !isEmpty()
-     */
-    Card draw();
-
-    /**
-     * @return True if there is no card in the source
-     */
-    boolean isEmpty();
-}
-```
-
-```java
-public class Deck implements CardSource { ... }
-```
-
-```java
-public static List<Card> drawCards(CardSource deck, int number) {
-    List<Card> result = new ArrayList<>();
-    for (int i = 0; i < number && !deck.isEmpty(); i++) {
-        result.add(deck.draw());
-    }
-    return result;
-}
-```
-
-### Collegamento statico e dinamico
-
-Notare come è necessario specificare __staticamente__ che `Deck` implementi `CardSource`, ovvero occorre forzare la dichiarazione del fatto che `Deck` sia un _sottotipo_ di `CardSource` (Java è strong typed) e quindi sia possibile mettere un oggetto `Deck` ovunque sia richiesto un oggetto `CardSource`. \\
-In altri linguaggi come __Go__ c'è una __maggiore dinamicità__ perché non c'è bisogno di specificare nel codice che un oggetto è sottotipo di qualcos'altro, è sufficiente solo che implementi un metodo con la stessa signature.
-Il controllo che l'oggetto passato ad una funzione abbia le capacità necessarie avviene a runtime e non prima.
-
-Un problema della troppa dinamicità (__duck typing__) è che se i metodi di un oggetto non hanno dei nomi abbastanza specifici si possono avere dei problemi. 
-Per esempio, in un programma per il gioco del tennis se una funzione richiede un oggetto che implementa il metodo `play()`, e riceve in input un oggetto che non c'entra nulla con il tennis (per esempio un oggetto di tipo `GiocatoreDiScacchi`) che ha il metodo `play()`, si possono avere degli effetti indesiderati.
-
-### _Loose coupling_
-Il _loose coupling_ è la capacità di una variabile o un parametro di accettare l'assegnamento di oggetti aventi tipo diverso da quello della variabile o parametro, a patto che sia un sottotipo.
-
-```java
-Deck deck = new Deck();
-CardSource source = deck;
-List<Card> cards = drawCards(deck, 5);
-```
-
-### Interfacce multiple
-
-Tornando all'esempio, la classe `Deck` (che implementa `CardSource`) __può implementare anche altre interfacce__, come `Shuffable` o `Iterable<Card>`. 
-Al metodo precedente interessa solo che Deck abbia le capacità specificate in `CardSource`, se poi implementa anche altre interfaccie è ininfluente.
-
-{% plantuml style="width:100%" %}
-
-class Client1
-class Client2
-class Client3
-
-interface Iterable<Card> << interface >> {
-    + {abstract} Iterator<Card> iterator()
-}
-
-class Deck implements Iterable, Shuffable, CardSource {
-    + void shuffle()
-    + Card draw()
-    + boolean isEmpty()
-    + Iterator<Card> iterator()
-}
-
-interface Shuffable << interface >> {
-    + {abstract} void shuffle()
-}
-
-interface CardSource << interface >> {
-    + {abstract} Card draw()
-    + {abstract} boolean isEmpty()
-}
-
-Client2 ..> Iterable
-Client1 ..> Shuffable
-Client3 ..> Iterable
-Client3 ..> CardSource
-
-hide empty fields
-hide empty methods
-
-{% endplantuml %}
-
-### _Contract-based_ design vs programmazione difensiva
-
-Tornando alla <a href="#cardsource">specificazione</a> dell'interfaccia di `CardSource`, è possibile notare dei commenti in formato Javadoc che specificano le __precondizioni__ e le __postcondizioni__ (il valore di ritorno) del metodo. Secondo il ___contract-based_ design__, esiste un _"contratto"_ tra chi implementa un metodo e chi lo chiama.
-
-Per esempio, considerando il metodo `draw()`, __è responsabilità del chiamante__ verificare il soddisfacimento delle precondizioni (_"il mazzo non è vuoto"_) prima di invocare il metodo.
-Se `draw()` viene chiamato quando il mazzo è vuoto ci troviamo in una situazione di __violazione di contratto__ e può anche esplodere la centrale nucleare.
-
-Per specificare il contratto si possono utilizzare delle __asserzioni__ o il `@pre` nei __commenti__. 
-Le prime sono particolarmenti utili in fase di sviluppo perché interrompono l'esecuzione del programma in caso di violazione, ma vengono solitamente rimosse in favore delle seconde nella fase di deployment.
-
-Un'altro approccio è la __programmazione difensiva__ che al contrario delega la responsabilità del soddisfacimento delle precondizioni al _chiamato_, e non al chiamante.
-
-### Classi astratte
-
-Una classe astratta che implementa un'interfaccia __non deve necessariamente implementarne__ tutti i metodi, ma può delegarne l'implementazione alle sottoclassi impedendo l'istanziamento di oggetti del suo tipo.
-
-Le interfacce diminuiscono leggermente le performance, però migliorano estremamente la generalità (che aiutano l'espandibilità ed evolvibilità del programma), quindi vale la pena di utilizzarle.
-
-È possibile utilizzare le __classi astratte__ anche per classi complete, ma che __non ha senso che siano istanziate__.
-Un buon esempio sono le classi _utility_ della libreria standard di Java.
-
-#### Classe utility della libreria standard di Java
-
-Un esempio è __`Collections.shuffle(List<?> list)`__ che accetta una lista omogenea di elementi e la mischia.
-Il _tipo_ degli elementi è volutamente ignorato in quanto non è necessario conoscerlo per mischiarli.
-
-Per l'__ordinamento__, invece, è necessario conoscere il tipo degli oggetti in quanto bisogna confrontarli tra loro per poterli ordinare.
-La responsabilità della comparazione è però delegata all'oggetto, che deve aderire all'interfaccia `Comparable<T>`.
-
-__`Collections.sort(...)`__ ha, infatti, la seguente signature:
-```java
-public static <T extends Comparable<? super T>> void sort(List<T> list)
-```
-
-La notazione di generico __aggiunge dei vincoli__ su `T`, ovvero il tipo degli elementi contenuti nella lista:
-- `T extends Comparable<...>` significa che `T` deve estendere - e quindi implementare - l'interfaccia `Comparable<...>`;
-- `Comparable<? super T>` significa che tale interfaccia può essere implementata su un antenato di `T` (o anche `T` stesso).
-
-`Comparable` è un altro esempio di _interface segregation_: serve per specificare che un oggetto ha bisogno della caratteristica di essere comparabile.
-
-__Digressione__: la classe Collections era l'unico modo per definire dei metodi sulle interfacce (es: dare la possibilità di avere dei metodi sulle collezioni, ovvero liste, mappe, ecc), ma ora si possono utilizzare i metodi di default.
-
-# Analisi del testo naturale
-
-Come organizzare la partenza del design suddividendo in classi e responsabilità?
-
-I due approcci principali sono:
-- __pattern__: riconoscere una situazione comune da una data;
-- __TDD__: partendo dalla soluzione più semplice si definiscono classi solo all'occorrenza.
-
-Un'altra tecnica che vedremo è l'__estrazione dei nomi__ (noun extraction), per un certo senso _naive_ ma adatta in caso di storie complesse.
-
-## Noun extraction
-
-Basandosi sulle specifiche - come i commenti esplicativi delle User Stories - si parte dai sostantivi (o frasi sostantivizzate), si _sfolsticono_ con dei criteri, si cercano le relazioni tra loro e quindi si produce la gerarchia delle classi.
-
-Per spiegare il procedimento considereremo il seguente esempio:
-
-> - The __library__ contains __books__ and __journals__.
-> It may have several __copies__ of a given book. 
-> Some of the books are for __short term loans__ only.
-> All other books may be borrowed by any __library member__ for three __weeks__.
-> - __Memebers of the library__ can normally borrow up to six __items__ at a time, but __members of staff__ may borrow up to 12 items at one time.
-> Only member of staff may borrow journals.
-> - The __system__ must keep track of when books and journals are borrowed and returned, enforcing the __rules__ described above.
-
-Nell'esempio sopra sono stati evidenziati i sostantivi e le frasi sostantivizzate.
-
-### Criteri di _sfoltimento_
-
-I criteri di _sfoltimento_ servono per diminuire il numero di sostantivi considerando solo quelli rilevanti per risolvere il problema.
-In questa fase, in caso di dubbi è possibile rimandare la decisione a un momento successivo.
-
-Di seguito ne sono riportati alcuni:
-- __Ridondanza__: sinonimi, termini diversi per indicare lo stesso concetto. Anche se è stata utilizzata una locuzione diversa potrebbe essere comunque ridondante, sopratutto in lingue diverse dall'inglese in cui ci sono molti sinonimi. \\
-Nell'esempio: _library member_ e _member of the library_, _loan_ e _short term loan_.
-- __Vaghezza__: nomi generici, comuni a qualunque specifica; potrebbero essere sintomo di una _classe comune astratta_. \\
-Nell'esempio: _items_.
-- __Nomi di eventi e operazioni__: nomi che indicano azioni e non hanno un concetto di _stato_. \\
-Nell'esempio: _loan_.
-- __Metalinguaggio__: parti _statiche_ che fanno parte della logica del programma e che quindi non necessitano di essere rappresentati come classi. \\
-Nell'esempio: _system_, _rules_.
-- __Esterne al sistema__: concetti esterni o verità _"assolute"_ al di fuori del controllo del programma. \\
-Esempio: _library_, _week_ (una settimana ha 7 giorni).
-- __Attributi__: informazioni atomiche e primitive (stringhe, interi, ...) relative a una classe, che quindi non necessitano la creazione di una classe di per sé. \\
-Esempio: _name of the member_ (se ci fosse stato).
-
-Al termine di questa fase, si avrà una lista di classi _"certe"_ e _"incerte"_.
-In questo esempio, sono soppravvisuti i termini _journal_, _book_, _copy_ (of _book_), _library member_ e _member of staff_. 
-
-### Relazioni tra classi
-
-Il prossimo passo è definire le relazioni tra le classi.
-
-Inizialmente, si collegano con delle _linee_ (non frecce) senza specificare la direzione dell'associazione.
-Parliamo di __associazioni__ e non __attributi__ perché non è necessariamente vero che tutte le associazioni si trasformino in attributi.
-
-{% plantuml style="width: 90%" %}
-class Book
-class CopyOfBook
-class LibraryMember
-class StaffMember
-class Journal
-
-Journal -- StaffMember : borrows/returns
-Book -- CopyOfBook : is a copy
-CopyOfBook -- LibraryMember : borrows/returns
-CopyOfBook -- StaffMember : borrows/returns
-
-hide empty fields
-hide empty methods
-{% endplantuml %}
-
-Il prossimo passo è specificare le __cardinalità__ delle relazioni, come specificato dal linguaggio UML (opposto in questo aspetto al diagramma ER).
-La precisione richiesta in questo punto è soggettiva: da una parte, specificare puntualmente il numero massimo di elementi di una associazione può aiutare ad ottimizzare successivamente, dall'altra porta confusione.
-
-{% plantuml style="width: 90%" %}
-class Book
-class CopyOfBook
-class LibraryMember
-class StaffMember
-class Journal
-
-Journal "0..*" -- "0..1" StaffMember : borrows/returns
-Book "1" -- "1..*" CopyOfBook : is a copy
-CopyOfBook "0..*" -- "0..1" LibraryMember : borrows/returns
-CopyOfBook "0..*" -- "0..1" StaffMember : borrows/returns
-
-hide empty fields
-hide empty methods
-{% endplantuml %}
-
-Dopo aver ragionato sulle cardinalità, si iniziano a cercare __generalizzazioni__ e fattorizzazioni. 
-In questo caso, notiamo che:
-- `StaffMember` _è un_ `LibraryMember` con in più la possibilità di prendere `Journal`. 
-Inoltre, un altro indicatore è che hanno la stesso tipo di relazioni con gli altri oggetti.
-- `Items` è un termine generico per indicare `CopyOfBook` e `Journal`.
-
-{% plantuml style="width: 90%" %}
-class BorrowableItem
-class LibraryMember
-class Book
-class CopyOfBook extends BorrowableItem
-class StaffMember extends LibraryMember
-class Journal extends BorrowableItem
-
-Book "1" -- "1..*" CopyOfBook : is a copy
-BorrowableItem "0..*" -- "0..1" LibraryMember : borrows/returns
-
-hide empty fields
-hide empty methods
-{% endplantuml %}
-
-Distinguere `CopyOfBook` e `Journal` è inutile, perché di fatto un `Journal` _è una copia di_ un giornale.
-Si può quindi fattorizzare __rimuovendo la generalizzazione__, come mostrato di seguito.
-
-{% plantuml style="width: 90%" %}
-class Book
-class BorrowableItem
-class LibraryMember
-class StaffMember extends LibraryMember
-class Journal
-
-Book "0..1" - "1..*" BorrowableItem : is a copy
-BorrowableItem "0..*" -- "0..1" LibraryMember : borrows/returns
-BorrowableItem "1..*" - "0..1" Journal : is a copy
-
-hide empty fields
-hide empty methods
-{% endplantuml %}
-
-È imporante però preoccuparsi delle __cardinalità__ delle relazioni: è sì vero che un `BorrowableItem` può non _essere una copia di_ un `Book` e di un `Journal`, ma deve essere copia di _esattamente_ una delle due opzioni.
-UML prevede un __linguaggio OCL__ ([Object Constraint Language](https://en.wikipedia.org/wiki/Object_Constraint_Language)) per esprimere vincoli divesamente impossibili da esprimere in un diagramma.
-È anche possibile scrivere il _constraint_ in linguaggio naturale come __nota__.
diff --git a/book.toml b/book.toml
index 8c31f2b2991f3723a0eea6851aae4eb990317dcf..716a32deade27da2041a6c2215a0a51b3c41805e 100644
--- a/book.toml
+++ b/book.toml
@@ -7,6 +7,7 @@ title = "Ingegneria del software"
 
 [preprocessor.plantuml]
 plantuml-cmd = "plantuml"
+clickable-img = true
 
 [output.html]
 mathjax-support = true
diff --git a/src/07_progettazione/00_index.md b/src/07_progettazione/00_index.md
new file mode 100644
index 0000000000000000000000000000000000000000..23dc9522f6de2c6c7e52b0cf9b83d7a46f502ebe
--- /dev/null
+++ b/src/07_progettazione/00_index.md
@@ -0,0 +1,68 @@
+# Progettazione
+
+Durante le lezioni, per discutere di progettazione siamo partiti da un esempio di programma in C che stampa una canzone.
+Il codice considerato è completamente illegibile:
+
+```c
+#include <stdio.h>
+main(t,_,a)
+char *a;
+{
+return!0<t?t<3?main(-79,-13,a+main(-87,1-_,main(-86,0,a+1)+a)):
+1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13?
+main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t,
+"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#\
+;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
+q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
+){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
+iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
+;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
+}'+}##(!!/")
+:t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1)
+:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a,
+"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);
+} 
+```
+
+Successivamente abbiamo scomposto il codice per renderlo logicamente più sensato e facilmente modificabile, sono state __estratte le parti comuni__ e spostate in una funzione apposita, mentre le __parti mutabili sono state salvate in alcune strutture dati__; la canzone viene così stampata tramite un ciclo. 
+In questo modo scrivendo un codice più semplice siamo stati in grado di creare una soluzione più generale e più aperta ai cambiamenti.
+
+```java
+public class TwelveDaysOfChristmas {
+    static String[] days = {"first", "second", ..., "twelfth"};
+    static String[] gifts = { "a partdrige in a pear tree", "two turtle doves", ... };
+
+    static String firstLine(int day) {
+        return "On the " + days[day] +
+               " day of Christmas my true love gave to me:\n";
+    }
+
+    static String allGifts(int day) {
+        if (day == 0) {
+            return "and " + gifts[0];
+        } else {
+            return gifts[day] + "\n" + allGifts(day-1);
+        }
+    }
+
+    public static void main(String[] args) {
+        System.out.println(firstLine(0));
+        System.out.println(gifts[0]);
+        for (int day == 1; day < 12; day++) {
+            System.out.println(firstLine(day));
+            System.out.println(allGifts(day));
+        }
+    }
+}
+```
+
+È importante quindi __adottare la soluzione più semplice__ (che __non è quella più stupida__!) e una misura convenzionale per dire quanto una cosa è semplice - almeno in Università - si esprime in termini del tempo dedicato dal programmatore all'implementazione.
+Tale misura si sposa bene con il __TDD__, che richiede __brevi iterazioni__ di circa 10 minuti: se la feature attuale richiede più tempo è opportuno ridurre la portata scomponendo il problema.
+
+- [**Refactoring**](./01_refactoring.md): modifiche al codice senza nuove funzionalità;
+- [**Design knowledge**](./02_design-knowledge.md): dove mantenere la conoscenza del design?
+- [**Conoscenze preliminari**](./03_conoscenze-preliminari.md): object orientation, SOLID principles, reference escaping, encapsulation e information hiding, immutabilità, code smell
+- [**Principio Tell-Don't-Ask**](./04_tell-dont-ask.md)
+- [**Interface segregation**](./05_interface-segregation.md)
+- [**Esempio**](./06_esempio/00_index.md) applicando i principi precedenti
+- [**Analisi del testo naturale**](./07_analisi-testo-naturale.md) con _noun extraction_
diff --git a/src/07_progettazione/01_refactoring.md b/src/07_progettazione/01_refactoring.md
new file mode 100644
index 0000000000000000000000000000000000000000..300e41bdd44a37b41ee9428b1671ac895bf7d582
--- /dev/null
+++ b/src/07_progettazione/01_refactoring.md
@@ -0,0 +1,16 @@
+# Refactoring
+Durante il refactoring è opportuno rispettare le seguenti regole:
+- le __modifiche al codice non devono modificare le funzionalità__:
+il refactoring DEVE essere invisibile al cliente;
+- __non possono essere aggiunti test aggiuntivi__ rispetto alla fase verde appena raggiunta.
+
+Se la fase di refactoring sta richiedendo troppo tempo allora è possibile fare rollback all'ultima versione verde e __pianificare meglio__ l'attività di refactoring, per esempio scomponendolo in più step.
+Vale la regola del _"do it twice"_: il secondo approccio a un problema è solitamente più veloce e migliore.
+
+## Motivazioni
+
+Spesso le motivazioni dietro un refactoring sono:
+- precedente __design molto complesso e poco leggibile__, a causa della velocità del passare ad uno _scenario verde_;
+- __preparare il design di una funzionalità__ che non si integra bene in quello esistente; dopo aver raggiunto uno _scenario verde_ in una feature, è possibile che la feature successiva sia difficile da integrare. 
+In questo caso, se il _refactoring_ non è banale è bene fermarsi, tornare indietro e evolvere il codice per facilitare l'iterazione successiva (__design for change__). 
+- presenza di __debito tecnico__ su lavoro fatto in precendenza, ovvero debolezze e "scorciatoie" che ostacolano notevolmente evoluzioni future: _"ogni debito tecnico lo si ripaga con gli interessi"_.
diff --git a/src/07_progettazione/02_design-knowledge.md b/src/07_progettazione/02_design-knowledge.md
new file mode 100644
index 0000000000000000000000000000000000000000..8710c09c115a3014a33c4874b7145820f81103ac
--- /dev/null
+++ b/src/07_progettazione/02_design-knowledge.md
@@ -0,0 +1,21 @@
+# Design knowledge
+
+La design knowledge è la __conoscenza del design__ architetturale di un progetto. 
+È possibile utilizzare:
+- la __memoria__: non è efficace perché nel tempo si erode, specialmente in coppia;
+- i __documenti di design__ (linguaggio naturale o diagrammi): se non viene aggiornato di pari passo con il codice rimane disallineato, risultando più dannoso che d'aiuto.
+- le __piattaforme di discussione__ (version control, issue management): possono aiutare ma le informazioni sono sparse in luoghi diversi e di conseguenza difficili da reperire e rimane il problema di mantenere aggiornate queste informazioni.
+- gli __UML__: tramite diagrammi UML si è cercato di sfruttare l'approccio ___generative programming___, ovvero la generazione automatica del codice a partire da specificazioni di diagrammi.
+Con l'esperienza si è visto che non funziona.
+- il __codice__ stesso: tramite la lettura del codice è possibile capire il design ma è difficile rappresentare le ragioni della scelta.
+
+È bene sfruttare tutte le tecniche sopra proposte __combinandole__, partendo dal codice. \
+È inoltre importante scrivere documentazione per spiegare le ragioni dietro le scelte effettuate e non le scelte in sé, che si possono dedurre dal codice.
+
+## Condivisione
+
+Per condividere tali scelte di design (il _know how_) è possibile sfruttare:
+- __metodi__: con pratiche (come Agile) o addirittura l'object orientation stessa, che può essere un metodo astratto per condividere scelte di design.
+- __design pattern__: fondamentali per condividere scelte di design, sono utili anche per generare un vocabolario comune (sfruttiamo dei nomi riconosciuti da tutti per descrivere i ruoli dei componenti) e aiutano l'implementazione (i pattern hanno delle metodologie note per essere implementati). 
+I pattern non si concentrano sulle prestazioni di un particolare sistema ma sulla generalità e la riusabilità di soluzioni a problemi comuni;
+- __principi__: per esempio i principi SOLID.
diff --git a/src/07_progettazione/03_conoscenze-preliminari.md b/src/07_progettazione/03_conoscenze-preliminari.md
new file mode 100644
index 0000000000000000000000000000000000000000..4820c07e2ab7b73008f63884649749efdcd93689
--- /dev/null
+++ b/src/07_progettazione/03_conoscenze-preliminari.md
@@ -0,0 +1,110 @@
+# Conoscenze preliminari
+
+Prima di proseguire è bene richiamare concetti e termini fondamentali presumibilmente visti durante il corso di Programmazione II.
+
+## Object orientation
+
+Per essere definito _object oriented_, un linguaggio di programmazione deve soddisfare tre proprietà:
+- __ereditarietà__: ovvero la possibilità di poter definire una classe ereditando proprietà e comportamenti di un'altra classe.
+- __polimorfismo__: quando una classe può assumere diverse forme in base alle interfacce che implementa. 
+Il prof fa l'esempio del _tennista scacchista_: in un torneo di tennis è poco utile sostituire una persona che gioca a tennis ed è brava con gli scacchi (quindi una classe che implementa entrambe le interfacce) con una che gioca a scacchi.
+Il collegamento tra capacità e oggetto è fatto __a tempo di compilazione__: non è importante quindi se la capacità non è ancora definita;
+- __collegamento dinamico__: in Java il tipo concreto degli oggetti e quindi il problema di stabilire _quale metodo chiamare_ viene risolto durante l'esecuzione. 
+In C++ occorre esplicitare questo comportamento utilizzando la keyword `virtual`.
+
+## <a style="color: darkgreen">SOLID</a> principles
+
+Ci sono 5 parti che compongono questo principio:
+1. __<span style="color: darkgreen"><big>S</big></span>INGLE RESPONSIBILITY__: una classe, un solo scopo.
+Così facendo, le classi rimangono semplici e si agevola la riusabilità.
+2. __<span style="color: darkgreen"><big>O</big></span>PEN-CLOSE PRINCIPLE__:
+le classi devono essere aperte ai cambiamenti (_opened_) ma senza modificare le parti già consegnate e in produzione (_closed_).
+Il refactoring è comunque possibile, ma deve essere preferibile estendere la classe attuale.
+3. __<span style="color: darkgreen"><big>L</big></span>ISKOV SUBSTITUTION PRINCIPLE__:
+c'è la garanzia che le caratteristiche eredidate dalla classe padre continuinino ad esistere nelle classi figlie.
+Questo concetto si collega all'aspetto __contract-based__ del metodo Agile: le _precondizioni_ di un metodo di una classe figlia devono essere ugualmente o meno restrittive del metodo della classe padre.
+Al contrario, le _postcondizioni_ di un metodo della classe figlia non possono garantire più di quello che garantiva il metodo nella classe padre.
+Fare _casting_ bypassa queste regole.
+4. __<span style="color: darkgreen"><big>I</big></span>NTERFACE SEGREGATION__:
+più le capacità e competenze di una classe sono frammentate in tante interfacce più è facile utilizzarla in contesti differenti.
+In questo modo un client non dipende da metodi che non usa. 
+Meglio quindi avere __tante interfacce specifiche__ e piccole (composte da pochi metodi), piuttosto che poche, grandi e generali. 
+5. __<span style="color: darkgreen"><big>D</big></span>EPENDENCY INVERSION__:
+il codice dal quale una classe dipende non deve essere più __concreto__ di tale classe.
+Per esempio, se il _telaio della FIAT 500_ dipende da uno specifico motore, è possibile utilizzarlo solo per quel specifico motore.
+Se invece il telaio dipende da _un_ concetto di motore, non c'è questa limitazione.
+In conlusione, le classi concrete devono tendenzialmente dipendere da classi astratte e non da altre classi concrete.
+
+## Reference escaping
+
+Il _reference escaping_ è una violazione dell'incapsulamento. 
+
+Può capitare, per esempio: 
+- quando un getter ritorna un riferimento a un segreto;
+```java
+public Deck {
+    private List<Card> cards;
+        
+    public List<Card> getCards() {
+        return this.cards;
+    }
+}
+```
+- quando un setter assegna a un segreto un riferimento che gli viene passato;
+```java
+public Deck {
+    private List<Card> cards;
+
+    public setCards(List<Card> cards) {
+        this.cards = cards;
+    }
+}
+```
+
+- quando il costruttore assegna al segreto un riferimento che gli viene passato;
+```java
+public Deck {
+    private List<Card> cards;
+
+    public Deck(List<Card> cards) {
+        this.cards = cards;
+    }
+}
+```
+
+## Encapsulation e information hiding
+
+__Legge di Parnas (L8)__.
+> _Solo ciò che è nascosto può essere cambiato liberamente e senza pericoli._
+
+Lo stato mostrato all'esterno non può essere modificato, mentre quello nascosto sì.
+
+Questo principio serve per __facilitare la comprensione del codice__ e renderne più facile la modifica parziale senza fare danni.
+
+## Immutabilità
+
+Una classe è immutabile quando non c'è modo di modificare lo stato di ogni suo oggetto dopo la creazione.
+
+Per assicurare tale proprietà è necessario:
+- __non fornire metodi di modifica__ allo stato;
+- avere tutti gli __attributi privati__ per i tipi potenzialmente mutabili (come `List<T>`);
+- avere tutti gli __attributi final__ se non già privati;
+- assicurare l'__accesso esclusivo__ a tutte le parti non mutabili, ovvero non avere reference escaping.
+
+## Code smell
+
+I _code smell_ sono dei segnali che suggeriscono problemi nella progettazione del codice. 
+Di seguito ne sono elencati alcuni:
+- __codice duplicato__: si può fare per arrivare velocemente al verde ma è da togliere con il refactoring. 
+Le parti di codice in comune possono quindi essere fattorizzate.
+- __metodi troppo lunghi__: sono poco leggibili e poco riusabili;
+- __troppi livelli di indentazione__: scarsa leggibilità e riusabilità, è bene fattorizzare il codice;
+- __troppi attributi__: suggerisce che la classe non rispetta la single responsability, ovvero fa troppe cose;
+- __lunghe sequenze di _if-else_ o _switch___;
+- __classe troppo grande__;
+- __lista parametri troppo lunga__;
+- __numeri _magici___: è importante assegnare alle costanti numeriche all'interno del codice un nome per comprendere meglio il loro scopo;
+- __commenti che spiegano cosa fa il codice__: indicazione che il codice non è abbastanza chiaro;
+- __nomi oscuri o inconsistenti__;
+- __codice morto__: nel programma non deve essere presente del codice irraggiungibile o commentato. Utilizzando strumenti di versioning è possibile riaccedere a codice precedentemente scritto con facilità.
+- __getter e setter__: vedi principio di __tell don't ask__.
diff --git a/src/07_progettazione/04_tell-dont-ask.md b/src/07_progettazione/04_tell-dont-ask.md
new file mode 100644
index 0000000000000000000000000000000000000000..b7688cdba6a20b0072a6e541ceb98d1c502319b3
--- /dev/null
+++ b/src/07_progettazione/04_tell-dont-ask.md
@@ -0,0 +1,61 @@
+# <a href="https://martinfowler.com/bliki/TellDontAsk.html">Principio Tell-Don't-Ask</a>
+
+![Tell-Don't-Ask](/assets/07_tell-dont-ask.png)
+
+> Non chiedere i dati, ma dì cosa vuoi che si faccia sui dati
+
+Il responsabile di un'informazione è anche responsabile di tutte le operazioni su quell'informazione.
+
+Il principio _Tell-Don't-Ask_ sancisce che piuttosto di __chiedere__ ad un oggetto dei dati e fare delle operazioni con quei dati è meglio __dire__ a questo oggetto cosa fare con i dati che contiene. 
+
+## Esempio
+
+Se desideriamo stampare il contenuto di tutte le carte in un mazzo possiamo partire da questo codice.
+
+```java
+class Main {
+    public static void main(String[] args) {
+        Deck deck = new Deck();
+        Card card = new Card();
+
+        card.setSuit(Suit.DIAMONDS);
+        card.setRank(Rank.THREE);
+        deck.getCards().add(card);
+        deck.getCards().add(new Card());    // <-- !!!
+
+        System.out.println("There are " + deck.getCards().size() + " cards:");
+        for (Card currentCard : deck.getCards()) {
+            System.out.println(
+                currentCard.getRank() + 
+                " of " + 
+                currentCard.getSuit()
+            );
+        }
+    }
+}
+```
+
+All'interno del ciclo reperiamo gli attributi della carta e li utilizziamo per stampare le sue informazioni.
+Inoltre, nella riga evidenziata viene aggiunta una carta senza settare i suoi attributi. 
+La responsabilità della gestione dell'informazione della carta è quindi __erroneamente delegata__ alla classe chiamante.
+
+Per risolvere, è possibile trasformare la classe `Card` nel seguente modo:
+
+```java
+class Card {
+    private Suit suit;
+    private Rank rank;
+
+    public Card(@NotNull Suit s, @NotNull Rank r) {
+        suit = s;
+        rank = r;
+    }
+
+    @Override
+    public String toString() {
+        return rank + " of " + suit;
+    }
+}
+```
+
+l'informazione viene ora interamente gestita dalla classe `Card`, che la gestisce nel metodo `toString()` per ritornare la sua rappresentazione testuale.
diff --git a/src/07_progettazione/05_interface-segregation.md b/src/07_progettazione/05_interface-segregation.md
new file mode 100644
index 0000000000000000000000000000000000000000..22dcacce38c285b6a41c6da97b24b52e91fc6611
--- /dev/null
+++ b/src/07_progettazione/05_interface-segregation.md
@@ -0,0 +1,7 @@
+# Interface segregation
+
+Le interfacce possono _"nascere"_ tramite due approcci: 
+- __up front__: scrivere direttamente l'interfaccia;
+- __down front__: scrivere il codice e quindi tentare di estrarne un'interfaccia.
+
+L'approccio down-front si adatta meglio al TDD ed è illustrato nel seguente esempio.
diff --git a/src/07_progettazione/06_esempio/00_index.md b/src/07_progettazione/06_esempio/00_index.md
new file mode 100644
index 0000000000000000000000000000000000000000..cfa990e9aa5fe07e04838ed37ecab1320dc8e514
--- /dev/null
+++ b/src/07_progettazione/06_esempio/00_index.md
@@ -0,0 +1,10 @@
+# Esempio con gerarchia Card / Deck
+
+In questo esempio sono trattati numerosi principi, come l'_interface segreagation_, _linking dinamico/statico_, _implementazione di interfacce multiple_ e il _contract based design_ vs la _programmazione difensiva_.
+
+- [**Interface segregation**](./01_interface-segregation.md)
+- [**Collegamento statico e dinamico**](./02_collegamento-statico-dinamico.md)
+- [**Loose coupling**](./03_loose-coupling.md)
+- [**Interfacce multiple**](./04_interfacce-multiple.md)
+- [**_Contract-based_ design vs programmazione difensiva**](./05_contract-based.md)
+- [**Classi astratte**](./06_classi-astratte.md)
diff --git a/src/07_progettazione/06_esempio/01_interface-segregation.md b/src/07_progettazione/06_esempio/01_interface-segregation.md
new file mode 100644
index 0000000000000000000000000000000000000000..0675e34edebde6df709590d550d07211c34b97e2
--- /dev/null
+++ b/src/07_progettazione/06_esempio/01_interface-segregation.md
@@ -0,0 +1,48 @@
+# Interface segregation all'opera
+
+```java
+public static List<Card> drawCards(Deck deck, int number) {
+    List<Card> result = new ArrayList<>();
+    for (int i = 0; i < number && !deck.isEmpty(); i++) {
+        result.add(deck.draw());
+    }
+    return result;
+}
+```
+
+Consideriamo il metodo `drawCards` che prende come parametri un `Deck` e un intero. \
+Le __uniche competenze__ riconosciute a `Deck` sono l'indicazione _se è vuoto_ (`isEmpty()`) e il _pescare una carta_ dal mazzo (`draw()`).
+`Deck` può quindi __implementare un'interfaccia__ che mette a disposizione queste capacità.
+
+È possibile modificare il metodo in modo da accettare un qualunque oggetto in grado di eseguire le operazioni sopra elencate, ovvero che implementi l'interfaccia __`CardSource`__. 
+
+<a id="cardsource" style="display:none;"></a>
+
+```java
+public interface CardSource {
+    /**
+     * @return The next available card.
+     * @pre !isEmpty()
+     */
+    Card draw();
+
+    /**
+     * @return True if there is no card in the source
+     */
+    boolean isEmpty();
+}
+```
+
+```java
+public class Deck implements CardSource { ... }
+```
+
+```java
+public static List<Card> drawCards(CardSource deck, int number) {
+    List<Card> result = new ArrayList<>();
+    for (int i = 0; i < number && !deck.isEmpty(); i++) {
+        result.add(deck.draw());
+    }
+    return result;
+}
+```
diff --git a/src/07_progettazione/06_esempio/02_collegamento-statico-dinamico.md b/src/07_progettazione/06_esempio/02_collegamento-statico-dinamico.md
new file mode 100644
index 0000000000000000000000000000000000000000..61782d566c5ca5aeba7ec6ce9750333446dcc2ea
--- /dev/null
+++ b/src/07_progettazione/06_esempio/02_collegamento-statico-dinamico.md
@@ -0,0 +1,8 @@
+# Collegamento statico e dinamico
+
+Notare come è necessario specificare __staticamente__ che `Deck` implementi `CardSource`, ovvero occorre forzare la dichiarazione del fatto che `Deck` sia un _sottotipo_ di `CardSource` (Java è strong typed) e quindi sia possibile mettere un oggetto `Deck` ovunque sia richiesto un oggetto `CardSource`. \
+In altri linguaggi come __Go__ c'è una __maggiore dinamicità__ perché non c'è bisogno di specificare nel codice che un oggetto è sottotipo di qualcos'altro, è sufficiente solo che implementi un metodo con la stessa signature.
+Il controllo che l'oggetto passato ad una funzione abbia le capacità necessarie avviene a runtime e non prima.
+
+Un problema della troppa dinamicità (__duck typing__) è che se i metodi di un oggetto non hanno dei nomi abbastanza specifici si possono avere dei problemi. 
+Per esempio, in un programma per il gioco del tennis se una funzione richiede un oggetto che implementa il metodo `play()`, e riceve in input un oggetto che non c'entra nulla con il tennis (per esempio un oggetto di tipo `GiocatoreDiScacchi`) che ha il metodo `play()`, si possono avere degli effetti indesiderati.
diff --git a/src/07_progettazione/06_esempio/03_loose-coupling.md b/src/07_progettazione/06_esempio/03_loose-coupling.md
new file mode 100644
index 0000000000000000000000000000000000000000..0ba63ea584e25acca485c9890c4f45ab5bd1f10f
--- /dev/null
+++ b/src/07_progettazione/06_esempio/03_loose-coupling.md
@@ -0,0 +1,8 @@
+# _Loose coupling_
+Il _loose coupling_ è la capacità di una variabile o un parametro di accettare l'assegnamento di oggetti aventi tipo diverso da quello della variabile o parametro, a patto che sia un sottotipo.
+
+```java
+Deck deck = new Deck();
+CardSource source = deck;
+List<Card> cards = drawCards(deck, 5);
+```
diff --git a/src/07_progettazione/06_esempio/04_interfacce-multiple.md b/src/07_progettazione/06_esempio/04_interfacce-multiple.md
new file mode 100644
index 0000000000000000000000000000000000000000..831f1eabdb27703e49c716ce2d6d823f7510b37c
--- /dev/null
+++ b/src/07_progettazione/06_esempio/04_interfacce-multiple.md
@@ -0,0 +1,42 @@
+# Interfacce multiple
+
+Tornando all'esempio, la classe `Deck` (che implementa `CardSource`) __può implementare anche altre interfacce__, come `Shuffable` o `Iterable<Card>`. 
+Al metodo precedente interessa solo che Deck abbia le capacità specificate in `CardSource`, se poi implementa anche altre interfaccie è ininfluente.
+
+```plantuml
+@startuml
+scale 1024 width
+
+class Client1
+class Client2
+class Client3
+
+interface Iterable<Card> << interface >> {
+    + {abstract} Iterator<Card> iterator()
+}
+
+class Deck implements Iterable, Shuffable, CardSource {
+    + void shuffle()
+    + Card draw()
+    + boolean isEmpty()
+    + Iterator<Card> iterator()
+}
+
+interface Shuffable << interface >> {
+    + {abstract} void shuffle()
+}
+
+interface CardSource << interface >> {
+    + {abstract} Card draw()
+    + {abstract} boolean isEmpty()
+}
+
+Client2 ..> Iterable
+Client1 ..> Shuffable
+Client3 ..> Iterable
+Client3 ..> CardSource
+
+hide empty fields
+hide empty methods
+@enduml
+```
\ No newline at end of file
diff --git a/src/07_progettazione/06_esempio/05_contract-based.md b/src/07_progettazione/06_esempio/05_contract-based.md
new file mode 100644
index 0000000000000000000000000000000000000000..d04decba42dc5dfbbf95e060b68c56f7ee9fd5a3
--- /dev/null
+++ b/src/07_progettazione/06_esempio/05_contract-based.md
@@ -0,0 +1,11 @@
+# _Contract-based_ design vs programmazione difensiva
+
+Tornando alla [specificazione](./01_interface-segregation.md#cardsource) dell'interfaccia di `CardSource`, è possibile notare dei commenti in formato Javadoc che specificano le __precondizioni__ e le __postcondizioni__ (il valore di ritorno) del metodo. Secondo il ___contract-based_ design__, esiste un _"contratto"_ tra chi implementa un metodo e chi lo chiama.
+
+Per esempio, considerando il metodo `draw()`, __è responsabilità del chiamante__ verificare il soddisfacimento delle precondizioni (_"il mazzo non è vuoto"_) prima di invocare il metodo.
+Se `draw()` viene chiamato quando il mazzo è vuoto ci troviamo in una situazione di __violazione di contratto__ e può anche esplodere la centrale nucleare.
+
+Per specificare il contratto si possono utilizzare delle __asserzioni__ o il `@pre` nei __commenti__. 
+Le prime sono particolarmenti utili in fase di sviluppo perché interrompono l'esecuzione del programma in caso di violazione, ma vengono solitamente rimosse in favore delle seconde nella fase di deployment.
+
+Un'altro approccio è la __programmazione difensiva__ che al contrario delega la responsabilità del soddisfacimento delle precondizioni al _chiamato_, e non al chiamante.
diff --git a/src/07_progettazione/06_esempio/06_classi-astratte.md b/src/07_progettazione/06_esempio/06_classi-astratte.md
new file mode 100644
index 0000000000000000000000000000000000000000..22795cfb6a67597fb3d533743b76c05757e8970f
--- /dev/null
+++ b/src/07_progettazione/06_esempio/06_classi-astratte.md
@@ -0,0 +1,29 @@
+# Classi astratte
+
+Una classe astratta che implementa un'interfaccia __non deve necessariamente implementarne__ tutti i metodi, ma può delegarne l'implementazione alle sottoclassi impedendo l'istanziamento di oggetti del suo tipo.
+
+Le interfacce diminuiscono leggermente le performance, però migliorano estremamente la generalità (che aiutano l'espandibilità ed evolvibilità del programma), quindi vale la pena di utilizzarle.
+
+È possibile utilizzare le __classi astratte__ anche per classi complete, ma che __non ha senso che siano istanziate__.
+Un buon esempio sono le classi _utility_ della libreria standard di Java.
+
+#### Classe utility della libreria standard di Java
+
+Un esempio è __`Collections.shuffle(List<?> list)`__ che accetta una lista omogenea di elementi e la mischia.
+Il _tipo_ degli elementi è volutamente ignorato in quanto non è necessario conoscerlo per mischiarli.
+
+Per l'__ordinamento__, invece, è necessario conoscere il tipo degli oggetti in quanto bisogna confrontarli tra loro per poterli ordinare.
+La responsabilità della comparazione è però delegata all'oggetto, che deve aderire all'interfaccia `Comparable<T>`.
+
+__`Collections.sort(...)`__ ha, infatti, la seguente signature:
+```java
+public static <T extends Comparable<? super T>> void sort(List<T> list)
+```
+
+La notazione di generico __aggiunge dei vincoli__ su `T`, ovvero il tipo degli elementi contenuti nella lista:
+- `T extends Comparable<...>` significa che `T` deve estendere - e quindi implementare - l'interfaccia `Comparable<...>`;
+- `Comparable<? super T>` significa che tale interfaccia può essere implementata su un antenato di `T` (o anche `T` stesso).
+
+`Comparable` è un altro esempio di _interface segregation_: serve per specificare che un oggetto ha bisogno della caratteristica di essere comparabile.
+
+__Digressione__: la classe Collections era l'unico modo per definire dei metodi sulle interfacce (es: dare la possibilità di avere dei metodi sulle collezioni, ovvero liste, mappe, ecc), ma ora si possono utilizzare i metodi di default.
diff --git a/src/07_progettazione/07_analisi-testo-naturale.md b/src/07_progettazione/07_analisi-testo-naturale.md
new file mode 100644
index 0000000000000000000000000000000000000000..205d29a5367c21e109a1dcbfddf19f25644d6ce3
--- /dev/null
+++ b/src/07_progettazione/07_analisi-testo-naturale.md
@@ -0,0 +1,148 @@
+# Analisi del testo naturale
+
+Come organizzare la partenza del design suddividendo in classi e responsabilità?
+
+I due approcci principali sono:
+- __pattern__: riconoscere una situazione comune da una data;
+- __TDD__: partendo dalla soluzione più semplice si definiscono classi solo all'occorrenza.
+
+Un'altra tecnica che vedremo è l'__estrazione dei nomi__ (noun extraction), per un certo senso _naive_ ma adatta in caso di storie complesse.
+
+## Noun extraction
+
+Basandosi sulle specifiche &mdash; come i commenti esplicativi delle User Stories &mdash; si parte dai sostantivi (o frasi sostantivizzate), si _sfolsticono_ con dei criteri, si cercano le relazioni tra loro e quindi si produce la gerarchia delle classi.
+
+Per spiegare il procedimento considereremo il seguente esempio:
+
+> - _The __library__ contains __books__ and __journals__.
+> It may have several __copies__ of a given book. 
+> Some of the books are for __short term loans__ only.
+> All other books may be borrowed by any __library member__ for three __weeks__._
+> - ___Members of the library__ can normally borrow up to six __items__ at a time, but __members of staff__ may borrow up to 12 items at one time.
+> Only member of staff may borrow journals._
+> - _The __system__ must keep track of when books and journals are borrowed and returned, enforcing the __rules__ described above._
+
+Nell'esempio sopra sono stati evidenziati i sostantivi e le frasi sostantivizzate.
+
+### Criteri di _sfoltimento_
+
+I criteri di _sfoltimento_ servono per diminuire il numero di sostantivi considerando solo quelli rilevanti per risolvere il problema.
+In questa fase, in caso di dubbi è possibile rimandare la decisione a un momento successivo.
+
+Di seguito ne sono riportati alcuni:
+- __Ridondanza__: sinonimi, termini diversi per indicare lo stesso concetto. Anche se è stata utilizzata una locuzione diversa potrebbe essere comunque ridondante, sopratutto in lingue diverse dall'inglese in cui ci sono molti sinonimi. \
+Nell'esempio: _library member_ e _member of the library_, _loan_ e _short term loan_.
+- __Vaghezza__: nomi generici, comuni a qualunque specifica; potrebbero essere sintomo di una _classe comune astratta_. \
+Nell'esempio: _items_.
+- __Nomi di eventi e operazioni__: nomi che indicano azioni e non hanno un concetto di _stato_. \
+Nell'esempio: _loan_.
+- __Metalinguaggio__: parti _statiche_ che fanno parte della logica del programma e che quindi non necessitano di essere rappresentati come classi. \
+Nell'esempio: _system_, _rules_.
+- __Esterne al sistema__: concetti esterni o verità _"assolute"_ al di fuori del controllo del programma. \
+Esempio: _library_, _week_ (una settimana ha 7 giorni).
+- __Attributi__: informazioni atomiche e primitive (stringhe, interi, ...) relative a una classe, che quindi non necessitano la creazione di una classe di per sé. \
+Esempio: _name of the member_ (se ci fosse stato).
+
+Al termine di questa fase, si avrà una lista di classi _"certe"_ e _"incerte"_.
+In questo esempio, sono soppravvisuti i termini _journal_, _book_, _copy_ (of _book_), _library member_ e _member of staff_. 
+
+### Relazioni tra classi
+
+Il prossimo passo è definire le relazioni tra le classi.
+
+Inizialmente, si collegano con delle _linee_ (non frecce) senza specificare la direzione dell'associazione.
+Parliamo di __associazioni__ e non __attributi__ perché non è necessariamente vero che tutte le associazioni si trasformino in attributi.
+
+```plantuml
+@startuml
+scale 1024 width
+
+class Book
+class CopyOfBook
+class LibraryMember
+class StaffMember
+class Journal
+
+Journal -- StaffMember : borrows/returns
+Book -- CopyOfBook : is a copy
+CopyOfBook -- LibraryMember : borrows/returns
+CopyOfBook -- StaffMember : borrows/returns
+
+hide empty fields
+hide empty methods
+@enduml
+```
+
+Il prossimo passo è specificare le __cardinalità__ delle relazioni, come specificato dal linguaggio UML (opposto in questo aspetto al diagramma ER).
+La precisione richiesta in questo punto è soggettiva: da una parte, specificare puntualmente il numero massimo di elementi di una associazione può aiutare ad ottimizzare successivamente, dall'altra porta confusione.
+
+```plantuml
+@startuml
+scale 1024 width
+
+class Book
+class CopyOfBook
+class LibraryMember
+class StaffMember
+class Journal
+
+Journal "0..*" -- "0..1" StaffMember : borrows/returns
+Book "1" -- "1..*" CopyOfBook : is a copy
+CopyOfBook "0..*" -- "0..1" LibraryMember : borrows/returns
+CopyOfBook "0..*" -- "0..1" StaffMember : borrows/returns
+
+hide empty fields
+hide empty methods
+@enduml
+```
+
+Dopo aver ragionato sulle cardinalità, si iniziano a cercare __generalizzazioni__ e fattorizzazioni. 
+In questo caso, notiamo che:
+- `StaffMember` _è un_ `LibraryMember` con in più la possibilità di prendere `Journal`. 
+Inoltre, un altro indicatore è che hanno la stesso tipo di relazioni con gli altri oggetti.
+- `Items` è un termine generico per indicare `CopyOfBook` e `Journal`.
+
+```plantuml
+@startuml
+scale 1024 width
+
+class BorrowableItem
+class LibraryMember
+class Book
+class CopyOfBook extends BorrowableItem
+class StaffMember extends LibraryMember
+class Journal extends BorrowableItem
+
+Book "1" -- "1..*" CopyOfBook : is a copy
+BorrowableItem "0..*" -- "0..1" LibraryMember : borrows/returns
+
+hide empty fields
+hide empty methods
+@enduml
+```
+
+Distinguere `CopyOfBook` e `Journal` è inutile, perché di fatto un `Journal` _è una copia di_ un giornale.
+Si può quindi fattorizzare __rimuovendo la generalizzazione__, come mostrato di seguito.
+
+```plantuml
+@startuml
+scale 1024 width
+
+class Book
+class BorrowableItem
+class LibraryMember
+class StaffMember extends LibraryMember
+class Journal
+
+Book "0..1" - "1..*" BorrowableItem : is a copy
+BorrowableItem "0..*" -- "0..1" LibraryMember : borrows/returns
+BorrowableItem "1..*" - "0..1" Journal : is a copy
+
+hide empty fields
+hide empty methods
+@enduml
+```
+
+È imporante però preoccuparsi delle __cardinalità__ delle relazioni: è sì vero che un `BorrowableItem` può non _essere una copia di_ un `Book` e di un `Journal`, ma deve essere copia di _esattamente_ una delle due opzioni.
+UML prevede un __linguaggio OCL__ ([Object Constraint Language](https://en.wikipedia.org/wiki/Object_Constraint_Language)) per esprimere vincoli divesamente impossibili da esprimere in un diagramma.
+È anche possibile scrivere il _constraint_ in linguaggio naturale come __nota__.
diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index fe1290fb9fc897257c8fee3ec57eb83270b7443c..be67256a77bcf68addf63c6c1ffaa0bfefadbacf 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -1,6 +1,6 @@
 # Summary
 
-# 1. Prodotto e processo
+# Prodotto e processo
 
 - [Ingegneria, qualità e processi](./01_introduzione/00_index.md)
     - [Informazioni logistiche](./01_introduzione/01_logistica.md)
@@ -56,8 +56,23 @@
         - [Build automation](./06_git-workflow/04_strumenti-opensource/01_build-automation.md)
         - [Bug tracking](./06_git-workflow/04_strumenti-opensource/02_bug-tracking.md)
 
-# 2. Progettazione e implementazione
+# Progettazione e implementazione
 
-# 3. Verifica e convalida
+- [Progettazione](./07_progettazione/00_index.md)
+    - [Refactoring](./07_progettazione/01_refactoring.md)
+    - [Design knowledge](./07_progettazione/02_design-knowledge.md)
+    - [Conoscenze preliminari](./07_progettazione/03_conoscenze-preliminari.md)
+    - [Principio Tell-Don't-Ask](./07_progettazione/04_tell-dont-ask.md)
+    - [Interface segregation](./07_progettazione/05_interface-segregation.md)
+    - [Esempio](./07_progettazione/06_esempio/00_index.md)
+        - [Interface segregation all'opera](./07_progettazione/06_esempio/01_interface-segregation.md)
+        - [Collegamento statico e dinamico](./07_progettazione/06_esempio/02_collegamento-statico-dinamico.md)
+        - [Loose coupling](./07_progettazione/06_esempio/03_loose-coupling.md)
+        - [Interfacce multiple](./07_progettazione/06_esempio/04_interfacce-multiple.md)
+        - [Contract-based design vs programmazione difensiva](./07_progettazione/06_esempio/05_contract-based.md)
+        - [Classi astratte](./07_progettazione/06_esempio/06_classi-astratte.md)
+    - [Analisi del testo naturale](./07_progettazione/07_analisi-testo-naturale.md)
 
-# 4. Reti di Petri
+# Verifica e convalida
+
+# Reti di Petri