modulo 07 di 24 / Ore 0-20

Moduli 1-8 / Checkpoint 20 ore

RegistraStrumento: input, validazione minima e salvataggio

Costruire il caso d'uso RegistraStrumento coordinando input, modello di dominio e archivio, senza dipendere dalla UI.

30 min Architettura del software

RegistraStrumento: input, validazione minima e salvataggio

Il primo caso d’uso che costruiamo e:

RegistraStrumento

Scopo:

Aggiungere al registro uno strumento valido.

Sembra semplice, ed e proprio per questo e un buon punto di partenza.

Obiettivo

Alla fine devi avere un caso d’uso che:

  • riceve i dati dello strumento;
  • crea uno Strumento usando il dominio;
  • salva lo strumento in un archivio;
  • restituisce lo strumento registrato;
  • non legge direttamente dalla UI;
  • non usa direttamente localStorage.

Il comando

Il caso d’uso riceve un comando.

Esempio:

const comando = {
  id: "s-001",
  nome: "Arduino Uno",
  categoria: "microcontrollori",
  stato: "disponibile",
};

La UI puo costruire questo oggetto leggendo un form, ma il caso d’uso non deve sapere da dove arriva.

Il comando potrebbe arrivare anche da:

  • test;
  • CLI;
  • file;
  • API futura.

Il dominio crea lo strumento

Nel dominio abbiamo una funzione simile:

export function creaStrumento({ id, nome, categoria, stato }) {
  if (!nome || nome.trim() === "") {
    throw new Error("NOME_STRUMENTO_OBBLIGATORIO");
  }

  return {
    id: id.trim(),
    nome: nome.trim(),
    categoria: categoria.trim(),
    stato,
  };
}

Il caso d’uso non deve duplicare questa validazione.

Deve chiamarla.

Archivio in memoria minimo

Per ora possiamo usare un archivio semplice.

File:

src/infrastructure/archivioStrumentiInMemoria.js

Esempio:

export function creaArchivioStrumentiInMemoria() {
  const strumenti = [];

  return {
    salva(strumento) {
      strumenti.push(strumento);
      return strumento;
    },

    tutti() {
      return [...strumenti];
    },
  };
}

Questo archivio e ancora semplice. Piu avanti lo sostituiremo con localStorage.

La cosa importante e che il caso d’uso non deve conoscere come l’archivio salva i dati.

Scrivere il caso d’uso

File:

src/application/registraStrumento.js

Codice:

import { creaStrumento } from "../domain/strumento.js";

export function creaRegistraStrumento({ archivioStrumenti }) {
  return function registraStrumento(comando) {
    const strumento = creaStrumento({
      id: comando.id,
      nome: comando.nome,
      categoria: comando.categoria,
      stato: comando.stato,
    });

    archivioStrumenti.salva(strumento);

    return strumento;
  };
}

Questa forma usa una funzione che riceve le dipendenze e restituisce il caso d’uso.

Non serve chiamarla subito “dependency injection”. Basta capire il vantaggio:

posso passare archivi diversi senza cambiare il caso d'uso

Uso dal codice di avvio

Nel punto di avvio dell’applicazione:

const archivioStrumenti = creaArchivioStrumentiInMemoria();

const registraStrumento = creaRegistraStrumento({
  archivioStrumenti,
});

registraStrumento({
  id: "s-001",
  nome: "Arduino Uno",
  categoria: "microcontrollori",
  stato: "disponibile",
});

Questo codice puo stare in main.js o in un file di composizione.

Uso dalla UI

La UI puo fare:

form.addEventListener("submit", (event) => {
  event.preventDefault();

  const comando = {
    id: inputId.value,
    nome: inputNome.value,
    categoria: inputCategoria.value,
    stato: selectStato.value,
  };

  try {
    registraStrumento(comando);
    mostraMessaggio("Strumento registrato.");
  } catch (errore) {
    mostraMessaggio(messaggioPerErrore(errore));
  }
});

Qui la UI legge input e mostra messaggi.

Il caso d’uso registra lo strumento.

Il dominio valida lo strumento.

L’archivio salva.

Validazione minima

Nel caso d’uso possiamo fare solo validazioni applicative se servono.

Esempio:

Il comando deve esistere.

Ma non dobbiamo duplicare:

nome obbligatorio
stato valido
categoria obbligatoria

Se sono regole del modello Strumento, restano nel dominio.

Scenario

Scrivi:

## Caso d'uso

RegistraStrumento

## Scenario valido

Dato un comando con id, nome, categoria e stato validi,
quando registro lo strumento,
allora lo strumento viene salvato nell'archivio e restituito.

## Scenario non valido

Dato un comando senza nome,
quando registro lo strumento,
allora ottengo errore NOME_STRUMENTO_OBBLIGATORIO e nulla viene salvato.

Esercizio

Implementa o descrivi RegistraStrumento.

Poi verifica manualmente:

  1. registro uno strumento valido;
  2. controllo che sia nell’archivio;
  3. provo a registrare uno strumento senza nome;
  4. controllo che non venga salvato;
  5. verifico che la UI mostri un messaggio comprensibile.

Cosa produrre

Alla fine della lezione devi avere:

  • file src/application/registraStrumento.js;
  • caso d’uso RegistraStrumento;
  • archivio in memoria minimo o equivalente;
  • almeno due scenari;
  • nessun riferimento a document.querySelector nel caso d’uso;
  • nessun riferimento diretto a localStorage nel caso d’uso.

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 registraStrumento: input, validazione minima e salvataggio, il punto centrale è questo: Gestire errori significa distinguere origine, significato e messaggio. Un errore di dominio non è uguale a un campo mancante o a un salvataggio fallito.

Il rischio tipico è mostrare all’utente il messaggio tecnico grezzo oppure nascondere tutti gli errori dietro una frase generica. L’utente deve sapere cosa fare; chi mantiene il sistema deve poter capire cosa è successo. 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. Classifica l’errore: input, dominio, applicazione o infrastruttura.
  4. Scrivi un messaggio utente breve e utile.
  5. Conserva il dettaglio tecnico solo dove serve.
  6. Testa almeno uno scenario di errore.
  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:

const messaggi = {
  STRUMENTO_NON_TROVATO: "Strumento non trovato.",
  STRUMENTO_GUASTO_NON_PRESTABILE: "Questo strumento è guasto e non può essere prestato.",
  ARCHIVIO_NON_DISPONIBILE: "Non riesco a salvare i dati. Riprova tra poco."
};

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:

  • il caso d’uso riceve un comando;
  • il dominio crea lo strumento;
  • l’archivio salva lo strumento;
  • la UI non contiene la logica di registrazione;
  • posso chiamare RegistraStrumento da un test.

Nella prossima lezione costruiamo CercaStrumenti.