modulo 12 di 24 / Ore 21-40
Moduli 9-16 / Checkpoint 40 ore
Separare messaggio pubblico e dettaglio tecnico
Costruire nel Registro un sistema a due livelli per gli errori: il messaggio pubblico che aiuta l'utente e il dettaglio tecnico che aiuta chi mantiene il sistema.
Separare messaggio pubblico e dettaglio tecnico
Questa lezione appartiene al Modulo 12 — Errori, validazione e messaggi.
I due destinatari di ogni errore
Quando un’operazione fallisce nel Registro, ci sono due destinatari con bisogni opposti:
L’utente vuole sapere:
- cosa è andato storto in termini comprensibili
- cosa può fare per risolvere
Chi mantiene il sistema vuole sapere:
- quale parte del codice ha generato il problema
- quali dati erano coinvolti
- se è un bug o una condizione attesa
Questi bisogni richiedono informazioni diverse. Il messaggio pubblico deve essere semplice. Il dettaglio tecnico deve essere preciso. Non si possono unire senza compromettere entrambi.
Il flusso di separazione nel Registro
Domain/Application → lancia errore con codice preciso
throw new Error("STRUMENTO_NON_TROVATO")
Presentation → cattura l'errore
→ traduce il codice in messaggio utente
→ conserva il dettaglio tecnico nel log
In codice:
// Presentation — gestisce la separazione
async function gestisciSubmitPrestito(comando) {
try {
await registraPrestito(comando);
mostraSuccesso("Prestito registrato.");
} catch (errore) {
// Messaggio pubblico — per l'utente
const messaggioUtente = traduciErrore(errore.message);
mostraErroreUI(messaggioUtente);
// Dettaglio tecnico — per chi mantiene il sistema
if (!messaggiUtente[errore.message]) {
// Errore non previsto: logga il dettaglio completo
console.error("[ERRORE NON PREVISTO]", {
codice: errore.message,
stack: errore.stack,
comando: { strumentoId: comando.strumentoId } // no dati personali
});
}
}
}
La funzione di traduzione
La traduzione da codice a messaggio è una responsabilità della Presentation:
// presentation/traduttoreErrori.js
const messaggiUtente = {
// Errori applicativi
STRUMENTO_NON_TROVATO: "Strumento non trovato. Controlla l'ID e riprova.",
PRESTITO_NON_TROVATO: "Prestito non trovato.",
// Errori di dominio
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.",
PRESTITO_GIA_CHIUSO: "Questo prestito è già stato chiuso.",
// Errori di input
NOME_NON_VALIDO: "Il nome deve avere almeno 2 caratteri.",
CATEGORIA_MANCANTE: "Seleziona una categoria.",
// Errori infrastrutturali
ARCHIVIO_NON_DISPONIBILE: "Non riesco a salvare i dati. Riprova tra poco.",
};
function traduciErrore(codice) {
return messaggiUtente[codice] ?? "Si è verificato un problema. Riprova tra poco.";
}
Cosa va nel messaggio pubblico
Il messaggio pubblico deve:
- usare parole del vocabolario dell’utente, non del codice
- dire cosa può fare l’utente (“controlla l’ID”, “riprova tra poco”)
- non rivelare stack trace, nomi di variabili, chiavi di localStorage
- essere breve — una frase basta
✅ "Strumento non trovato. Controlla l'ID e riprova."
✅ "Questo strumento è guasto e non può essere prestato."
✅ "Non riesco a salvare i dati. Riprova tra poco."
❌ "STRUMENTO_NON_TROVATO"
❌ "Cannot read properties of undefined (reading 'stato')"
❌ "localStorage.getItem('registro:strumenti') ha restituito null"
Cosa va nel dettaglio tecnico
Il dettaglio tecnico deve:
- essere preciso e completo per il debugging
- finire in
console.error(non inalerto nell’UI) - includere il contesto minimo utile (ID coinvolti, operazione)
- non includere dati personali (nomi di studenti, assegnatari)
// ✅ Dettaglio tecnico utile
console.error("Errore non previsto in registraPrestito", {
codice: errore.message,
strumentoId: comando.strumentoId,
timestamp: new Date().toISOString()
});
// ❌ Dettaglio tecnico con dati personali — da evitare
console.error("Errore", {
assegnatario: comando.assegnatario, // dato personale
command: JSON.stringify(comando) // potrebbe contenere dati sensibili
});
Il caso del messaggio generico
Quando si cattura un errore non previsto (codice non nel dizionario), il messaggio generico è la scelta corretta:
function traduciErrore(codice) {
const messaggio = messaggiUtente[codice];
if (messaggio) return messaggio;
// Errore non previsto — messaggio generico per l'utente
// Il dettaglio verrà loggato da chi chiama questa funzione
return "Si è verificato un problema. Riprova tra poco.";
}
Il messaggio generico non è una sconfitta — è la scelta corretta per errori imprevisti. Meglio un messaggio vago ma sicuro che uno specifico ma che rivela dettagli interni.
Procedura guidata
- Apri tutti i blocchi
catchdel tuo Registro. - Per ogni
catch: cosa viene mostrato all’utente? È un messaggio pubblico o un dettaglio tecnico? - Aggiungi
traduciErrorese non esiste. - Aggiungi
console.errorper i dettagli tecnici degli errori non previsti. - Verifica che nessun codice errore (
STRUMENTO_NON_TROVATO) appaia nell’interfaccia.
Attività in classe
## Separazione errori nel mio Registro
Blocco catch analizzato (file:riga):
Cosa mostra all'utente attualmente:
→ è un messaggio pubblico o un dettaglio tecnico?
Messaggio pubblico proposto:
Il dettaglio tecnico va in console.error (sì/no):
Errori non previsti hanno un messaggio generico (sì/no):
Dati personali nei log (da rimuovere se presenti):
Spiegazione guidata per studiare
La separazione tra messaggio pubblico e dettaglio tecnico segue la stessa logica della separazione dei livelli: ogni parte del sistema ha una responsabilità diversa verso destinatari diversi.
Il punto centrale è: il codice errore è un contratto interno — non una comunicazione con l’utente. STRUMENTO_NON_TROVATO è preciso e utile per il debugging. Non ha senso per un tecnico del laboratorio scolastico. La traduzione avviene nella Presentation — l’unico livello che conosce sia il codice che il contesto dell’interfaccia.
Il rischio tipico è usare alert(errore.message) perché è rapido. Funziona in sviluppo. In produzione espone i dettagli interni e confonde l’utente.
Passo per passo nel progetto
- Cerca tutti i punti che mostrano errori:
alert,textContent = errore,innerHTML = errore.message. - Per ognuno: sostituisci con
mostraErroreUI(traduciErrore(errore.message)). - Aggiungi
console.errornello stesso blocco per gli errori non previsti. - Verifica il dizionario: copre tutti i codici errore che il progetto genera?
Esempio da leggere lentamente
// Prima: un solo catch che mostra il codice grezzo
catch (errore) {
alert(errore.message); // ← mostra "STRUMENTO_NON_TROVATO" all'utente
}
// Dopo: separazione netta
catch (errore) {
// Messaggio pubblico — comprensibile
mostraErroreUI(traduciErrore(errore.message));
// Dettaglio tecnico — per il debugging
if (!messaggiUtente[errore.message]) {
// Solo per errori non previsti — quelli previsti non hanno stack trace utili
console.error("Errore non gestito:", errore.message, errore.stack);
}
}
Prova di comprensione
- Quale codice errore del tuo Registro non ha ancora un messaggio pubblico nel dizionario?
- Dove nel tuo progetto appare un codice errore direttamente nell’interfaccia?
- Come distingui un errore “previsto” (nel dizionario) da uno “non previsto”?
Errori da evitare
- usare il messaggio generico per tutti gli errori — impossibile distinguere cosa è successo;
- mostrare lo stack trace nell’interfaccia — inutile per l’utente, rivela dettagli interni;
- non loggare gli errori non previsti — rende il debugging impossibile;
- inserire dati personali nei log tecnici.
Prodotto da consegnare
Può essere:
- il dizionario
messaggiUtentecompleto per tutti i codici errore del Registro; - tutti i blocchi
catchaggiornati con messaggio pubblico +console.error; - un test manuale: provoca tre errori diversi e verifica che l’UI mostri messaggi comprensibili.
Checklist di chiusura
- Il dizionario
messaggiUtentecopre tutti i codici errore del progetto - Nessun codice errore appare direttamente nell’interfaccia utente
- Gli errori non previsti hanno
console.errorcon il dettaglio tecnico - I log tecnici non contengono dati personali
- Il messaggio generico è usato solo per errori non previsti
Domande per la revisione
- Hai trovato codici errore che mancavano nel dizionario?
- I messaggi pubblici dicono all’utente cosa fare (non solo cosa è andato storto)?
- Gli errori non previsti sono loggati in modo utile per il debugging?
Risultato atteso
Alla fine lo studente deve saper dire:
Nel mio Registro, gli errori vengono gestiti così:
- il dominio lancia: [codici errore]
- la Presentation traduce con messaggiUtente: [lista]
- i dettagli tecnici vanno in console.error
- i dati personali non appaiono nei log
Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.