modulo 12 di 24 / Ore 21-40
Moduli 9-16 / Checkpoint 40 ore
Micro-sfida: da Cannot read properties a Strumento non trovato
Come trasformare l'errore tecnico 'Cannot read properties of undefined' in 'STRUMENTO_NON_TROVATO' nel Registro — causa, posizione nel codice e correzione guidata.
Micro-sfida: da Cannot read properties a Strumento non trovato
Questa lezione appartiene al Modulo 12 — Errori comprensibili.
Obiettivo della lezione
Trasformare un errore JavaScript generico e incomprensibile (Cannot read properties of undefined) in un errore di dominio esplicito (STRUMENTO_NON_TROVATO) nel Registro, capendo dove si trova il problema nel codice e come correggerlo.
Alla fine sai leggere un errore in console, trovare la riga che lo causa e sostituirlo con una verifica esplicita prima che il crash avvenga.
Perché serve nel percorso
Cannot read properties of undefined è l’errore più comune in JavaScript. Compare quando si accede a una proprietà di un valore che si aspettava un oggetto ma era undefined. Nel Registro, questo succede quasi sempre quando si cerca uno strumento o un prestito per ID e non viene trovato — e poi si prova a leggerne lo stato.
Nel Registro del laboratorio
Scenario che causa l’errore:
Un utente inserisce un ID strumento che non esiste più in localStorage (magari cancellato manualmente o non ancora creato). Il codice prova a leggere strumento.stato ma strumento è undefined.
Il codice problematico:
// src/application/registraPrestito.js — PRIMA (fragile)
export function registraPrestito({ strumentoId, studenteId }, archivio) {
const strumento = archivio.trovaPerId(strumentoId);
// strumento può essere undefined se non trovato!
if (strumento.stato !== "disponibile") { // CRASH: Cannot read properties of undefined
throw new Error("Non disponibile");
}
// ...
}
L’errore in console:
Uncaught TypeError: Cannot read properties of undefined (reading 'stato')
at registraPrestito (registraPrestito.js:4)
at HTMLButtonElement.<anonymous> (azioniPrestito.js:12)
L’utente vede la pagina bloccarsi. Non capisce cosa è successo.
La correzione:
// src/application/registraPrestito.js — DOPO (esplicito)
export function registraPrestito({ strumentoId, studenteId }, archivio) {
const strumento = archivio.trovaPerId(strumentoId);
// Verifica esplicita PRIMA di accedere alle proprietà
if (!strumento) {
throw new Error("STRUMENTO_NON_TROVATO");
}
if (strumento.stato === "guasto") {
throw new Error("STRUMENTO_GUASTO_NON_PRESTABILE");
}
if (strumento.stato === "in_prestito") {
throw new Error("STRUMENTO_GIA_IN_PRESTITO");
}
if (strumento.stato !== "disponibile") {
throw new Error("STRUMENTO_NON_DISPONIBILE");
}
// Solo qui accediamo ad altre proprietà, sapendo che strumento esiste
const prestito = {
id: crypto.randomUUID(),
strumentoId: strumento.id,
studenteId,
apertura: new Date(),
chiusura: null
};
archivio.aggiorna({ ...strumento, stato: "in_prestito" });
return prestito;
}
Procedura guidata
- Riproduci l’errore: passa un ID strumento inesistente a
registraPrestitonel browser. - Leggi il messaggio in console: identifica la riga esatta del crash.
- Trova il punto in cui il valore può essere
undefined(risultato ditrovaPerId,find,filter). - Aggiungi la verifica esplicita (
if (!valore) throw new Error("CODICE")) prima di accedere alle proprietà. - Riproduci lo scenario: ora deve apparire un errore leggibile, non un crash.
Attività in classe
Cerca nel codice del Registro tutti i punti in cui si usa un risultato di trovaPerId, find o filter senza verificare prima che non sia undefined:
grep -n "\.trovaPerId\|\.find\|\.filter" src/application/
Per ogni occorrenza trovata, verifica se subito dopo c’è un controllo if (!risultato). Se manca, aggiungilo.
Compila la scheda:
## Micro-sfida: errore → codice esplicito
Errore originale:
File e riga del crash:
Causa (quale variabile era undefined?):
Codice aggiunto:
Errore ora lanciato:
Messaggio utente tradotto:
Spiegazione guidata per studiare
La regola è semplice: mai accedere a una proprietà di un risultato che potrebbe essere undefined senza prima verificarlo.
I metodi che restituiscono undefined quando l’elemento non c’è:
Array.find()→ restituisceundefinedse nessun elemento soddisfa il predicato;Map.get()→ restituisceundefinedse la chiave non esiste;- qualsiasi funzione
trovaPerIdscritta da te che usafindinternamente.
I metodi che non restituiscono undefined (restituiscono array vuoto):
Array.filter()→ restituisce[]se nessun elemento soddisfa il predicato.
Il pattern corretto dopo ogni ricerca per ID:
const entità = archivio.trovaPerId(id);
if (!entità) {
throw new Error("ENTITA_NON_TROVATA"); // codice leggibile, non crash
}
// da qui in poi puoi usare entità.qualsiasiproprieta in modo sicuro
Questo pattern vale per strumenti, prestiti e guasti nel Registro.
Perché un codice errore invece di un messaggio? Il codice ("STRUMENTO_NON_TROVATO") viene tradotto dalla UI in italiano. Il dominio non deve sapere come parlare all’utente — si limita a segnalare cosa è andato storto.
Passo per passo nel progetto
- Apri
src/application/registraPrestito.js. - Trova la riga
trovaPerId(strumentoId)e aggiungi il controlloif (!strumento). - Apri
src/application/chiudiPrestito.jse fai lo stesso pertrovaPerId(prestitoId). - Apri
src/application/apriSegnalazioneGuasto.jsse esiste e fai lo stesso. - Aggiungi un test per ogni caso:
test("registraPrestito lancia STRUMENTO_NON_TROVATO per ID inesistente", () => {
const archivio = creaArchivioStrumentiFake([]); // archivio vuoto
expect(() =>
registraPrestito({ strumentoId: "non-esiste", studenteId: "stu-01" }, archivio, archivioPrestiti)
).toThrow("STRUMENTO_NON_TROVATO");
});
Prova di comprensione
- Quando
Array.find()restituisceundefined? - Perché il codice errore (
"STRUMENTO_NON_TROVATO") è meglio del messaggio diretto ("Strumento non trovato")? - Dove nel codice del Registro è più probabile trovare questo tipo di crash?
- Come si verifica che la correzione funziona senza usare il browser?
Errori da evitare
- usare optional chaining (
strumento?.stato) invece di una verifica esplicita — nasconde il problema invece di gestirlo; - controllare
strumento !== nullinvece di!strumento—undefinednon ènullin JavaScript; - mettere il controllo dopo aver già acceduto a una proprietà dell’oggetto — troppo tardi;
- lanciare
new Error(err.message)invece di un codice semantico — perde informazione.
Prodotto da consegnare
Tutti i casi d’uso del Registro con verifica esplicita dopo trovaPerId e almeno un test che verifica che l’errore corretto viene lanciato per un ID inesistente.
Checklist di chiusura
- nessun accesso a proprietà di variabile che potrebbe essere
undefinedsenza controllo precedente - ogni
trovaPerIdè seguita daif (!risultato) throw new Error("CODICE") - i codici errore usano maiuscole e underscore (
STRUMENTO_NON_TROVATO) - almeno un test verifica il caso “ID non trovato”
- il messaggio
Cannot read properties of undefinednon appare più in console durante l’uso normale
Risultato atteso
Ho trovato il crash in registraPrestito.js alla riga che legge strumento.stato.
Ho aggiunto if (!strumento) throw new Error("STRUMENTO_NON_TROVATO") prima.
Ho fatto lo stesso in chiudiPrestito.js per il prestito non trovato.
I test passano e il crash non compare più in console.
La UI mostra ora "Lo strumento cercato non esiste" invece di un errore tecnico.