modulo 11 di 24 / Ore 21-40
Moduli 9-16 / Checkpoint 40 ore
Mostrare risultati senza duplicare regole
Costruire la vista dei risultati nella Presentation usando l'esito del caso d'uso, senza replicare condizioni o regole del dominio nella funzione di rendering.
Mostrare risultati senza duplicare regole
Questa lezione appartiene al Modulo 11 — Presentation: l’interfaccia come bordo del sistema.
Il problema della duplicazione
Quando la UI mostra i risultati di un’operazione, c’è la tentazione di aggiungere condizioni per decidere cosa mostrare. Alcune di queste condizioni sono logica di presentazione — appartengono alla UI. Altre sono regole del dominio — appartengono al dominio e non devono essere replicate.
La duplicazione crea due problemi:
- Inconsistenza: se la regola cambia nel dominio ma non nella UI, il comportamento diverge
- Manutenzione: la stessa logica va aggiornata in due punti ogni volta che cambia
Cosa appartiene alla UI e cosa no
Appartiene alla UI (logica di presentazione)
// Tradurre uno stato tecnico in un'etichetta leggibile
function etichettaStato(stato) {
const etichette = {
"disponibile": "Disponibile",
"in_prestito": "In prestito",
"guasto": "Guasto",
"in_manutenzione": "In manutenzione"
};
return etichette[stato] ?? stato;
}
// Scegliere una classe CSS in base allo stato
function classeDaStato(stato) {
return `strumento--${stato}`;
}
// Mostrare un messaggio di successo o errore
function mostraEsitoOperazione(successo, messaggioErrore) {
if (successo) mostraSuccesso("Operazione completata.");
else mostraErrore(messaggioErrore);
}
Non appartiene alla UI (regole del dominio)
// ❌ Queste condizioni sono regole del dominio — non metterle nel rendering
function renderListaStrumenti(strumenti) {
strumenti.forEach(s => {
const li = document.createElement("li");
// SBAGLIATO — queste sono regole del laboratorio, non presentazione
if (s.stato === "guasto" || s.stato === "in_prestito") {
li.classList.add("non-prestabile");
li.setAttribute("data-prestabile", "false");
}
contenitore.appendChild(li);
});
}
Come mostrare l’esito senza duplicare — tre pattern
Pattern 1: mostrare l’esito del caso d’uso
Il caso d’uso restituisce un risultato. La UI lo mostra senza reinterpretarlo.
// Application — il caso d'uso decide l'esito
async function registraPrestito(comando) {
const strumento = await archivioStrumenti.trovaPerId(comando.strumentoId);
if (!strumento) throw new Error("STRUMENTO_NON_TROVATO");
puoEsserePrestato(strumento); // lancia se non disponibile
const prestito = apriPrestito(strumento.id, new Date().toISOString());
await archivioPrestiti.salva({ ...prestito, assegnatario: comando.assegnatario });
await archivioStrumenti.salva({ ...strumento, stato: "in_prestito" });
return { prestitoId: prestito.id }; // ← esito minimo
}
// Presentation — mostra l'esito senza reinterpretare
try {
const esito = await registraPrestito(comando);
mostraSuccesso(`Prestito registrato. ID: ${esito.prestitoId}`);
} catch (errore) {
mostraErrore(messaggi[errore.message] ?? "Operazione non riuscita.");
}
Pattern 2: rendering da stato, non da regola
La UI mostra lo stato degli oggetti ricevuti — non applica regole su di essi.
// ✅ Il rendering riflette lo stato — non applica regole
function renderStrumento(strumento) {
return `
<li class="strumento strumento--${strumento.stato}">
<span>${strumento.nome}</span>
<span class="badge">${etichettaStato(strumento.stato)}</span>
</li>
`;
// La classe CSS dice lo stato, non se è prestabile.
// Chi può prestare e chi no — lo decide il dominio quando si tenta l'operazione.
}
Pattern 3: stato vuoto e stato di caricamento
Mostrare stati speciali dell’interfaccia — non errori di dominio.
function renderListaStrumenti(contenitore, strumenti, statoCaricamento) {
if (statoCaricamento === "caricamento") {
contenitore.innerHTML = "<p>Caricamento in corso...</p>";
return;
}
if (strumenti.length === 0) {
contenitore.innerHTML = "<p>Nessuno strumento trovato.</p>";
return;
}
contenitore.innerHTML = strumenti.map(renderStrumento).join("");
}
Questi stati (caricamento, vuoto) sono stati della UI — non regole del laboratorio.
Esempio: prima e dopo
Prima — regola duplicata nella UI
// ❌ La UI decide chi può prestare — regola del dominio nella Presentation
function renderListaStrumenti(strumenti) {
return strumenti.map(s => {
const prestabile = s.stato === "disponibile"; // ← regola del dominio!
return `
<li>
${s.nome}
${prestabile
? `<button data-id="${s.id}">Presta</button>`
: `<span>Non disponibile</span>`}
</li>
`;
}).join("");
}
Dopo — la UI usa lo stato, il dominio decide la regola
// ✅ La UI mostra lo stato — il dominio decide al momento dell'operazione
function renderListaStrumenti(strumenti) {
return strumenti.map(s => `
<li class="strumento--${s.stato}">
${s.nome}
<span class="badge">${etichettaStato(s.stato)}</span>
<button data-id="${s.id}" data-azione="presta">Presta</button>
</li>
`).join("");
// Il pulsante c'è sempre.
// Se si tenta di prestare uno strumento non disponibile,
// il caso d'uso lancia l'errore e la UI mostra il messaggio.
}
Il pulsante è sempre visibile. Se l’utente preme “Presta” su uno strumento guasto, il caso d’uso lancia STRUMENTO_GUASTO_NON_PRESTABILE e la UI mostra il messaggio. La regola sta nel dominio — non nella UI.
Procedura guidata
- Apri le funzioni di rendering della tua UI (
renderListaStrumenti,renderStrumento, ecc.). - Cerca condizioni
ifche controllanostato,chiusoIl, o altri campi del dominio. - Per ogni condizione: è logica di presentazione o è una regola del laboratorio?
- Sposta le regole del laboratorio fuori dal rendering.
- Verifica che il comportamento rimanga identico.
Attività in classe
## Mostrare risultati senza duplicare regole
Funzione di rendering analizzata:
Condizioni trovate nel rendering:
Per ogni condizione: logica di presentazione o regola del dominio?
Condizioni spostate fuori dal rendering:
Verifica del comportamento dopo la modifica:
Spiegazione guidata per studiare
La funzione di rendering ha un solo compito: trasformare dati in HTML. Non deve decidere se un’operazione è permessa — deve mostrare i dati che riceve.
Il punto centrale è: il rendering è puro — riceve dati e restituisce HTML, senza effetti collaterali e senza regole di dominio. Se una funzione di rendering ha un if (stato === "guasto") che decide cosa mostrare sulla base di una regola del laboratorio, quella condizione appartiene altrove.
Il rischio tipico è ottimizzare l’esperienza utente nascondendo pulsanti “non applicabili” direttamente nel rendering. Funziona, ma duplica la regola. La soluzione alternativa è mostrare sempre il pulsante e lasciare che il dominio risponda con un errore comprensibile.
Passo per passo nel progetto
- Apri tutte le funzioni di rendering.
- Elenca ogni
ifo operatore ternario che appare nel rendering. - Classifica: logica di presentazione (CSS, etichette, layout) o regola del dominio (chi può fare cosa)?
- Sposta le regole del dominio — non duplicarle.
- Verifica con scenari: strumento disponibile, guasto, in prestito — il rendering mostra lo stato corretto?
Esempio da leggere lentamente
// Rendering pulito — solo presentazione
function renderStrumento(strumento) {
const etichette = {
"disponibile": "Disponibile",
"in_prestito": "In prestito",
"guasto": "Guasto",
"in_manutenzione": "In manutenzione"
};
return `
<li class="strumento strumento--${strumento.stato}">
<strong>${strumento.nome}</strong>
<span>${strumento.categoria}</span>
<span class="badge badge--${strumento.stato}">
${etichette[strumento.stato] ?? strumento.stato}
</span>
<button data-id="${strumento.id}">Presta</button>
</li>
`;
// Nessuna regola del dominio.
// La classe CSS comunica lo stato all'utente tramite colore.
// Il tentativo di prestare uno strumento non disponibile viene
// gestito dal caso d'uso al momento del click.
}
Prova di comprensione
- Hai trovato nel tuo rendering condizioni che duplicano regole del dominio?
- Qual è la differenza tra “mostrare lo stato” e “applicare una regola”?
- Se la regola di prestabilità cambia (es. si aggiunge lo stato
"dismesso"), quanti file devi toccare nel tuo progetto attuale?
Errori da evitare
- nascondere pulsanti nel rendering in base a regole del dominio — duplica la regola;
- non mostrare mai stati intermedi (caricamento, lista vuota) — l’interfaccia sembra rotta;
- mescolare la traduzione delle etichette con la logica di business nello stesso blocco;
- rimuovere il rendering di uno stato senza verificare tutti gli scenari.
Prodotto da consegnare
Può essere:
- funzione
renderStrumentoche usa solo logica di presentazione, senza regole del dominio; - tre scenari testati manualmente: strumento disponibile, guasto, in prestito — screenshot o descrizione del comportamento;
- nota tecnica che spiega la differenza tra logica di presentazione e regola del dominio nel contesto del Registro.
Checklist di chiusura
- Le funzioni di rendering non contengono condizioni sulle regole del laboratorio
- Lo stato di ogni strumento viene mostrato con etichetta e classe CSS
- Lo stato vuoto (nessun risultato) è gestito con un messaggio
- Il pulsante di azione è sempre visibile — gli errori vengono gestiti dal caso d’uso
- Ho verificato il comportamento con strumenti in stati diversi
Domande per la revisione
- Hai trovato condizioni nel rendering che erano regole del dominio?
- Dopo le modifiche, quanti file bisogna aggiornare se cambia una regola di prestabilità?
- Il rendering funziona correttamente con una lista vuota? E con 100 strumenti?
Risultato atteso
Alla fine lo studente deve saper dire:
La mia funzione renderStrumento mostra [nome, categoria, stato, badge].
Non contiene condizioni sulle regole del laboratorio.
Ho verificato il rendering con strumenti in stati: disponibile, guasto, in prestito.
Se si tenta di prestare uno strumento non disponibile, il messaggio viene gestito da [caso d'uso].
Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.