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.
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_prestitoein_manutenzioneiniziano 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:
- input di ricerca;
- filtro per stato;
- funzione
aggiornaRisultati; - cambio stato manuale;
- 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.jscon 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.