modulo 03 di 24 / Ore 0-20
Moduli 1-8 / Checkpoint 20 ore
Esempio guidato: cosa succede quando cambia la persistenza
Usare il cambio di persistenza come esempio guidato per capire perché UI, casi d'uso, dominio e infrastruttura devono avere confini chiari.
Esempio guidato: cosa succede quando cambia la persistenza
Una delle domande più utili per capire l’architettura è:
cosa succede se cambio il modo in cui salvo i dati?
Nel Registro fragile il salvataggio può essere dentro gli event listener:
localStorage.setItem("strumenti", JSON.stringify(strumenti));
localStorage.setItem("prestiti", JSON.stringify(prestiti));
Funziona.
Ma cosa succede se domani vogliamo usare un file JSON, una piccola API o un database?
Questa lezione serve a vedere il costo reale del cambiamento.
Obiettivo della lezione
Alla fine devi avere:
- una lista dei punti in cui il codice usa
localStorage; - una distinzione tra persistenza, dominio, UI e caso d’uso;
- una tabella di ciò che cambierebbe passando a JSON o API;
- una prima idea di archivio sostituibile;
- una frase che spiega perché il problema non è
localStorage, ma la dipendenza diffusa.
Non devi ancora implementare un adapter completo. Devi capire perché servirà.
Scenario iniziale
Oggi il Registro salva nel browser.
Quando registri un prestito, il codice fragile può fare così:
strumento.stato = "in_prestito";
prestiti.push(nuovoPrestito);
localStorage.setItem("strumenti", JSON.stringify(strumenti));
localStorage.setItem("prestiti", JSON.stringify(prestiti));
Questo blocco sembra innocuo.
Però, se sta dentro il click del bottone, la UI conosce troppe cose:
- conosce l’array
strumenti; - conosce l’array
prestiti; - conosce il formato JSON;
- conosce le chiavi
"strumenti"e"prestiti"; - conosce il momento in cui salvare;
- conosce anche parte delle regole di modifica dello stato.
La UI non sta solo mostrando una pagina.
Sta partecipando alla persistenza.
Il cambio richiesto
Immagina una richiesta del docente:
Vorrei esportare i dati in un file JSON, così posso consegnarli o importarli
in un altro browser.
Oppure:
Vorrei usare una piccola API locale, così più postazioni vedono gli stessi dati.
Nel codice fragile la prima reazione è cercare ogni punto in cui appare:
localStorage
JSON.stringify
JSON.parse
Probabilmente li trovi:
- al caricamento iniziale;
- dopo la registrazione di uno strumento;
- dopo un prestito;
- dopo la chiusura di un prestito;
- dopo un cambio stato;
- dopo una segnalazione di guasto;
- in eventuali funzioni di reset;
- in eventuali test manuali.
Più punti trovi, più il cambio è costoso.
Il problema non è localStorage
localStorage non è sbagliato.
È adatto a un laboratorio iniziale:
- è disponibile nel browser;
- non richiede server;
- permette di vedere subito la persistenza;
- è semplice da ispezionare con gli strumenti sviluppatore.
Il problema nasce quando il resto del progetto dipende direttamente da localStorage.
Questo è fragile:
function puoEsserePrestato(idStrumento) {
const dati = localStorage.getItem("strumenti");
const strumenti = JSON.parse(dati);
const strumento = strumenti.find((item) => item.id === idStrumento);
return strumento.stato === "disponibile";
}
La funzione sembra controllare una regola, ma in realtà:
- legge dal browser;
- conosce la chiave
"strumenti"; - conosce il formato salvato;
- cerca lo strumento;
- applica la regola.
Sono troppe responsabilità.
Una regola più pulita ragiona su uno strumento già disponibile:
function puoEsserePrestato(strumento) {
return strumento.stato === "disponibile";
}
Questa funzione non sa nulla di browser, file, database o API.
Per questo è più facile da testare.
Che cosa dovrebbe restare stabile
Se cambio persistenza, alcune cose non dovrebbero cambiare:
| Parte | Perché dovrebbe restare stabile |
|---|---|
Strumento |
il concetto di strumento non dipende da dove salvo |
Prestito |
il ciclo del prestito non dipende da localStorage |
| Regola sul guasto | uno strumento guasto non diventa prestabile perché cambio archivio |
| Regola sul già in prestito | vale in memoria, JSON, API o database |
RegistraPrestito |
il flusso dovrebbe restare simile |
| Test del dominio | devono continuare a verificare le regole |
Altre cose possono cambiare:
| Parte | Perché può cambiare |
|---|---|
chiavi di localStorage |
sono dettagli tecnici |
| formato JSON salvato | è formato esterno |
| endpoint API | riguarda comunicazione esterna |
| mapping dei dati | traduce tra esterno e dominio |
| gestione di dati mancanti | dipende dal tipo di archivio |
Questa distinzione è architettura pratica.
Primo schizzo di archivio
Più avanti useremo un’idea semplice:
ArchivioStrumenti
trovaPerId(id)
salva(strumento)
cerca(filtri)
elenco()
All’inizio può essere un oggetto in memoria.
Poi può diventare localStorage.
Poi può diventare JSON o API.
Il punto è che un caso d’uso dovrebbe ragionare così:
1. chiedo all'archivio lo strumento
2. applico le regole
3. chiedo all'archivio di salvare lo strumento aggiornato
4. chiedo all'archivio prestiti di salvare il nuovo prestito
Non così:
1. leggo localStorage
2. faccio JSON.parse
3. cerco nello stesso array
4. modifico l'array
5. faccio JSON.stringify
6. riscrivo localStorage
Il secondo elenco è infrastruttura travestita da caso d’uso.
Esempio di separazione minima
Prima:
function salvaDopoPrestito(strumenti, prestiti) {
localStorage.setItem("strumenti", JSON.stringify(strumenti));
localStorage.setItem("prestiti", JSON.stringify(prestiti));
}
Questo è ancora legato a localStorage, ma almeno il dettaglio è concentrato.
Meglio ancora, più avanti:
const archivioStrumenti = {
salva(strumento) {
// dettaglio tecnico qui dentro
},
trovaPerId(id) {
// dettaglio tecnico qui dentro
},
};
Per ora non serve arrivare subito alla versione completa.
Serve vedere la direzione: il dettaglio tecnico deve avere un posto.
Attività guidata
Cerca nel tuo progetto fragile tutte le occorrenze di:
localStorage
JSON.stringify
JSON.parse
Puoi usare la ricerca dell’editor oppure, se sei nel terminale:
rg "localStorage|JSON\\.stringify|JSON\\.parse" .
Per ogni occorrenza compila una tabella:
| Punto del codice | Cosa fa | Responsabilità reale | Se cambio persistenza lo tocco? |
| --- | --- | --- | --- |
| caricamento iniziale | legge strumenti | infrastruttura | sì |
| event listener prestito | salva strumenti e prestiti | UI + infrastruttura mescolate | sì |
| regola prestito | legge localStorage | dominio contaminato | sì, grave |
Se trovi localStorage dentro una funzione di dominio, segnalo nel tuo documento come priorità alta.
Micro-sfida
Immagina di sostituire localStorage con un file JSON.
Scrivi due liste:
Dovrebbe cambiare:
- il modo in cui leggo strumenti;
- il modo in cui salvo prestiti;
- il formato esterno dei dati;
- la gestione di dati mancanti o corrotti.
Non dovrebbe cambiare:
- la regola sullo strumento guasto;
- la regola sullo strumento già in prestito;
- il significato di Strumento;
- il flusso generale di RegistraPrestito;
- i test sulle regole di dominio.
Vincolo: ogni elemento deve essere collegato al Registro, non scritto in modo generico.
Prodotto da ottenere
Alla fine della lezione devi avere:
- elenco delle occorrenze di
localStorage,JSON.stringify,JSON.parse; - tabella con responsabilità e costo del cambio;
- lista di cose che cambierebbero passando a JSON;
- lista di cose che non dovrebbero cambiare;
- primo schizzo testuale di
ArchivioStrumenti; - una priorità di refactoring legata alla persistenza.
Domande di comprensione
Rispondi per iscritto:
- Perché
localStoragenon è il problema in sé? - Perché una regola di dominio non dovrebbe leggere dal browser?
- Quale parte del progetto dovrebbe conoscere
JSON.stringify? - Che cosa significa rendere la persistenza sostituibile?
- Quale punto del tuo codice sarebbe più costoso da cambiare se passassi a una API?
Controllo finale
La lezione è completata quando puoi dire sì a queste domande:
- ho trovato i punti che usano
localStorage; - so spiegare perché il problema è la dipendenza diffusa, non
localStorage; - ho distinto ciò che dovrebbe cambiare da ciò che dovrebbe restare stabile;
- ho capito perché il dominio non deve conoscere il browser;
- so spiegare a parole cosa sarà un archivio sostituibile.
Nel prossimo passo torneremo sul programma fragile e coloreremo i confini direttamente nel codice.