modulo 08 di 24 / Ore 0-20
Moduli 1-8 / Checkpoint 20 ore
Collegare la UI ai casi d'uso
Collegare la pagina del Registro del laboratorio ai casi d'uso senza riportare regole e salvataggio dentro la UI.
Collegare la UI ai casi d’uso
Ora colleghiamo la UI ai casi d’uso.
Questo passaggio e delicato: dopo aver separato i file, e facile riportare tutto dentro la pagina per far funzionare rapidamente qualcosa.
Non vogliamo una UI isolata.
Vogliamo una UI collegata bene.
Obiettivo
Alla fine devi avere una UI che:
- legge input dai form;
- costruisce comandi;
- chiama casi d’uso;
- mostra risultati;
- mostra errori comprensibili;
- non contiene regole di dominio;
- non salva direttamente i dati.
Punto di composizione
Nel file di avvio possiamo comporre il sistema:
import { creaArchivioStrumentiInMemoria } from "./infrastructure/archivioStrumentiInMemoria.js";
import { creaArchivioPrestitiInMemoria } from "./infrastructure/archivioPrestitiInMemoria.js";
import { creaRegistraStrumento } from "./application/registraStrumento.js";
import { creaRegistraPrestito } from "./application/registraPrestito.js";
import { avviaUIRegistro } from "./presentation/uiRegistro.js";
const archivioStrumenti = creaArchivioStrumentiInMemoria();
const archivioPrestiti = creaArchivioPrestitiInMemoria();
const registraStrumento = creaRegistraStrumento({
archivioStrumenti,
});
const registraPrestito = creaRegistraPrestito({
archivioStrumenti,
archivioPrestiti,
});
avviaUIRegistro({
registraStrumento,
registraPrestito,
});
Questo file non contiene regole.
Collega pezzi.
UI come funzione di avvio
Nel file:
src/presentation/uiRegistro.js
possiamo scrivere:
export function avviaUIRegistro({ registraStrumento, registraPrestito }) {
const formStrumento = document.querySelector("#form-strumento");
const formPrestito = document.querySelector("#form-prestito");
const messaggio = document.querySelector("#messaggio");
formStrumento.addEventListener("submit", (event) => {
event.preventDefault();
try {
registraStrumento(leggiComandoStrumento());
messaggio.textContent = "Strumento registrato.";
} catch (errore) {
messaggio.textContent = messaggioPerErrore(errore);
}
});
formPrestito.addEventListener("submit", (event) => {
event.preventDefault();
try {
registraPrestito(leggiComandoPrestito());
messaggio.textContent = "Prestito registrato.";
} catch (errore) {
messaggio.textContent = messaggioPerErrore(errore);
}
});
}
La UI riceve casi d’uso gia pronti.
Non li costruisce da zero.
Costruire comandi
La UI puo avere funzioni come:
function leggiComandoStrumento() {
return {
id: document.querySelector("#strumento-id").value,
nome: document.querySelector("#strumento-nome").value,
categoria: document.querySelector("#strumento-categoria").value,
stato: document.querySelector("#strumento-stato").value,
};
}
Questo codice sta bene nella presentation.
Legge dalla pagina e costruisce un oggetto semplice.
Mostrare risultati
Dopo un caso d’uso, la UI puo aggiornare la schermata:
function renderizzaStrumenti(strumenti) {
listaStrumenti.innerHTML = "";
for (const strumento of strumenti) {
const riga = document.createElement("li");
riga.textContent = `${strumento.nome} - ${strumento.stato}`;
listaStrumenti.append(riga);
}
}
Questo e compito della UI.
Il dominio non deve sapere come viene renderizzata una lista.
Mostrare errori
File:
src/presentation/messaggiErrore.js
Esempio:
const messaggi = {
NOME_STRUMENTO_OBBLIGATORIO: "Inserisci il nome dello strumento.",
STRUMENTO_NON_TROVATO: "Strumento non trovato.",
STRUMENTO_NON_PRESTABILE: "Questo strumento non puo essere prestato.",
PRESTITO_GIA_CHIUSO: "Questo prestito e gia chiuso.",
};
export function messaggioPerErrore(errore) {
return messaggi[errore.message] ?? "Operazione non riuscita.";
}
La UI mostra il messaggio.
Il dominio produce codici errore.
Controllo: cosa non deve ricomparire nella UI
Cerca nella UI:
if (strumento.stato === "guasto")
localStorage.setItem(...)
prestiti.push(...)
strumento.stato = "in_prestito"
Se trovi questi pezzi, chiediti se devono stare:
- nel dominio;
- nel caso d’uso;
- nell’archivio.
La UI puo chiamare, non deve ricostruire tutto.
Esercizio
Collega almeno due casi d’uso alla UI:
RegistraStrumento;RegistraPrestito.
Per ciascuno compila:
## Collegamento UI
Caso d'uso:
Form o evento:
Comando costruito:
Messaggio di successo:
Errori gestiti:
Codice che non deve stare nella UI:
Cosa produrre
Alla fine della lezione devi avere:
main.jso punto di avvio che compone archivi, casi d’uso e UI;uiRegistro.jso file equivalente;- almeno due form collegati ai casi d’uso;
- funzione per trasformare errori in messaggi;
- nessuna regola di dominio duplicata nella UI.
Spiegazione guidata per studiare
Questa lezione va studiata su due piani. Il primo è il comportamento visibile del Registro del laboratorio: che cosa vede o fa l’utente quando registra uno strumento, cerca un dispositivo, apre un prestito o segnala un guasto. Il secondo è il confine architetturale: dove deve stare il codice che rende possibile quel comportamento.
Per collegare la UI ai casi d’uso, il punto centrale è questo: Un caso d’uso coordina un’operazione completa: riceve un comando, legge ciò che serve, applica regole, salva il risultato e restituisce un esito.
Il rischio tipico è far diventare il caso d’uso una seconda UI o un secondo database. Deve coordinare, non mostrare HTML e non conoscere dettagli tecnici di salvataggio. Per evitarlo, non partire dal file che hai già aperto nell’editor. Parti dalla domanda: “quale responsabilità sto modificando?”. Se la risposta riguarda una regola del laboratorio, guarda il dominio. Se riguarda una sequenza di operazioni, guarda i casi d’uso. Se riguarda salvataggio, file, localStorage, API o database, guarda l’infrastruttura. Se riguarda input, pulsanti, form e messaggi, guarda la Presentation.
Il tempo è sufficiente per alternare spiegazione, modifica guidata e revisione. Alla fine della lezione lo studente non deve ricordare una definizione a memoria: deve saper indicare un punto del progetto, spiegare perché quel codice sta lì e mostrare una verifica del comportamento.
Passo per passo nel progetto
- Rileggi il titolo della lezione e riscrivilo come domanda pratica. Per esempio: “dove deve stare questa regola?”, “chi deve salvare questo dato?”, “come verifico questo errore?”.
- Apri solo i file necessari. Se devi toccare più di tre file, fermati e scrivi prima una mini-mappa.
- Definisci input e output del caso d’uso.
- Leggi i dati attraverso un archivio o una dipendenza esplicita.
- Chiama le regole del dominio.
- Salva il risultato senza sapere come funziona la persistenza concreta.
- Aggiorna una nota breve nel README o negli appunti se hai cambiato un confine del progetto.
Esempio da leggere lentamente
Questo esempio serve a ragionare, non a incollare codice senza capire:
function registraPrestito(comando, archivioStrumenti, archivioPrestiti) {
const strumento = archivioStrumenti.trovaPerId(comando.strumentoId);
verificaStrumentoPrestabile(strumento);
const prestito = apriPrestito(strumento.id, comando.nomePersona);
archivioPrestiti.salva(prestito);
archivioStrumenti.salva({ ...strumento, stato: "in_prestito" });
return prestito;
}
Leggilo chiedendoti che cosa cambierebbe se domani sostituissimo la pagina web con una CLI, oppure localStorage con un’API. Se l’esempio continua ad avere senso senza riscrivere tutto, il confine è probabilmente buono. Se invece un dettaglio tecnico si propaga in molti file, il progetto sta tornando fragile.
Prova di comprensione
Prima di chiudere la lezione, rispondi per iscritto a queste domande:
- Qual è la responsabilità principale trattata in questa lezione?
- In quale livello del progetto dovrebbe stare?
- Quale errore faresti se cercassi la soluzione più veloce?
- Quale piccolo test, controllo manuale o esempio dimostra che hai capito?
- Che cosa deve restare facile da cambiare dopo questa lezione?
Una risposta accettabile non deve essere lunga. Deve però usare parole concrete del Registro: strumento, prestito, stato, archivio, caso d’uso, messaggio, test.
Controllo finale
La lezione e completata quando puoi rispondere si:
- la UI chiama i casi d’uso;
- la UI costruisce comandi;
- i casi d’uso sono creati fuori dagli event listener;
- la UI mostra errori comprensibili;
- la UI non salva direttamente i dati;
- la UI non contiene le regole principali.
Nella prossima lezione scriviamo i primi test sulle regole.