modulo 02 di 24 / Ore 0-20
Moduli 1-8 / Checkpoint 20 ore
Dati, eventi, regole e salvataggio mescolati
Analizzare una versione volutamente fragile del registro in cui dati, eventi della UI, regole di dominio e salvataggio sono concentrati nello stesso punto.
Dati, eventi, regole e salvataggio mescolati
Nella lezione precedente abbiamo costruito una versione fragile del Registro. Ora la guardiamo con calma.
Il punto non è dire “questo codice fa schifo”. Il punto è capire perché un codice che funziona può diventare difficile da modificare.
Quando dati, eventi, regole e salvataggio si mescolano, il programma diventa fragile perché ogni modifica tocca più responsabilità insieme.
Obiettivo della lezione
Alla fine devi saper:
- distinguere dati, eventi, regole, messaggi e salvataggio;
- indicare dove queste responsabilità compaiono in
main.js; - spiegare perché il codice funziona ma resta fragile;
- aggiungere un salvataggio volutamente diretto in
localStorage; - osservare perché salvare non basta se non esiste anche una fase di caricamento;
- annotare i punti che più avanti dovranno essere separati.
Non stiamo ancora facendo refactoring. Stiamo imparando a vedere.
Le responsabilità mescolate
Nel nostro main.js stanno insieme almeno quattro tipi di codice:
- dati;
- eventi della UI;
- regole;
- aggiornamento della pagina.
Se aggiungiamo localStorage, entra una quinta responsabilità:
- salvataggio dati.
Vediamole una per una.
Dati
Questi sono dati:
let strumenti = [
{
id: "str-001",
nome: "Notebook Lenovo 01",
categoria: "notebook",
stato: "disponibile",
},
];
let prestiti = [];
I dati descrivono lo stato corrente del sistema.
Per ora sono in memoria. Quando ricarichi la pagina, tornano al valore iniziale. Questo è un limite accettabile nella primissima versione, ma diventerà un problema quando vorremo conservare prestiti e stati.
Domanda utile:
questo codice descrive che cosa esiste nel registro?
Se sì, probabilmente stai guardando dati.
Eventi della UI
Questo è codice di interfaccia:
bottonePresta.addEventListener("click", () => {
const id = inputStrumentoId.value;
const studente = inputStudente.value;
// ...
});
La UI legge input e reagisce a un click.
Questa responsabilità è legittima: qualcuno deve ascoltare il click del bottone. Il problema nasce quando dentro lo stesso evento finiscono anche regole importanti, salvataggio e modifiche al modello.
Domanda utile:
questo codice dipende da un bottone, da un input o dal DOM?
Se sì, sei nella Presentation, cioè nel bordo visibile del sistema.
Regole
Questa è una regola:
if (strumento.stato === "guasto") {
messaggioElement.textContent = "Uno strumento guasto non può essere prestato";
return;
}
La regola dice qualcosa che deve valere sempre:
uno strumento guasto non può essere prestato
Non è una preferenza grafica. Non è un dettaglio del bottone. È una regola del dominio.
Se resta nell’event listener, sarà più difficile:
- riusarla;
- testarla;
- applicarla da una UI diversa;
- proteggerla quando cambiamo il salvataggio.
Domanda utile:
questa cosa deve valere anche se cambio interfaccia?
Se sì, probabilmente è una regola di dominio.
Messaggi e aggiornamento della pagina
Questo è codice di presentazione:
messaggioElement.textContent = "Prestito registrato";
mostraStrumenti();
Serve a comunicare con l’utente e aggiornare ciò che vede.
Va bene che la UI mostri messaggi. Il problema è quando la UI decide anche le regole. Un messaggio può stare vicino all’interfaccia; la regola che produce l’errore dovrebbe diventare indipendente dalla pagina.
Domanda utile:
questo codice serve a mostrare qualcosa all'utente?
Se sì, è presentazione.
Aggiungere salvataggio nel modo più diretto
Ora aggiungiamo intenzionalmente un salvataggio fragile.
Dentro l’event listener del prestito, dopo aver modificato strumenti e prestiti, scrivi:
localStorage.setItem("strumenti", JSON.stringify(strumenti));
localStorage.setItem("prestiti", JSON.stringify(prestiti));
Il codice diventa:
strumento.stato = "in_prestito";
prestiti.push({
id: `pre-${Date.now()}`,
strumentoId: strumento.id,
studente,
aperto: true,
});
localStorage.setItem("strumenti", JSON.stringify(strumenti));
localStorage.setItem("prestiti", JSON.stringify(prestiti));
messaggioElement.textContent = "Prestito registrato";
mostraStrumenti();
Funziona. Ma ora lo stesso blocco:
- modifica lo stato del sistema;
- crea un prestito;
- salva dati nel browser;
- mostra un messaggio;
- aggiorna la lista.
È una zona a rischio.
Perché è un problema
Il problema non è localStorage in sé. Il problema è il punto in cui lo stiamo usando.
Se domani cambi il modo di salvare i dati, devi toccare l’event listener.
Se domani cambi la UI, rischi di toccare anche il salvataggio.
Se domani vuoi testare la regola sullo strumento guasto, devi passare da input, bottone, DOM e messaggi.
Questa è la fragilità: il codice non è rotto, ma è costoso da cambiare.
Salvare non significa caricare
Dopo aver aggiunto localStorage.setItem, fai una prova:
- presta uno strumento;
- controlla in DevTools che i dati siano stati salvati;
- ricarica la pagina.
Probabilmente la pagina tornerà ai dati iniziali.
Perché?
Perché hai scritto dati in localStorage, ma non li hai ancora letti all’avvio.
Per caricarli nel modo più diretto potresti scrivere:
const strumentiSalvati = localStorage.getItem("strumenti");
const prestitiSalvati = localStorage.getItem("prestiti");
if (strumentiSalvati) {
strumenti = JSON.parse(strumentiSalvati);
}
if (prestitiSalvati) {
prestiti = JSON.parse(prestitiSalvati);
}
Anche questo funziona. Ma main.js cresce ancora: ora contiene dati iniziali, DOM, eventi, regole, salvataggio e caricamento.
Non correggerlo ancora. Annotalo.
Mappa delle responsabilità
Prendi un pezzo del codice e annotalo così:
Lettura input:
const id = inputStrumentoId.value
Ricerca dati:
strumenti.find(...)
Regola:
if (strumento.stato === "guasto")
Modifica stato:
strumento.stato = "in_prestito"
Salvataggio:
localStorage.setItem(...)
Messaggio:
messaggioElement.textContent = ...
Render:
mostraStrumenti()
Questa mappa è più utile di un giudizio generico. Ti fa vedere dove il codice è mescolato.
Attività guidata
Aggiungi localStorage nel modo fragile:
- salva
strumentidopo un prestito; - salva
prestitidopo un prestito; - salva
strumentidopo aver segnato uno strumento guasto; - ricarica la pagina;
- osserva se i dati vengono caricati oppure no;
- aggiungi il caricamento iniziale nel modo più diretto;
- annota quali nuove responsabilità sono entrate in
main.js.
Questo ultimo punto è il più importante: salvare non basta. Bisogna anche leggere, gestire dati mancanti e gestire dati non validi. Se tutto resta nella UI, il file cresce in fretta.
Micro-sfida
Evidenzia il tuo main.js con commenti temporanei.
Prima di ogni blocco scrivi una di queste etichette:
// DATI
// UI
// REGOLA
// MODIFICA STATO
// SALVATAGGIO
// MESSAGGIO
// RENDER
Vincolo: non spostare ancora il codice.
Risultato atteso: il file resta fragile, ma ora sai leggere quali responsabilità contiene.
Prodotto da ottenere
Alla fine della lezione devi avere:
- salvataggio diretto in
localStorage; - eventuale caricamento iniziale diretto da
localStorage; - una mappa delle responsabilità presenti in
main.js; - almeno cinque righe o blocchi etichettati;
- una nota su quali parti saranno difficili da testare.
Domande di comprensione
Rispondi per iscritto:
- Qual è la differenza tra dati, regole e UI?
- Perché
localStorageè infrastruttura e non dominio? - Perché salvare i dati dentro l’event listener crea accoppiamento?
- Che cosa succede se salvi i dati ma non li carichi all’avvio?
- Quale blocco del tuo
main.jscontiene più responsabilità?
Controllo finale
La lezione è completata quando puoi dire sì a queste domande:
- so distinguere dati, UI, regole, messaggi e salvataggio;
- ho visto un esempio di salvataggio mescolato alla UI;
- so perché questo codice può funzionare ma restare fragile;
- ho annotato almeno cinque responsabilità dentro
main.js; - ho capito che
localStorageè infrastruttura, non dominio.
Nel prossimo passo aggiungeremo ricerca e cambio stato nel modo più diretto possibile. Il programma diventerà più utile, ma anche più difficile da tenere sotto controllo.