modulo 08 di 24 / Ore 0-20
Moduli 1-8 / Checkpoint 20 ore
Spostare i casi d'uso fuori dagli event listener
Ridurre gli event listener a codice di bordo: raccolgono input, chiamano casi d'uso e mostrano risultati.
Spostare i casi d’uso fuori dagli event listener
Nel programma fragile gli event listener fanno tutto.
Esempio:
click sul bottone
legge input
cerca dati
applica regole
crea prestito
salva
aggiorna UI
Questo rende il codice difficile da testare e modificare.
L’obiettivo e far diventare l’event listener un bordo sottile.
Obiettivo
Alla fine devi avere:
- un event listener che legge input;
- un caso d’uso chiamato dall’event listener;
- logica applicativa fuori dalla UI;
- gestione degli errori piu chiara.
Punto di partenza
Esempio fragile:
formPrestito.addEventListener("submit", (event) => {
event.preventDefault();
const strumentoId = inputStrumentoId.value;
const assegnatario = inputAssegnatario.value;
const strumento = strumenti.find((item) => item.id === strumentoId);
if (!strumento) {
messaggio.textContent = "Strumento non trovato";
return;
}
if (strumento.stato !== "disponibile") {
messaggio.textContent = "Strumento non disponibile";
return;
}
const prestito = {
id: crypto.randomUUID(),
strumentoId,
assegnatario,
stato: "aperto",
};
prestiti.push(prestito);
strumento.stato = "in_prestito";
messaggio.textContent = "Prestito registrato";
renderizzaStrumenti();
});
Qui l’event listener contiene un caso d’uso intero.
Estrarre il comando
La UI deve preparare un comando:
function leggiComandoPrestito() {
return {
prestitoId: crypto.randomUUID(),
strumentoId: inputStrumentoId.value,
assegnatario: inputAssegnatario.value,
apertoIl: new Date().toISOString().slice(0, 10),
};
}
Questo e codice di presentation.
Legge input e prepara dati.
Chiamare il caso d’uso
L’event listener diventa:
formPrestito.addEventListener("submit", (event) => {
event.preventDefault();
try {
const comando = leggiComandoPrestito();
registraPrestito(comando);
mostraMessaggio("Prestito registrato.");
aggiornaSchermata();
} catch (errore) {
mostraMessaggio(messaggioPerErrore(errore));
}
});
Ora e piu leggibile.
La UI:
- legge input;
- chiama il caso d’uso;
- mostra risultato;
- aggiorna la schermata.
Il caso d’uso coordina l’operazione.
Dove creare il caso d’uso
Nel punto di avvio:
const registraPrestito = creaRegistraPrestito({
archivioStrumenti,
archivioPrestiti,
});
avviaUIRegistro({
registraPrestito,
});
La UI riceve il caso d’uso gia pronto.
Non deve costruire archivi da sola se possiamo evitarlo.
Prima e dopo
Prima:
event listener = operazione completa
Dopo:
event listener = bordo
caso d'uso = operazione completa
dominio = regole
archivio = dati
Questa e la forma che vogliamo al checkpoint 20 ore.
Errori
L’event listener non deve contenere una lunga catena di regole:
if (strumento.stato === "guasto") ...
if (strumento.stato === "in_manutenzione") ...
Deve limitarsi a:
try {
registraPrestito(comando);
} catch (errore) {
mostraMessaggio(messaggioPerErrore(errore));
}
Questo rende piu facile cambiare le regole senza toccare la UI.
Esercizio
Scegli un event listener del tuo progetto.
Compila:
## Event listener da alleggerire
Evento:
Responsabilita presenti ora:
- ...
Caso d'uso da chiamare:
Comando da costruire:
Codice da lasciare nella UI:
- ...
Codice da spostare fuori:
- ...
Poi modifica un solo listener.
Verifica che il comportamento sia identico.
Cosa produrre
Alla fine della lezione devi avere:
- almeno un event listener semplificato;
- una funzione che costruisce il comando;
- un caso d’uso chiamato dalla UI;
- gestione errori con
try/catcho forma equivalente; - una nota sul refactoring fatto.
Spiegazione guidata per studiare
Questa lezione va studiata su due piani. Il primo è il comportamento visibile del Registro del laboratorio: che cosa vede o fa l’utente quando registra uno strumento, cerca un dispositivo, apre un prestito o segnala un guasto. Il secondo è il confine architetturale: dove deve stare il codice che rende possibile quel comportamento.
Per spostare i casi d’uso fuori dagli event listener, il punto centrale è questo: Un caso d’uso coordina un’operazione completa: riceve un comando, legge ciò che serve, applica regole, salva il risultato e restituisce un esito.
Il rischio tipico è far diventare il caso d’uso una seconda UI o un secondo database. Deve coordinare, non mostrare HTML e non conoscere dettagli tecnici di salvataggio. Per evitarlo, non partire dal file che hai già aperto nell’editor. Parti dalla domanda: “quale responsabilità sto modificando?”. Se la risposta riguarda una regola del laboratorio, guarda il dominio. Se riguarda una sequenza di operazioni, guarda i casi d’uso. Se riguarda salvataggio, file, localStorage, API o database, guarda l’infrastruttura. Se riguarda input, pulsanti, form e messaggi, guarda la Presentation.
Il tempo è sufficiente per alternare spiegazione, modifica guidata e revisione. Alla fine della lezione lo studente non deve ricordare una definizione a memoria: deve saper indicare un punto del progetto, spiegare perché quel codice sta lì e mostrare una verifica del comportamento.
Passo per passo nel progetto
- Rileggi il titolo della lezione e riscrivilo come domanda pratica. Per esempio: “dove deve stare questa regola?”, “chi deve salvare questo dato?”, “come verifico questo errore?”.
- Apri solo i file necessari. Se devi toccare più di tre file, fermati e scrivi prima una mini-mappa.
- Definisci input e output del caso d’uso.
- Leggi i dati attraverso un archivio o una dipendenza esplicita.
- Chiama le regole del dominio.
- Salva il risultato senza sapere come funziona la persistenza concreta.
- Aggiorna una nota breve nel README o negli appunti se hai cambiato un confine del progetto.
Esempio da leggere lentamente
Questo esempio serve a ragionare, non a incollare codice senza capire:
function registraPrestito(comando, archivioStrumenti, archivioPrestiti) {
const strumento = archivioStrumenti.trovaPerId(comando.strumentoId);
verificaStrumentoPrestabile(strumento);
const prestito = apriPrestito(strumento.id, comando.nomePersona);
archivioPrestiti.salva(prestito);
archivioStrumenti.salva({ ...strumento, stato: "in_prestito" });
return prestito;
}
Leggilo chiedendoti che cosa cambierebbe se domani sostituissimo la pagina web con una CLI, oppure localStorage con un’API. Se l’esempio continua ad avere senso senza riscrivere tutto, il confine è probabilmente buono. Se invece un dettaglio tecnico si propaga in molti file, il progetto sta tornando fragile.
Prova di comprensione
Prima di chiudere la lezione, rispondi per iscritto a queste domande:
- Qual è la responsabilità principale trattata in questa lezione?
- In quale livello del progetto dovrebbe stare?
- Quale errore faresti se cercassi la soluzione più veloce?
- Quale piccolo test, controllo manuale o esempio dimostra che hai capito?
- Che cosa deve restare facile da cambiare dopo questa lezione?
Una risposta accettabile non deve essere lunga. Deve però usare parole concrete del Registro: strumento, prestito, stato, archivio, caso d’uso, messaggio, test.
Controllo finale
La lezione e completata quando puoi rispondere si:
- l’event listener non contiene piu tutta l’operazione;
- la UI costruisce un comando;
- il caso d’uso coordina l’operazione;
- le regole stanno nel dominio;
- gli errori vengono trasformati in messaggi utente;
- posso testare il caso d’uso senza click.
Nella prossima lezione creiamo un archivio in memoria.