modulo 08 di 24 / Ore 0-20

Moduli 1-8 / Checkpoint 20 ore

Spostare il dominio fuori dalla UI

Estrarre regole e modelli dal codice di interfaccia, lasciando alla UI il compito di leggere input e mostrare risultati.

30 minArchitettura del software

Spostare il dominio fuori dalla UI

Una delle correzioni piu importanti del primo checkpoint e questa:

Le regole principali non devono stare nella UI.

Se una regola vive dentro un event listener, vale solo in quel punto.

Il dominio deve poter essere chiamato da UI, test, casi d’uso e futuri adattatori senza dipendere dal browser.

Obiettivo

Alla fine devi avere:

  • almeno una regola spostata dalla UI al dominio;
  • una funzione di dominio chiamabile senza browser;
  • un event listener piu piccolo;
  • uno scenario di verifica.

Punto di partenza fragile

Esempio:

buttonPresta.addEventListener("click", () => {
  const id = inputStrumentoId.value;
  const strumento = strumenti.find((item) => item.id === id);

  if (strumento.stato === "guasto") {
    messaggio.textContent = "Strumento guasto";
    return;
  }

  if (strumento.stato === "in_manutenzione") {
    messaggio.textContent = "Strumento in manutenzione";
    return;
  }

  strumento.stato = "in_prestito";
  renderizzaStrumenti();
});

Qui la UI contiene una regola:

guasto e in_manutenzione impediscono il prestito

La regola deve uscire.

Estrarre la regola

Nel dominio:

src/domain/strumento.js

scrivi:

import { StatoStrumento } from "./statoStrumento.js";

export function verificaStrumentoPrestabile(strumento) {
  if (strumento.stato !== StatoStrumento.DISPONIBILE) {
    throw new Error("STRUMENTO_NON_PRESTABILE");
  }
}

Ora la regola e nominata.

Non e nascosta dentro un click.

Usare la regola dalla UI

Nella UI:

buttonPresta.addEventListener("click", () => {
  const id = inputStrumentoId.value;
  const strumento = strumenti.find((item) => item.id === id);

  try {
    verificaStrumentoPrestabile(strumento);
    strumento.stato = "in_prestito";
    renderizzaStrumenti();
  } catch (errore) {
    messaggio.textContent = messaggioPerErrore(errore);
  }
});

Questo e un miglioramento, ma non e il punto finale.

La UI chiama ancora direttamente il dominio e modifica lo stato.

Nel passo successivo useremo i casi d’uso.

Per ora il focus e:

la regola non e piu scritta dentro la UI

Verificare senza browser

Puoi creare uno scenario:

const strumento = {
  id: "s-001",
  nome: "Proiettore",
  stato: "guasto",
};

verificaStrumentoPrestabile(strumento);

Risultato atteso:

STRUMENTO_NON_PRESTABILE

Questo controllo non richiede DOM.

Se riesci a farlo, la regola e uscita dalla UI.

Regole candidate da spostare

Cerca nella UI controlli come:

if (strumento.stato === "guasto")
if (!nome)
if (prestito.stato === "chiuso")
if (strumento.stato !== "disponibile")

Non tutti vanno spostati nello stesso modo.

Ma questi sono buoni candidati:

  • strumento senza nome;
  • stato strumento non valido;
  • strumento non prestabile;
  • prestito gia chiuso;
  • descrizione guasto obbligatoria.

Cosa resta nella UI

La UI puo ancora fare:

const id = inputStrumentoId.value;
messaggio.textContent = "Operazione non riuscita";
renderizzaStrumenti();

Questo e il suo lavoro.

Ma non deve decidere:

quali stati rendono lo strumento prestabile

Esercizio guidato

Scegli una regola presente nella UI.

Compila:

## Regola da spostare

Frase della regola:

Dove si trova ora:

Nuovo file nel dominio:

Nome della funzione:

Errore previsto:

Scenario di verifica:

Poi fai lo spostamento a piccoli passi.

Cosa produrre

Alla fine della lezione devi avere:

  • almeno una regola estratta dalla UI;
  • file di dominio aggiornato;
  • UI piu corta;
  • scenario manuale o test candidato;
  • nota nel README o nella scheda di refactoring.

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 spostare il dominio fuori dalla UI, il punto centrale è questo: Il dominio contiene il significato del problema: strumenti, prestiti, stati ammessi e regole che devono valere anche se cambia la UI o il modo in cui salviamo i dati.

Il rischio tipico è confondere un controllo di schermata con una regola del progetto. Se una regola protegge il senso del Registro, deve vivere nel dominio o vicino al caso d’uso. 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

  1. 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?”.
  2. Apri solo i file necessari. Se devi toccare più di tre file, fermati e scrivi prima una mini-mappa.
  3. Scrivi la regola in linguaggio naturale.
  4. Trasformala in una funzione o in un metodo con un nome leggibile.
  5. Verifica almeno un caso valido e un caso non valido.
  6. Controlla che la regola non sia duplicata nella UI.
  7. 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 verificaStrumentoPrestabile(strumento) {
  if (strumento.stato === "guasto") {
    throw new Error("STRUMENTO_GUASTO_NON_PRESTABILE");
  }
  if (strumento.stato === "in_prestito") {
    throw new Error("STRUMENTO_GIA_IN_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:

  • ho trovato una regola nella UI;
  • l’ho spostata nel dominio;
  • la UI chiama codice esterno invece di riscrivere la regola;
  • posso verificare la regola senza DOM;
  • il comportamento non e cambiato.

Nella prossima lezione spostiamo i casi d’uso fuori dagli event listener.