modulo 12 di 24 / Ore 21-40
Moduli 9-16 / Checkpoint 40 ore
Errore di dominio: regola violata
Riconoscere e gestire gli errori di dominio nel Registro: violazioni delle regole del laboratorio che devono essere rilevate e lanciate dal dominio stesso.
Errore di dominio: regola violata
Questa lezione appartiene al Modulo 12 — Errori, validazione e messaggi.
Cos’è un errore di dominio
Un errore di dominio nasce quando viene violata una regola del laboratorio — una regola che esiste indipendentemente da come il sistema è costruito, da dove i dati vengono salvati o da come l’utente interagisce.
Nel Registro del laboratorio, le regole del dominio sono:
- uno strumento guasto non può essere prestato
- uno strumento già in prestito non può essere prestato di nuovo
- un prestito chiuso non si può chiudere una seconda volta
- uno strumento in manutenzione non può essere prestato
Queste regole esistono perché descrivono la realtà del laboratorio — non perché il programmatore le ha inventate.
Dove deve stare il controllo
Le regole del dominio vanno verificate nel dominio, non nella UI e non nel caso d’uso.
// domain/strumento.js — la regola sta qui, non altrove
function verificaDisponibilita(strumento) {
if (strumento.stato !== "disponibile") {
throw new Error("STRUMENTO_NON_DISPONIBILE");
}
}
// domain/prestito.js
function verificaPrestito(prestito) {
if (prestito.chiusoIl !== null) {
throw new Error("PRESTITO_GIA_CHIUSO");
}
}
Se il controllo stesse nella UI, potrebbe essere aggirato aprendo un’altra pagina. Se stesse solo nel caso d’uso, non sarebbe riutilizzabile. Nel dominio, è disponibile a chiunque nel sistema.
Errori di dominio nel Registro
| Codice errore | Regola violata | Dove viene lanciato |
|---|---|---|
STRUMENTO_NON_DISPONIBILE | Strumento non è in stato disponibile | domain/strumento.js |
PRESTITO_GIA_CHIUSO | Prestito ha già una data di chiusura | domain/prestito.js |
STATO_NON_VALIDO | Stato non è tra i valori ammessi | domain/strumento.js |
Differenza rispetto agli altri errori
Errore di input → "il nome è vuoto" — rilevato in Presentation / Application
Errore di dominio → "strumento guasto" — rilevato in Domain
Errore applicativo → "strumento non trovato" — rilevato in Application
Errore infrastrutturale → "salvataggio fallito" — rilevato in Infrastructure
Un errore di dominio non dipende dall’archivio (un dominio che funziona in memoria ha le stesse regole di uno con localStorage). Non dipende dall’input dell’utente — i dati sono già stati validati prima.
Come viene lanciato e catturato
// Domain — lancia l'errore con codice chiaro
function puoEsserePrestato(strumento) {
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 === "in_manutenzione") throw new Error("STRUMENTO_IN_MANUTENZIONE");
}
// Application — chiama la funzione di dominio
async function registraPrestito(comando) {
const strumento = await archivioStrumenti.trovaPerId(comando.strumentoId);
if (!strumento) throw new Error("STRUMENTO_NON_TROVATO"); // ← errore applicativo
puoEsserePrestato(strumento); // ← può lanciare errore di dominio
// ...
}
// Presentation — cattura e traduce
try {
await registraPrestito(comando);
} catch (errore) {
const messaggi = {
STRUMENTO_GUASTO_NON_PRESTABILE: "Questo strumento è guasto. Non può essere prestato.",
STRUMENTO_GIA_IN_PRESTITO: "Questo strumento è già in prestito.",
STRUMENTO_IN_MANUTENZIONE: "Questo strumento è in manutenzione.",
STRUMENTO_NON_TROVATO: "Strumento non trovato."
};
mostraMessaggio(messaggi[errore.message] ?? "Operazione non riuscita.");
}
Perché i codici errore, non le stringhe libere
I codici errore (STRUMENTO_GUASTO_NON_PRESTABILE) sono costanti confrontabili. Una stringa libera (“Strumento guasto, impossibile prestare”) può cambiare forma senza che il test si accorga — il test confronta la stringa e smette di funzionare.
Con i codici, il test confronta solo il codice:
test("non apre un prestito per uno strumento guasto", () => {
const strumento = { id: "s1", stato: "guasto" };
expect(() => puoEsserePrestato(strumento)).toThrow("STRUMENTO_GUASTO_NON_PRESTABILE");
});
Il messaggio per l’utente viene costruito altrove — nella Presentation — e può cambiare senza toccare il test.
Procedura guidata
- Apri
domain/strumento.jsedomain/prestito.jsnel tuo progetto. - Per ogni regola del laboratorio, verifica che ci sia una funzione che la controlla e lancia un errore con codice chiaro.
- Verifica che quelle funzioni vengano chiamate nei casi d’uso, non nella UI.
- Scrivi un test per almeno una regola: il dominio lancia l’errore corretto quando la regola è violata?
- Verifica che la UI traduca il codice in un messaggio comprensibile.
Attività in classe
## Errore di dominio nel mio Registro
Regola del dominio analizzata:
Funzione che la verifica:
Codice errore lanciato:
Dove viene catturato:
Messaggio utente corrispondente:
Test scritto:
Spiegazione guidata per studiare
Gli errori di dominio nascono nel dominio perché le regole del laboratorio appartengono al dominio. Non dipendono dall’interfaccia, dall’archivio o dalla tecnologia scelta.
Il punto centrale è: il dominio lancia, la Presentation traduce. Il dominio usa codici brevi e univoci (STRUMENTO_GUASTO_NON_PRESTABILE). La UI usa frasi comprensibili per l’utente. I due livelli non si mescolano.
Il rischio tipico è mettere il controllo della regola direttamente nell’event listener della UI: if (strumento.stato === "guasto") { mostraMessaggio("Guasto"); }. In questo modo la regola esiste solo nella UI — se domani si aggiunge una seconda pagina, la regola va replicata. E se una delle due repliche è sbagliata, il comportamento è inconsistente.
Passo per passo nel progetto
- Elenca le regole del laboratorio che il tuo Registro deve rispettare.
- Per ogni regola, la verifica sta nel dominio? O è dispersa in altri livelli?
- Ogni controllo lancia un errore con codice chiaro?
- La UI ha una tabella o funzione che traduce i codici in messaggi?
- Almeno una regola ha un test nel dominio?
Esempio da leggere lentamente
// domain/strumento.js — tutte le regole di prestabilità in un posto
function puoEsserePrestato(strumento) {
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 === "in_manutenzione") {
throw new Error("STRUMENTO_IN_MANUTENZIONE");
}
// Se arriva qui, lo strumento è disponibile
}
Nota: la funzione non restituisce true/false — lancia un errore con il motivo preciso. Questo rende i test più chiari e il codice chiamante più semplice (non deve controllare il valore di ritorno).
Prova di comprensione
- Elenca tre regole del dominio del tuo Registro. Per ognuna: dove sta il controllo?
- Perché è sbagliato mettere il controllo della regola direttamente nella UI?
- Cosa succede se lo stesso controllo è scritto in due posti e uno dei due è sbagliato?
Errori da evitare
- verificare le regole del dominio direttamente negli event listener della UI;
- usare messaggi utente come codici errore nel dominio (
throw new Error("Strumento guasto")); - avere la stessa regola verificata in più punti del codice;
- far dipendere la verifica della regola dall’archivio (il dominio non deve conoscere localStorage).
Prodotto da consegnare
Può essere:
- una funzione
puoEsserePrestatocompleta con tutti i controlli nel dominio; - un test per ogni regola di dominio verificata;
- una tabella codici-errore → messaggi-utente nella Presentation.
Checklist di chiusura
- Ogni regola del laboratorio ha una funzione nel dominio che la verifica
- I codici errore sono costanti chiare e univoche
- Il dominio non conosce messaggi per l’utente
- La UI traduce i codici in messaggi comprensibili
- Almeno una regola ha un test automatico
Domande per la revisione
- Hai trovato regole del dominio messe nella UI o nel caso d’uso? Dove?
- Il tuo dominio potrebbe funzionare con un archivio diverso senza toccare le regole?
- Un test che rompi deliberatamente una regola — il codice errore corretto viene lanciato?
Risultato atteso
Alla fine lo studente deve saper dire:
Nel mio Registro, la regola "[X]" è verificata in [file/funzione].
Lancia l'errore [Y] quando viene violata.
La UI mostra il messaggio: "[Z]".
Ho un test che verifica questo comportamento.
Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.