modulo 02 di 24 / Ore 0-20

Moduli 1-8 / Checkpoint 20 ore

Aggiungere ricerca e cambio stato nel modo più diretto

Estendere il registro fragile con ricerca per nome, categoria o stato e con un cambio stato diretto, osservando come cresce il costo di modifica.

25 min Architettura del software

Aggiungere ricerca e cambio stato nel modo più diretto

Ora rendiamo il Registro più utile.

Aggiungeremo:

  • ricerca per testo;
  • filtro per stato;
  • cambio stato manuale.

Lo faremo nel modo più diretto possibile. Questo significa che il codice non sarà ancora ben separato. Va bene: stiamo ancora costruendo materiale da analizzare.

Obiettivo della lezione

Alla fine avrai:

  • un campo di ricerca;
  • un filtro per stato;
  • una funzione che aggiorna i risultati;
  • un controllo per cambiare stato a uno strumento;
  • salvataggio aggiornato dopo il cambio stato;
  • una lista di nuove fragilità introdotte dalla funzionalità.

Questa lezione mostra una cosa importante: un programma può diventare più utile per l’utente e più fragile per chi lo mantiene nello stesso momento.

Perché aggiungere funzionalità prima di rifinire

Se sistemiamo troppo presto la struttura, rischiamo di progettare al buio.

Prima vogliamo vedere come cresce il codice quando arrivano richieste normali:

  • “posso cercare uno strumento?”;
  • “posso vedere solo quelli guasti?”;
  • “posso cambiare rapidamente lo stato?”;

Queste richieste sembrano piccole. Ma se il codice è tutto nello stesso file, ogni richiesta aumenta il miscuglio.

Aggiornare l’HTML

Aggiungi una sezione di ricerca:

<section>
  <h2>Ricerca</h2>
  <label>
    Cerca per nome o categoria
    <input id="ricerca" />
  </label>

  <label>
    Stato
    <select id="filtro-stato">
      <option value="">Tutti</option>
      <option value="disponibile">Disponibile</option>
      <option value="in_prestito">In prestito</option>
      <option value="guasto">Guasto</option>
      <option value="in_manutenzione">In manutenzione</option>
    </select>
  </label>
</section>

<section>
  <h2>Cambio stato</h2>
  <label>
    Nuovo stato
    <select id="nuovo-stato">
      <option value="disponibile">Disponibile</option>
      <option value="in_prestito">In prestito</option>
      <option value="guasto">Guasto</option>
      <option value="in_manutenzione">In manutenzione</option>
    </select>
  </label>
  <button id="cambia-stato">Cambia stato</button>
</section>

Stiamo ancora usando input e select direttamente dalla UI. Non stiamo cercando una struttura elegante: stiamo estendendo la versione fragile.

Aggiungere i riferimenti nel JavaScript

In main.js aggiungi:

const inputRicerca = document.querySelector("#ricerca");
const filtroStato = document.querySelector("#filtro-stato");
const selectNuovoStato = document.querySelector("#nuovo-stato");
const bottoneCambiaStato = document.querySelector("#cambia-stato");

La lista dei riferimenti DOM cresce. Questo è un segnale: main.js sta diventando il centro di tutto.

Ogni nuovo elemento della pagina porta una nuova costante, un nuovo event listener, nuovi controlli e nuovi casi da ricordare.

Rendere mostraStrumenti più flessibile

Modifica mostraStrumenti per accettare una lista:

function mostraStrumenti(lista) {
  strumentiElement.innerHTML = `
    <ul>
      ${lista
        .map(
          (strumento) => `
            <li>
              <strong>${strumento.nome}</strong>
              <span>${strumento.categoria}</span>
              <span>${strumento.stato}</span>
              <code>${strumento.id}</code>
            </li>
          `,
        )
        .join("")}
    </ul>
  `;
}

Alla fine del file userai:

mostraStrumenti(strumenti);

Questa modifica è ragionevole: la funzione non mostra più sempre tutti gli strumenti, ma mostra la lista che riceve.

È un piccolo miglioramento, anche dentro un file ancora fragile.

Aggiungere ricerca e filtro

Scrivi una funzione diretta:

function aggiornaRisultati() {
  const testo = inputRicerca.value.toLowerCase();
  const stato = filtroStato.value;

  const risultati = strumenti.filter((strumento) => {
    const corrispondeTesto =
      strumento.nome.toLowerCase().includes(testo) ||
      strumento.categoria.toLowerCase().includes(testo);

    const corrispondeStato = stato === "" || strumento.stato === stato;

    return corrispondeTesto && corrispondeStato;
  });

  mostraStrumenti(risultati);
}

Poi collega gli eventi:

inputRicerca.addEventListener("input", aggiornaRisultati);
filtroStato.addEventListener("change", aggiornaRisultati);

Funziona, ma osserva cosa succede:

  • la ricerca legge direttamente gli input HTML;
  • la ricerca conosce la struttura degli strumenti;
  • la ricerca decide quali campi cercare;
  • la ricerca chiama direttamente il render.

Non è ancora un errore da correggere. È un segnale da annotare.

Aggiungere il cambio stato

Scrivi il cambio stato nel modo più diretto:

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

  if (!strumento) {
    messaggioElement.textContent = "Strumento non trovato";
    return;
  }

  strumento.stato = nuovoStato;

  localStorage.setItem("strumenti", JSON.stringify(strumenti));
  messaggioElement.textContent = `Stato aggiornato: ${nuovoStato}`;
  aggiornaRisultati();
});

Questo codice è comodo, ma pericoloso.

Permette di impostare qualunque stato senza chiedersi se il passaggio abbia senso. Per esempio, potresti cambiare uno strumento da guasto a in_prestito senza registrare un prestito.

Per ora lo lasciamo così. Sarà materiale per le regole di dominio.

Cosa abbiamo guadagnato

Il programma ora è più utile:

  • puoi cercare strumenti;
  • puoi filtrare per stato;
  • puoi cambiare stato;
  • puoi vedere i risultati aggiornati;
  • puoi salvare lo stato aggiornato.

Dal punto di vista dell’utente è un miglioramento reale.

Cosa abbiamo perso

Dal punto di vista della manutenzione, il codice è più fragile:

  • la UI conosce tutti gli stati;
  • la UI modifica direttamente gli strumenti;
  • il salvataggio è dentro l’evento;
  • la ricerca è legata agli input HTML;
  • il cambio stato non rispetta regole esplicite;
  • ogni nuova funzionalità aumenta main.js;
  • stringhe come in_prestito e in_manutenzione iniziano a comparire in più punti.

Questa è una lezione importante: aggiungere valore all’utente può aumentare il disordine interno se non si governa la struttura.

Il problema delle stringhe di stato

Gli stati sono scritti come stringhe:

"disponibile"
"in_prestito"
"guasto"
"in_manutenzione"

Questo sembra innocuo, ma crea un rischio.

Se in un punto scrivi:

"in_prestito"

e in un altro:

"in_prestito"

per il programma sono due valori diversi.

Il filtro potrebbe non funzionare. La regola potrebbe non scattare. Il messaggio potrebbe essere sbagliato.

Non risolviamo ancora questo problema. Lo teniamo in vista, perché porterà alla modellazione di StatoStrumento.

Attività guidata

Implementa:

  1. input di ricerca;
  2. filtro per stato;
  3. funzione aggiornaRisultati;
  4. cambio stato manuale;
  5. salvataggio dopo il cambio stato.

Poi prova:

  • cerca notebook;
  • filtra guasto;
  • cambia uno strumento in in_manutenzione;
  • cerca lo strumento modificato;
  • prova a cambiare uno strumento guasto in in_prestito;
  • ricarica la pagina, se hai già aggiunto caricamento da localStorage.

Annota i casi in cui il comportamento è comodo ma rischioso.

Micro-sfida

Aggiungi un filtro per categoria.

Vincoli:

  • fallo ancora nel modo diretto;
  • non creare un modulo di dominio;
  • non creare un adapter;
  • aggiorna aggiornaRisultati;
  • annota quante righe devi cambiare.

Risultato atteso: puoi filtrare, per esempio, solo notebook o solo elettronica.

Domanda da annotare: aggiungere un filtro ha richiesto solo UI o ha toccato anche logica di ricerca?

Prodotto da ottenere

Alla fine della lezione devi avere:

  • campo di ricerca funzionante;
  • filtro per stato funzionante;
  • cambio stato diretto;
  • salvataggio aggiornato dopo il cambio stato;
  • eventuale filtro categoria della micro-sfida;
  • lista di almeno tre fragilità nuove;
  • nota sul problema delle stringhe di stato.

Domande di comprensione

Rispondi per iscritto:

  • Perché aggiungiamo funzionalità prima di refactorare?
  • Quali responsabilità sono entrate in main.js con la ricerca?
  • Perché il cambio stato diretto è comodo ma rischioso?
  • Che problema nasce quando gli stati sono stringhe ripetute?
  • Quale parte di questa lezione ti sembra più difficile da testare?

Controllo finale

La lezione è completata quando puoi dire sì a queste domande:

  • la ricerca per testo funziona;
  • il filtro per stato funziona;
  • il cambio stato modifica la lista;
  • il salvataggio viene aggiornato;
  • hai notato almeno tre nuove fragilità;
  • sai spiegare perché il cambio stato diretto non è una buona regola di dominio.

Nel prossimo passo introdurremo un bug realistico. Non sarà un errore assurdo: sarà proprio il tipo di bug che nasce quando stati, stringhe, UI e regole sono sparsi nello stesso file.