modulo 06 di 24 / Ore 0-20
Moduli 1-8 / Checkpoint 20 ore
Che cosa mettiamo nel dominio
Capire che cosa appartiene al dominio del Registro del laboratorio e che cosa deve restare fuori: UI, localStorage, HTML e dettagli tecnici.
Che cosa mettiamo nel dominio
Nel modulo precedente abbiamo raccolto utenti, azioni, vincoli, requisiti e parole importanti. Ora iniziamo a trasformare quel materiale in codice organizzato.
Il primo livello da costruire è il dominio.
Nel nostro corso, dominio significa: la parte del programma che rappresenta il problema del laboratorio scolastico. Non è la pagina web. Non è il salvataggio dati. Non è il modo in cui il bottone reagisce al click. È il punto in cui il progetto dice che cosa sono uno strumento, un prestito, uno stato valido e una regola che non deve essere violata.
Nel Registro del laboratorio il dominio parla di:
- strumenti;
- prestiti;
- stati degli strumenti;
- segnalazioni di guasto;
- regole di prestito;
- regole di chiusura;
- errori legati a regole violate.
Il dominio non parla di:
- HTML;
- CSS;
document.querySelector;- eventi del browser;
localStorage;- JSON salvato su disco;
- chiamate API;
- messaggi colorati nella pagina.
Questa separazione è una delle idee più importanti del corso. Se capiamo bene questa lezione, le prossime diventano molto più ordinate.
Obiettivo della lezione
Alla fine devi saper guardare una frase, un pezzo di codice o una funzione e decidere se appartiene al dominio oppure no.
Devi anche iniziare a preparare una piccola cartella domain, con file che rappresentano i concetti centrali del Registro:
src/
domain/
strumento.js
statoStrumento.js
prestito.js
Non è ancora il modello finale. È il primo confine visibile.
La domanda guida
Per capire se qualcosa appartiene al dominio, usa questa domanda:
Questa cosa sarebbe ancora vera se cambiassi interfaccia o salvataggio dati?
Esempio:
Uno strumento guasto non può essere prestato.
Questa frase resta vera se usiamo una pagina web, una CLI, un test automatico, localStorage, un file JSON, un database o una API. Quindi appartiene al dominio.
Esempio contrario:
Il messaggio di errore viene scritto dentro un div con id "messaggio".
Questa frase dipende dalla UI. Se passiamo da una pagina web a una CLI, non esiste più nessun div. Quindi non appartiene al dominio.
Altro esempio:
Gli strumenti vengono salvati con la chiave "registro-strumenti" in localStorage.
Questa frase riguarda il modo in cui conserviamo i dati nel browser. Se passiamo a un file JSON o a una API, cambia. Quindi appartiene all’infrastruttura, non al dominio.
La domanda non risolve tutto, ma è un ottimo filtro iniziale.
Dominio non significa “tutti i dati”
Un errore comune è pensare che il dominio sia semplicemente il posto dove mettiamo gli oggetti dati.
Per esempio:
const strumento = {
id: "s-1",
nome: "Microscopio",
categoria: "ottica",
stato: "disponibile",
};
Questo oggetto può far parte del dominio, ma da solo non basta. Il dominio non contiene solo dati: contiene anche significato.
Domande di dominio:
- uno strumento può esistere senza nome?
- quali stati sono ammessi?
- uno strumento guasto può essere prestato?
- che cosa succede quando un prestito viene chiuso?
- un prestito chiuso può essere chiuso una seconda volta?
Se nel dominio mettiamo solo oggetti senza regole, le regole finiranno altrove: nella UI, nei casi d’uso, nel salvataggio dati, o peggio ancora duplicate in più punti.
Cosa entra nel dominio
Nel Registro del laboratorio entrano nel dominio i concetti che restano veri anche cambiando tecnologia.
Strumento
Uno strumento è un oggetto o dispositivo del laboratorio. Può essere un microscopio, un tablet, un sensore, un kit Arduino, una stampante 3D o un oscilloscopio.
Nel dominio ci interessano almeno:
- identificativo;
- nome;
- categoria;
- stato.
Esempio:
const strumento = {
id: "str-001",
nome: "Microscopio ottico",
categoria: "ottica",
stato: "disponibile",
};
StatoStrumento
Lo stato indica la condizione corrente dello strumento. Per questo percorso useremo stati semplici:
export const StatoStrumento = {
DISPONIBILE: "disponibile",
IN_PRESTITO: "in_prestito",
GUASTO: "guasto",
IN_MANUTENZIONE: "in_manutenzione",
};
Gli stati non sono etichette grafiche. Sono informazioni che determinano che cosa si può fare.
Per esempio:
- disponibile: lo strumento può essere prestato;
- in prestito: lo strumento non può essere prestato di nuovo;
- guasto: lo strumento non può essere prestato;
- in manutenzione: lo strumento non può essere prestato.
Prestito
Un prestito rappresenta il periodo in cui uno strumento è assegnato a una persona e non è disponibile per altri.
Nel dominio ci interessano almeno:
- identificativo del prestito;
- identificativo dello strumento;
- nome o identificativo dello studente;
- data di inizio;
- eventuale data di chiusura;
- stato del prestito, aperto o chiuso.
Esempio:
const prestito = {
id: "pre-001",
strumentoId: "str-001",
studente: "Luca Bianchi",
dataInizio: "2026-05-09",
dataChiusura: null,
chiuso: false,
};
Regole e invarianti
Una regola di dominio dice che cosa è permesso. Una invariante è una regola che deve rimanere vera sempre, non solo quando l’utente compila bene il form.
Esempi:
Uno strumento deve avere un nome non vuoto.
Uno strumento deve avere uno stato valido.
Uno strumento guasto non può essere prestato.
Uno strumento in manutenzione non può essere prestato.
Uno strumento già in prestito non può essere prestato di nuovo.
Un prestito chiuso non può essere chiuso di nuovo.
Queste frasi sono dominio perché non dipendono dal browser.
Cosa resta fuori dal dominio
Restano fuori dal dominio tutti i dettagli che riguardano come l’utente interagisce con il sistema o come i dati vengono conservati.
Esempi di Presentation:
const nome = document.querySelector("#nome").value;
messaggioElement.textContent = "Strumento registrato";
listaElement.innerHTML = strumenti.map(renderStrumento).join("");
Questo codice riguarda campi, messaggi e rendering. Non deve stare nel dominio.
Esempi di Infrastructure:
localStorage.setItem("strumenti", JSON.stringify(strumenti));
const strumenti = JSON.parse(localStorage.getItem("strumenti") ?? "[]");
const risposta = await fetch("/api/strumenti");
Questo codice riguarda il modo in cui leggiamo o salviamo dati. Non deve stare nel dominio.
Esempio di Application:
export function registraPrestito({ archivioStrumenti, archivioPrestiti }) {
return function esegui(comando) {
const strumento = archivioStrumenti.trovaPerId(comando.strumentoId);
const prestito = creaPrestito({
strumento,
studente: comando.studente,
dataInizio: comando.dataInizio,
});
archivioPrestiti.salva(prestito);
archivioStrumenti.salva(prestaStrumento(strumento));
};
}
Questo codice coordina più operazioni. Non è UI, non è salvataggio concreto, ma non è nemmeno una regola pura del dominio. Lo vedremo meglio nel modulo sui casi d’uso.
Per ora ci basta questa idea:
Domain = concetti e regole del laboratorio.
Application = sequenze di lavoro del sistema.
Presentation = input e output verso l'utente.
Infrastructure = dettagli tecnici esterni al dominio.
Prima e dopo: togliere una regola dalla UI
Nel programma fragile potremmo avere una funzione così:
function prestaDaBottone() {
const id = inputStrumentoId.value;
const studente = inputStudente.value;
const strumento = strumenti.find((item) => item.id === id);
if (strumento.stato === "guasto") {
messaggio.textContent = "Strumento guasto";
return;
}
if (strumento.stato === "in_prestito") {
messaggio.textContent = "Strumento già in prestito";
return;
}
strumento.stato = "in_prestito";
localStorage.setItem("strumenti", JSON.stringify(strumenti));
messaggio.textContent = "Prestito registrato";
}
Questa funzione funziona, ma mescola quattro responsabilità:
- legge input dalla UI;
- cerca uno strumento;
- controlla regole di dominio;
- salva dati in
localStorage; - mostra messaggi.
Il primo passo non è riscrivere tutto. Il primo passo è isolare una regola.
export function puoEsserePrestato(strumento) {
return strumento.stato === "disponibile";
}
Questa funzione è semplice, ma ha un vantaggio enorme: possiamo usarla senza browser.
Poi possiamo renderla più esplicita:
import { StatoStrumento } from "./statoStrumento.js";
export function verificaStrumentoPrestabile(strumento) {
if (strumento.stato === StatoStrumento.GUASTO) {
throw new Error("STRUMENTO_GUASTO_NON_PRESTABILE");
}
if (strumento.stato === StatoStrumento.IN_MANUTENZIONE) {
throw new Error("STRUMENTO_IN_MANUTENZIONE_NON_PRESTABILE");
}
if (strumento.stato === StatoStrumento.IN_PRESTITO) {
throw new Error("STRUMENTO_GIA_IN_PRESTITO");
}
}
Questa funzione non decide come mostrare l’errore all’utente. Dice solo quale regola è stata violata. In seguito la UI potrà trasformare STRUMENTO_GIA_IN_PRESTITO in un messaggio comprensibile.
Il dominio non deve essere complicato
Separare il dominio non significa introdurre una architettura pesante. Non serve partire con classi astratte, ereditarietà, pattern avanzati o framework.
In questo corso possiamo usare funzioni e oggetti semplici.
Esempio:
import { StatoStrumento } from "./statoStrumento.js";
export function creaStrumento({ id, nome, categoria, stato = StatoStrumento.DISPONIBILE }) {
if (!id) {
throw new Error("ID_STRUMENTO_OBBLIGATORIO");
}
if (!nome || nome.trim() === "") {
throw new Error("NOME_STRUMENTO_OBBLIGATORIO");
}
if (!Object.values(StatoStrumento).includes(stato)) {
throw new Error("STATO_STRUMENTO_NON_VALIDO");
}
return {
id,
nome: nome.trim(),
categoria: categoria?.trim() || "senza categoria",
stato,
};
}
Questo è dominio anche se non usa classi. La domanda giusta non è:
Sto usando classi?
La domanda giusta è:
Sto rappresentando un concetto o una regola del laboratorio?
Se la risposta è sì, probabilmente siamo nel dominio.
Tre criteri pratici
Quando hai un dubbio, usa questi tre criteri.
Primo criterio: indipendenza dalla UI.
Posso eseguire questa funzione in un test senza aprire il browser?
Se la funzione usa document, window, campi HTML o elementi della pagina, non è dominio.
Secondo criterio: indipendenza dalla persistenza.
La funzione funziona anche se i dati arrivano da un array, da localStorage o da una API?
Se la funzione usa direttamente localStorage, fetch o file JSON, non è dominio.
Terzo criterio: linguaggio del problema.
Il nome della funzione parla di strumenti, prestiti, stati o regole del laboratorio?
Nomi come prestaStrumento, chiudiPrestito, verificaStrumentoPrestabile sono vicini al dominio. Nomi come renderCard, readForm, saveToLocalStorage appartengono ad altri livelli.
Esercizio di classificazione
Classifica questi elementi scrivendo accanto:
Dominio
Application
Presentation
Infrastructure
Da chiarire
Elementi:
1. Uno strumento guasto non può essere prestato.
2. Il bottone "Registra prestito" apre una finestra.
3. Un prestito chiuso non può essere chiuso di nuovo.
4. Gli strumenti vengono salvati in localStorage.
5. Uno strumento deve avere un nome.
6. La lista mostra gli strumenti in una tabella.
7. Lo stato "in_manutenzione" impedisce il prestito.
8. Il file JSON contiene una proprietà "tools".
9. Il caso d'uso registra un prestito e aggiorna lo stato dello strumento.
10. Se la ricerca non trova risultati, viene mostrato un messaggio.
Possibile soluzione:
1. Dominio
2. Presentation
3. Dominio
4. Infrastructure
5. Dominio
6. Presentation
7. Dominio
8. Infrastructure
9. Application
10. Presentation
La riga 9 è utile: coordinare più operazioni è spesso responsabilità applicativa, anche se usa regole del dominio.
Attività sul progetto
Apri il programma fragile costruito nei moduli precedenti. Cerca almeno tre regole che oggi sono mescolate a UI o salvataggio dati.
Esempi possibili:
- controllo sullo stato guasto prima di un prestito;
- controllo sul nome vuoto quando registri uno strumento;
- controllo sul prestito già chiuso;
- controllo sullo stato
in_manutenzione; - controllo su prestito duplicato.
Poi prepara la cartella:
src/
domain/
statoStrumento.js
strumento.js
prestito.js
Dentro statoStrumento.js scrivi una prima bozza:
export const StatoStrumento = {
DISPONIBILE: "disponibile",
IN_PRESTITO: "in_prestito",
GUASTO: "guasto",
IN_MANUTENZIONE: "in_manutenzione",
};
Dentro strumento.js annota, anche solo come commento o appunto, le regole candidate:
// Regole candidate:
// - uno strumento deve avere un nome
// - uno strumento deve avere uno stato valido
// - solo uno strumento disponibile può essere prestato
Nelle prossime lezioni trasformeremo queste note in funzioni più precise.
Cosa produrre
Alla fine della lezione devi avere:
- una cartella o sezione dedicata al dominio;
- una lista di elementi che entrano nel dominio;
- una lista di elementi che restano fuori;
- almeno tre regole candidate da spostare fuori dalla UI;
- una prima bozza dei file
strumento.js,statoStrumento.js,prestito.js; - una risposta scritta alla domanda: “perché il dominio non deve conoscere
localStorage?”.
Controllo finale
La lezione è completata quando puoi rispondere sì a queste domande:
- so spiegare che cosa significa dominio in questo progetto;
- so distinguere dominio, UI, applicazione e persistenza;
- ho individuato almeno tre regole del dominio;
- non ho messo
document.querySelectornel dominio; - non ho messo
localStoragenel dominio; - posso immaginare un test sul dominio senza aprire il browser;
- so dire che cosa resta fuori dal dominio e perché.
Nella prossima lezione modelliamo il primo concetto concreto: Strumento. Partiremo da id, nome, categoria e stato, ma soprattutto dalle regole che impediscono di creare strumenti senza significato.