modulo 06 di 24 / Ore 0-20

Moduli 1-8 / Checkpoint 20 ore

Regola: uno strumento guasto non può essere prestato

Implementare e verificare una regola di dominio fondamentale: uno strumento guasto deve essere escluso dai prestiti.

25 min Architettura del software

Regola: uno strumento guasto non può essere prestato

Ora prendiamo una regola concreta e la portiamo nel dominio:

Uno strumento guasto non può essere prestato.

Questa regola e facile da capire, ma spesso viene messa nel posto sbagliato.

Se resta solo nella UI, il sistema e fragile.

Obiettivo

Alla fine devi avere:

  • una funzione di dominio che rifiuta il prestito di uno strumento guasto;
  • uno scenario di test scritto in modo chiaro;
  • un esempio di UI che non contiene la regola;
  • un messaggio utente derivato dall’errore, non scritto dentro il dominio.

Il problema nel codice fragile

Nel programma fragile potremmo trovare:

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

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

  strumento.stato = "in_prestito";
});

Il controllo esiste, ma sta nel click handler.

Questo significa che la regola vale solo se il prestito passa da quel bottone.

Se domani aggiungiamo:

  • un altro bottone;
  • una scorciatoia;
  • una CLI;
  • un test;
  • una API;

dobbiamo ricordarci di copiare la stessa regola.

Questo e un segnale di architettura fragile.

Spostare la regola nel dominio

File:

src/domain/strumento.js

Possiamo aggiungere:

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

export function verificaStrumentoPrestabile(strumento) {
  if (strumento.stato === StatoStrumento.GUASTO) {
    throw new Error("STRUMENTO_GUASTO_NON_PRESTABILE");
  }

  return true;
}

Questa funzione non presta ancora lo strumento. Verifica una regola.

Il nome e intenzionale:

verificaStrumentoPrestabile

Non dice “controlla bottone” o “mostra errore”. Dice una cosa del dominio.

Rendere la regola piu generale

Subito dopo possiamo accorgerci che non e prestabile solo lo strumento guasto.

Anche in_manutenzione e in_prestito impediscono il prestito.

Allora possiamo scegliere una forma piu generale:

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

  return true;
}

Questa versione copre piu casi.

Pero in questa lezione ci concentriamo sul guasto per capire bene il passaggio.

Errore di dominio, messaggio utente

Il dominio puo produrre un errore tecnico interno:

STRUMENTO_GUASTO_NON_PRESTABILE

La UI lo trasforma in messaggio:

Questo strumento e guasto e non puo essere prestato.

Non fare questo nel dominio:

throw new Error("Questo strumento e guasto e non puo essere prestato.");

Perche il dominio inizierebbe a decidere il testo mostrato all’utente.

Meglio tenere separati:

  • codice errore nel dominio;
  • messaggio leggibile nella presentation;
  • eventuale log tecnico altrove.

Uso nel caso d’uso

Quando arriveremo al caso d’uso, la regola verra chiamata cosi:

export function registraPrestito({ strumento, datiPrestito }) {
  verificaStrumentoPrestabile(strumento);

  const prestito = apriPrestito(datiPrestito);
  const strumentoAggiornato = {
    ...strumento,
    stato: StatoStrumento.IN_PRESTITO,
  };

  return { prestito, strumento: strumentoAggiornato };
}

Il caso d’uso coordina.

La regola resta nel dominio.

Scenario di test

Scrivi lo scenario prima del test automatico:

## Regola

Uno strumento guasto non può essere prestato.

## Scenario

Dato uno strumento con stato guasto,
quando verifico se puo essere prestato,
allora ottengo errore STRUMENTO_GUASTO_NON_PRESTABILE.

Poi il test potrebbe essere:

import { verificaStrumentoPrestabile } from "../src/domain/strumento.js";
import { StatoStrumento } from "../src/domain/statoStrumento.js";

test("uno strumento guasto non può essere prestato", () => {
  const strumento = {
    id: "s-001",
    nome: "Proiettore",
    categoria: "video",
    stato: StatoStrumento.GUASTO,
  };

  expect(() => verificaStrumentoPrestabile(strumento)).toThrow(
    "STRUMENTO_GUASTO_NON_PRESTABILE"
  );
});

Se non hai ancora un test runner configurato, scrivi comunque lo scenario. Il test automatico arrivera piu avanti.

Esercizio

Prendi la funzione del tuo programma fragile che registra un prestito.

Trova il punto in cui controlla se lo strumento e guasto.

Poi:

  1. sposta il controllo in una funzione di dominio;
  2. lascia nella UI solo la traduzione dell’errore in messaggio;
  3. scrivi uno scenario di test;
  4. verifica manualmente che il prestito venga rifiutato.

Cosa produrre

Alla fine della lezione devi avere:

  • funzione verificaStrumentoPrestabile o equivalente;
  • controllo dello stato guasto fuori dalla UI;
  • scenario di test scritto;
  • messaggio utente chiaro;
  • nota nel README o nei documenti sulle regole del dominio.

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 regola: uno strumento guasto non può essere prestato, 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:

  • la regola non sta piu solo nel click handler;
  • il dominio rifiuta uno strumento guasto;
  • la UI mostra un messaggio, ma non decide la regola;
  • posso verificare la regola senza browser;
  • so spiegare perche questa regola appartiene al dominio.

Nella prossima lezione affrontiamo una regola simile ma piu sottile: lo strumento gia in prestito.