modulo 11 di 24 / Ore 21-40
Moduli 9-16 / Checkpoint 40 ore
Micro-sfida: sposta una regola fuori dalla UI
Trovare una regola del laboratorio nascosta in un event listener della UI, spostarla nel dominio o nel caso d'uso, e verificare che il comportamento rimanga identico.
Micro-sfida: sposta una regola fuori dalla UI
Questa lezione appartiene al Modulo 11 — Presentation: l’interfaccia come bordo del sistema.
La sfida
Trova una condizione if nel tuo event listener che riguarda una regola del laboratorio. Spostala nel dominio o nel caso d’uso. Verifica che il comportamento del Registro sia identico prima e dopo.
Regola del pollice: se la condizione risponde a “il laboratorio permette questa operazione?”, appartiene al dominio — non alla UI.
Esempio concreto — prima e dopo
Prima: regola nella UI
// presentation/ui.js — PROBLEMA: la regola è nell'event listener
document.getElementById("btn-presta").addEventListener("click", () => {
const strumento = archivioStrumenti.trovaPerId(strumentoId); // ← anche questo è sbagliato
// Queste condizioni sono regole del laboratorio — non appartengono qui
if (strumento.stato === "guasto") {
mostraErrore("Strumento guasto.");
return;
}
if (strumento.stato === "in_prestito") {
mostraErrore("Già in prestito.");
return;
}
// Salva direttamente — senza passare dal caso d'uso
strumento.stato = "in_prestito";
archivioStrumenti.salva(strumento);
mostraSuccesso("Prestito registrato.");
});
Problemi in questo codice:
- Le regole (
guasto,in_prestito) sono nel posto sbagliato — duplicabili, testabili solo con il browser - L’event listener accede direttamente all’archivio — viola il confine Infrastructure
- Non c’è un caso d’uso — tutta la logica è nell’evento
Dopo: regola nel dominio, UI come bordo
// domain/strumento.js — le regole stanno qui
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/registraPrestito.js — il caso d'uso coordina
function creaRegistraPrestito({ archivioStrumenti, archivioPrestiti }) {
return async function registraPrestito(comando) {
const strumento = await archivioStrumenti.trovaPerId(comando.strumentoId);
if (!strumento) throw new Error("STRUMENTO_NON_TROVATO");
puoEsserePrestato(strumento); // ← chiama la regola del dominio
const prestito = apriPrestito(strumento.id, new Date().toISOString());
await archivioPrestiti.salva({ ...prestito, assegnatario: comando.assegnatario });
await archivioStrumenti.salva({ ...strumento, stato: "in_prestito" });
};
}
// presentation/ui.js — bordo pulito: solo input, chiamata, output
document.getElementById("btn-presta").addEventListener("click", async () => {
const comando = {
strumentoId: document.getElementById("strumento-id").value,
assegnatario: document.getElementById("assegnatario").value
};
try {
await registraPrestito(comando); // ← chiama il caso d'uso, non l'archivio
mostraSuccesso("Prestito registrato.");
} catch (errore) {
const messaggi = {
STRUMENTO_NON_TROVATO: "Strumento non trovato.",
STRUMENTO_GUASTO_NON_PRESTABILE: "Questo strumento è guasto.",
STRUMENTO_GIA_IN_PRESTITO: "Questo strumento è già in prestito.",
STRUMENTO_IN_MANUTENZIONE: "Questo strumento è in manutenzione."
};
mostraErrore(messaggi[errore.message] ?? "Operazione non riuscita.");
}
});
Come trovare la regola da spostare
Cerca nel tuo progetto queste condizioni negli event listener:
✓ strumento.stato === "guasto" → regola del dominio
✓ strumento.stato === "in_prestito" → regola del dominio
✓ prestito.chiusoIl !== null → regola del dominio
✓ lista.length > LIMITE → potrebbe essere regola del dominio
✗ form.value.trim() === "" → validazione input, sta bene nell'event listener
✗ elemento.classList.add(...) → presentazione, sta bene nell'event listener
I quattro passi della sfida
Passo 1: trova la condizione da spostare. Scrivi in una frase cosa fa:
"Se lo strumento è guasto, non permette il prestito."
Passo 2: crea o aggiorna la funzione nel dominio:
// domain/strumento.js — aggiungi o aggiorna
function puoEsserePrestato(strumento) {
if (strumento.stato !== "disponibile") {
throw new Error("STRUMENTO_NON_DISPONIBILE");
}
}
Passo 3: rimuovi la condizione dall’event listener e sostituisci con la chiamata al caso d’uso.
Passo 4: verifica che il comportamento sia identico:
- premi il pulsante con uno strumento disponibile → deve funzionare
- premi il pulsante con uno strumento guasto → deve mostrare il messaggio di errore corretto
- premi il pulsante con uno strumento in prestito → deve mostrare il messaggio di errore corretto
Attività in classe
## Micro-sfida: sposta una regola fuori dalla UI
Regola trovata nell'event listener (scrivi in linguaggio naturale):
File e riga dove stava:
Funzione creata o aggiornata nel dominio:
File dell'event listener modificato:
Verifica eseguita:
- Caso valido: [comportamento]
- Caso non valido 1: [comportamento]
- Caso non valido 2: [comportamento]
Comportamento cambiato rispetto a prima (sì/no):
(Deve essere "no" — il refactoring non cambia il comportamento)
Spiegazione guidata per studiare
Un event listener deve fare tre cose: leggere l’input, chiamare il caso d’uso, mostrare il risultato. Non deve decidere se un’operazione è permessa — quella è la responsabilità del dominio.
Il punto centrale è: se sposti la regola nel dominio e il comportamento del Registro rimane identico, hai fatto un refactoring corretto. La verifica è il momento più importante della sfida — non la modifica stessa.
Il rischio tipico è spostare la regola nel dominio ma lasciare una copia nell’event listener “per sicurezza”. Questo crea duplicazione: domani aggiorni la regola nel dominio ma dimentichi l’event listener, e il comportamento diverge.
Passo per passo nel progetto
- Apri tutti i file della
presentation/. - Cerca condizioni
ifche controllano lo stato di strumenti o prestiti. - Per ogni condizione: è una regola del laboratorio o una logica di presentazione?
- Sposta una regola nel dominio — una sola, per questa sfida.
- Rimuovi la copia dall’event listener — non lasciare duplicati.
- Verifica con almeno tre scenari: caso valido, un caso non valido, un secondo caso non valido.
Esempio da leggere lentamente
// Trovato nell'event listener:
if (strumento.stato === "guasto" || strumento.stato === "in_prestito") {
alert("Strumento non disponibile");
return;
}
// Spostato nel dominio come:
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");
}
// L'event listener diventa:
try {
await registraPrestito(comando); // il caso d'uso chiama puoEsserePrestato internamente
} catch (errore) {
mostraErrore(messaggi[errore.message] ?? "Operazione non riuscita.");
}
Il comportamento è identico. La regola è ora nel posto giusto: testabile, riutilizzabile, non duplicabile.
Prova di comprensione
- Hai trovato la regola da spostare nel tuo progetto?
- Dove stava prima? Dove sta adesso?
- Il comportamento del Registro è cambiato? (Deve essere: no.)
- Se aggiungi un quarto stato
"dismesso"— dove aggiungi il controllo?
Errori da evitare
- spostare la regola nel dominio e lasciare una copia nell’event listener;
- spostare la logica di presentazione invece della regola di dominio;
- non verificare i casi non validi dopo lo spostamento;
- modificare il comportamento mentre si fa il refactoring (deve restare identico).
Prodotto da consegnare
Può essere:
- la funzione
puoEsserePrestato(o analoga) aggiornata nel dominio; - l’event listener modificato che chiama il caso d’uso invece di controllare lo stato;
- la scheda della sfida compilata con i risultati delle verifiche.
Checklist di chiusura
- Ho trovato una condizione nell’event listener che è una regola del laboratorio
- L’ho spostata nel dominio come funzione con nome chiaro
- Ho rimosso la copia dall’event listener (nessun duplicato)
- Ho verificato almeno: caso valido, strumento guasto, strumento in prestito
- Il comportamento del Registro è identico prima e dopo
Domande per la revisione
- Quante condizioni simili hai trovato nel progetto? Ne hai spostata solo una — quali restano?
- Se aggiungi uno stato
"dismesso", quanti file devi toccare ora? E prima dello spostamento? - Hai trovato regole che invece appartengono davvero all’event listener? Quali?
Risultato atteso
Alla fine lo studente deve saper dire:
Ho trovato la regola "[descrizione]" nell'event listener di [file].
L'ho spostata in [domain/strumento.js o altra funzione del dominio].
Ho rimosso il controllo dall'event listener.
Ho verificato con questi scenari: [lista].
Il comportamento è rimasto identico.
Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.