modulo 07 di 24 / Ore 0-20

Moduli 1-8 / Checkpoint 20 ore

CercaStrumenti: filtri per nome, categoria e stato

Costruire il caso d'uso CercaStrumenti distinguendo filtri, normalizzazione dell'input e lettura dall'archivio.

25 minArchitettura del software

CercaStrumenti: filtri per nome, categoria e stato

Il secondo caso d’uso e:

CercaStrumenti

Scopo:

Trovare strumenti per nome, categoria o stato.

Questo caso d’uso e utile per chiarire una cosa: non tutte le operazioni modificano dati.

Cercare strumenti legge, filtra e restituisce risultati.

Obiettivo

Alla fine devi avere un caso d’uso che:

  • legge gli strumenti dall’archivio;
  • applica filtri opzionali;
  • non modifica i dati;
  • non dipende dalla UI;
  • restituisce una lista.

Il comando di ricerca

Il comando puo essere:

const comando = {
  testo: "arduino",
  categoria: "microcontrollori",
  stato: "disponibile",
};

Tutti i campi possono essere opzionali.

Esempi:

cercaStrumenti({ testo: "kit" });
cercaStrumenti({ stato: "guasto" });
cercaStrumenti({ categoria: "audio", stato: "disponibile" });
cercaStrumenti({});

Se il comando e vuoto, possiamo restituire tutti gli strumenti.

Archivio

L’archivio deve offrire una operazione per leggere gli strumenti.

Esempio:

const archivioStrumenti = {
  tutti() {
    return strumenti;
  },
};

Piu avanti potremmo decidere se il filtro deve stare nell’archivio o nel caso d’uso.

Per ora, con dati piccoli e laboratorio didattico, possiamo filtrare nel caso d’uso.

Normalizzare l’input

Per cercare in modo piu robusto:

function normalizzaTesto(valore) {
  return valore.trim().toLowerCase();
}

Questo permette di trattare:

Arduino
arduino
  ARDUINO

come ricerche equivalenti.

Non e una regola profonda di dominio. E una scelta applicativa utile per la ricerca.

Implementazione

File:

src/application/cercaStrumenti.js

Codice:

function normalizzaTesto(valore) {
  return String(valore ?? "").trim().toLowerCase();
}

export function creaCercaStrumenti({ archivioStrumenti }) {
  return function cercaStrumenti(filtri = {}) {
    const strumenti = archivioStrumenti.tutti();

    const testo = normalizzaTesto(filtri.testo);
    const categoria = normalizzaTesto(filtri.categoria);
    const stato = normalizzaTesto(filtri.stato);

    return strumenti.filter((strumento) => {
      const nomeCorrisponde =
        !testo || normalizzaTesto(strumento.nome).includes(testo);

      const categoriaCorrisponde =
        !categoria || normalizzaTesto(strumento.categoria) === categoria;

      const statoCorrisponde =
        !stato || normalizzaTesto(strumento.stato) === stato;

      return nomeCorrisponde && categoriaCorrisponde && statoCorrisponde;
    });
  };
}

Il caso d’uso riceve filtri e restituisce strumenti.

Non mostra “nessun risultato”. Quello e compito della UI.

La UI decide come mostrare risultati vuoti

Il caso d’uso puo restituire:

[]

La UI puo trasformarlo in:

Nessuno strumento trovato.

Non serve che CercaStrumenti conosca quel messaggio.

Attenzione: cercare non deve modificare

Questa e una regola pratica:

CercaStrumenti non modifica strumenti.

Quindi non deve:

  • cambiare stato;
  • salvare dati;
  • ordinare modificando l’array originale se non previsto;
  • correggere automaticamente categorie;
  • creare strumenti mancanti.

Legge e restituisce.

Scenari

Scrivi:

## Scenario 1

Dato un elenco di strumenti,
quando cerco "arduino",
allora ottengo gli strumenti con nome che contiene "arduino".

## Scenario 2

Dato un elenco di strumenti,
quando filtro per stato disponibile,
allora ottengo solo strumenti disponibili.

## Scenario 3

Dato un elenco di strumenti,
quando uso filtri vuoti,
allora ottengo tutti gli strumenti.

## Scenario 4

Dato un elenco di strumenti,
quando non ci sono corrispondenze,
allora ottengo una lista vuota.

Esercizio

Prepara questi dati:

const strumenti = [
  { id: "s-001", nome: "Arduino Uno", categoria: "microcontrollori", stato: "disponibile" },
  { id: "s-002", nome: "Kit sensori", categoria: "robotica", stato: "in_prestito" },
  { id: "s-003", nome: "Multimetro", categoria: "misura", stato: "guasto" },
];

Verifica:

  • ricerca per nome arduino;
  • ricerca per categoria robotica;
  • ricerca per stato guasto;
  • ricerca con testo non presente;
  • ricerca con filtri vuoti.

Cosa produrre

Alla fine della lezione devi avere:

  • file src/application/cercaStrumenti.js;
  • caso d’uso CercaStrumenti;
  • filtri per nome, categoria e stato;
  • almeno quattro scenari;
  • nessun messaggio UI dentro il caso d’uso;
  • garanzia che la ricerca non modifica i dati.

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 cercaStrumenti: filtri per nome, categoria e stato, 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

  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. Definisci input e output del caso d’uso.
  4. Leggi i dati attraverso un archivio o una dipendenza esplicita.
  5. Chiama le regole del dominio.
  6. Salva il risultato senza sapere come funziona la persistenza concreta.
  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 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:

  • posso cercare per nome;
  • posso filtrare per categoria;
  • posso filtrare per stato;
  • la ricerca restituisce una lista vuota se non trova nulla;
  • il caso d’uso non aggiorna lo stato degli strumenti;
  • la UI decide come mostrare i risultati.

Nella prossima lezione costruiamo il caso d’uso piu importante: RegistraPrestito.