modulo 18 di 24 / Ore 41-60

Moduli 17-24 / Checkpoint 60 ore

Messaggi troppo dettagliati e informazioni tecniche

Riconoscere quando un messaggio contiene troppi dettagli tecnici e imparare a separare il messaggio per l'utente dal dettaglio tecnico per chi mantiene il sistema.

25 minArchitettura del software

Messaggi troppo dettagliati e informazioni tecniche

Questa lezione appartiene al Modulo 18 — Sicurezza di base.

Il problema

Un messaggio troppo dettagliato rivela all’utente informazioni che non servono a lui ma che potrebbero essere utili a qualcuno con intenzioni malevole — o semplicemente confondere chi non è tecnico.

Esempi di messaggi troppo dettagliati nel Registro:

❌  "TypeError: Cannot read properties of undefined (reading 'stato')"
❌  "localStorage.getItem('registro:strumenti') ha restituito null"
❌  "STRUMENTO_NON_TROVATO: id=str-042 non presente in archivio"
❌  "Errore SQL: UNIQUE constraint failed: strumenti.id"

Nessuno di questi aiuta l’utente a capire cosa fare. Tutti rivelano dettagli sull’implementazione interna.

La distinzione fondamentale

Ogni errore ha due “destinatari” con bisogni diversi:

Destinatario Cosa gli serve Dove va
Utente Cosa è andato storto e cosa può fare Visibile nella UI
Sviluppatore Dettaglio tecnico per diagnosticare console.error, log

Il messaggio per l’utente deve essere comprensibile e azionabile. Il dettaglio tecnico deve essere preciso e conservato, ma non visibile.

Messaggi tipici nel Registro — prima e dopo

Strumento non trovato

// ❌ Troppo tecnico
mostraMessaggio("STRUMENTO_NON_TROVATO: id=str-042");

// ✅ Comprensibile
mostraMessaggio("Strumento non trovato. Controlla l'ID e riprova.");
console.error("Strumento non trovato nell'archivio", { strumentoId: "str-042" });

Salvataggio fallito

// ❌ Troppo tecnico
mostraMessaggio("QuotaExceededError: localStorage quota exceeded");

// ✅ Comprensibile
mostraMessaggio("Non riesco a salvare i dati. Prova a liberare spazio nel browser.");
console.error("localStorage pieno", errore);

Regola di dominio violata

// ❌ Troppo tecnico (codice errore esposto)
mostraMessaggio("STRUMENTO_GIA_IN_PRESTITO");

// ✅ Comprensibile
mostraMessaggio("Questo strumento è già in prestito e non può essere prestato di nuovo.");
// nessun console.error — non è un errore tecnico, è una regola del laboratorio

Errore JavaScript non gestito

// ❌ Mostra lo stack trace in console E nella UI
alert(errore.stack);

// ✅ Messaggio generico per l'utente, dettaglio in console
mostraMessaggio("Si è verificato un problema. Ricarica la pagina e riprova.");
console.error("Errore non gestito:", errore);

Come costruire la separazione

// Dizionario messaggi — nella Presentation
const messaggiUtente = {
  STRUMENTO_NON_TROVATO: "Strumento non trovato. Controlla l'ID e riprova.",
  STRUMENTO_NON_DISPONIBILE: "Questo strumento non può essere prestato al momento.",
  STRUMENTO_GIA_IN_PRESTITO: "Questo strumento è già in prestito.",
  STRUMENTO_GUASTO_NON_PRESTABILE: "Questo strumento è guasto e non può essere prestato.",
  ARCHIVIO_NON_DISPONIBILE: "Non riesco a salvare i dati. Riprova tra poco.",
  NOME_NON_VALIDO: "Il nome deve avere almeno 2 caratteri.",
  CATEGORIA_MANCANTE: "Seleziona una categoria."
};

function gestisciErrore(errore) {
  const messaggioUtente = messaggiUtente[errore.message];

  if (messaggioUtente) {
    // Errore atteso — mostra messaggio comprensibile
    mostraAvviso(messaggioUtente);
  } else {
    // Errore inatteso — messaggio generico per l'utente, dettaglio in console
    mostraAvviso("Si è verificato un problema. Riprova tra poco.");
    console.error("Errore non gestito:", errore);
  }
}

// Uso nel gestore di eventi
try {
  await registraPrestito(comando);
} catch (errore) {
  gestisciErrore(errore);
}

Cosa NON deve mai apparire nella UI

  • Stack trace (at function.js:42)
  • Codici errore interni (STRUMENTO_NON_TROVATO)
  • Nomi di file o funzioni del codice
  • Query o chiavi di localStorage
  • Valori di variabili interne

Queste informazioni appartengono al log — non alla UI.

Procedura guidata

  1. Cerca tutti i blocchi catch nel tuo progetto.
  2. Per ogni catch: cosa viene mostrato all’utente? È comprensibile?
  3. Aggiungi console.error per conservare il dettaglio tecnico.
  4. Sostituisci il messaggio grezzo con uno del dizionario messaggiUtente.
  5. Aggiungi un fallback per errori non previsti ("Si è verificato un problema").

Attività in classe

## Messaggi nel mio Registro

Blocco catch analizzato (file e riga):

Messaggio attuale mostrato all'utente:

È comprensibile per un non-tecnico (sì/no):

Messaggio proposto:

Il dettaglio tecnico viene conservato (console.error) (sì/no):

Spiegazione guidata per studiare

La separazione tra messaggio utente e dettaglio tecnico è un principio di sicurezza e di qualità insieme. Da un lato, non riveli informazioni sull’implementazione. Dall’altro, chi usa il sistema capisce cosa fare.

Il punto centrale è: il codice errore appartiene al log, non alla UI. STRUMENTO_NON_TROVATO è un’etichetta interna precisa — utile per il debugging, non per l’utente. L’utente ha bisogno di “Strumento non trovato. Controlla l’ID.” — una frase che descrive il problema e suggerisce un’azione.

Il rischio tipico è usare alert(errore.message) perché è veloce. Funziona in sviluppo. In produzione espone l’implementazione e confonde l’utente.

Passo per passo nel progetto

  1. Apri tutti i file della presentation/.
  2. Cerca alert, innerHTML = errore, textContent = errore.message o simili.
  3. Per ogni occorrenza: sostituisci con il messaggio dal dizionario.
  4. Aggiungi console.error nello stesso blocco per conservare il dettaglio.
  5. Verifica che il dizionario messaggiUtente copra tutti i codici errore che il progetto genera.

Esempio da leggere lentamente

// Confronto — stesso errore, due gestioni diverse

// ❌ Prima
catch (errore) {
  document.getElementById("msg").textContent = errore.message;
  // L'utente vede: "STRUMENTO_NON_TROVATO"
}

// ✅ Dopo
catch (errore) {
  const messaggi = {
    STRUMENTO_NON_TROVATO: "Strumento non trovato. Controlla l'ID.",
    ARCHIVIO_NON_DISPONIBILE: "Impossibile salvare. Riprova tra poco."
  };
  const testo = messaggi[errore.message] ?? "Si è verificato un problema.";
  document.getElementById("msg").textContent = testo;
  // Dettaglio tecnico conservato nel log
  if (!messaggi[errore.message]) console.error("Errore non previsto:", errore);
}

Prova di comprensione

  • Elenca tre messaggi nel tuo Registro che un utente non tecnico non capirebbe.
  • Per ognuno: quale messaggio mostreresti invece?
  • Dove conserveresti il dettaglio tecnico?

Errori da evitare

  • mostrare errore.message direttamente nella UI;
  • usare alert() con codici errore interni;
  • eliminare il dettaglio tecnico invece di spostarlo nel log;
  • scrivere un messaggio generico per tutti gli errori senza distinzione (impossibile diagnosticare).

Prodotto da consegnare

Può essere:

  • un dizionario messaggiUtente completo con tutti i codici errore del progetto;
  • tre blocchi catch rivisti con messaggio comprensibile + console.error;
  • un test manuale documentato: provoca un errore noto, verifica che l’utente veda il messaggio corretto.

Checklist di chiusura

  • Nessun blocco catch mostra errore.message o stack trace direttamente nella UI
  • Esiste un dizionario che mappa codici errore a messaggi comprensibili
  • Tutti i blocchi catch hanno console.error per conservare il dettaglio tecnico
  • Gli errori non previsti mostrano un messaggio generico (non un codice)
  • Ho verificato il comportamento provocando almeno un errore noto

Domande per la revisione

  • Hai trovato messaggi tecnici nella UI? Quanti?
  • Il dizionario messaggiUtente copre tutti i casi del tuo progetto?
  • Come distingui un errore “previsto” (che hai gestito) da uno “non previsto”?

Risultato atteso

Alla fine lo studente deve saper dire:

Nel mio Registro, i messaggi mostrati all'utente sono comprensibili:
- [errore X] → "[messaggio utente]"
- [errore Y] → "[messaggio utente]"
Il dettaglio tecnico viene conservato in console.error.
Gli errori non previsti mostrano: "Si è verificato un problema. Riprova tra poco."

Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.