modulo 14 di 24 / Ore 21-40
Moduli 9-16 / Checkpoint 40 ore
Esercizio: refactoring a passi piccoli con commit intermedi
Come eseguire un refactoring a passi piccoli nel Registro con commit intermedi: un passo equivale a una verifica equivale a un commit, con struttura dei messaggi di commit.
Esercizio: refactoring a passi piccoli con commit intermedi
Questa lezione appartiene al Modulo 14 — Refactoring.
Il lavoro continua il progetto guida, il Registro del laboratorio scolastico. In questa lezione esegui un refactoring reale a passi piccoli, ognuno verificato e committato separatamente prima di procedere al successivo.
Obiettivo della lezione
Eseguire un refactoring strutturato nel Registro applicando la regola: un passo di refactoring = una verifica che il sistema funziona ancora = un commit. Nessun passo grande, nessun commit con troppe modifiche insieme.
Alla fine devi avere: una sequenza di commit nel log git, ognuno con una modifica piccola e verificata, e il sistema funzionante identico a prima del refactoring.
Il principio del refactoring a passi piccoli
Il refactoring non aggiunge funzionalità — cambia la struttura del codice mantenendo il comportamento uguale. Il rischio del refactoring è rompere qualcosa mentre si migliora la struttura.
La strategia dei passi piccoli riduce questo rischio: ogni passo è abbastanza piccolo da poter verificare rapidamente che il comportamento non è cambiato. Se qualcosa si rompe, si torna al commit precedente senza perdere tutto il lavoro.
La struttura dei commit è: refactor: [cosa hai fatto] senza cambiare comportamento.
Un refactoring concreto nel Registro
Il soggetto di questo esercizio è la funzione apriPrestito — spesso la più complessa dei casi d’uso. Una versione con problemi strutturali:
// PRIMA — apriPrestito con problemi
export function apriPrestito({ strumentoId }, as, ap) {
const s = as.caricaTutti();
let trovato;
for (let i = 0; i < s.length; i++) {
if (s[i].id === strumentoId) { trovato = s[i]; break; }
}
if (!trovato) throw new Error("STRUMENTO_NON_TROVATO");
if (trovato.stato !== "disponibile") throw new Error("STRUMENTO_NON_DISPONIBILE");
trovato.stato = "in-prestito";
as.salva(s);
const ps = ap.caricaTutti();
const np = { id: crypto.randomUUID(), strumentoId: strumentoId, dataApertura: new Date().toISOString().split("T")[0], dataChiusura: null };
ps.push(np);
ap.salva(ps);
return np;
}
Problemi strutturali: nomi dei parametri non leggibili (as, ap, s, ps), ciclo for invece di find, tutto in una sola funzione senza struttura.
Procedura guidata
- Scegli la funzione da refactorizzare nel tuo Registro.
- Esegui ogni passo nell’ordine: modifica → verifica → commit.
- Non passare al passo successivo senza aver verificato e committato.
- Se un passo rompe qualcosa, usa
git diffper capire cosa è cambiato e correggilo. - Alla fine, verifica che il comportamento complessivo sia identico a prima.
Attività in classe
Prima di iniziare, pianifica i passi:
## Piano di refactoring
Funzione da refactorizzare: ___
Problema principale: ___
Passo 1: (descrizione)
Verifica: (come controlli che funziona ancora)
Commit message: refactor: ___
Passo 2: ___
Passo 3: ___
Spiegazione guidata per studiare
Un commit di refactoring dovrebbe avere un messaggio che inizia con refactor: e descrive cosa è cambiato nella struttura, non nel comportamento. “refactor: rinomina parametri as e ap in archivioStrumenti e archivioPrestiti” è un buon messaggio. “fix: migliorato il codice” non è utile.
Il test di verifica tra un passo e l’altro non deve essere complesso — basta eseguire il caso d’uso manualmente nel browser o con il file di test. Se il test passa, il passo è sicuro. Se non passa, si torna al commit precedente.
Passo per passo nel progetto
Esegui questi sette passi in ordine sul tuo Registro:
Passo 1 — rinomina i parametri:
// da: export function apriPrestito({ strumentoId }, as, ap)
// a:
export function apriPrestito({ strumentoId }, archivioStrumenti, archivioPrestiti)
Verifica: esegui apriPrestito nel browser — funziona ancora.
Commit: git commit -m "refactor: rinomina parametri as/ap in archivioStrumenti/archivioPrestiti"
Passo 2 — rinomina le variabili locali:
// da: const s = archivioStrumenti.caricaTutti()
// a:
const strumenti = archivioStrumenti.caricaTutti();
E ps → prestiti, trovato → strumento, np → nuovoPrestito.
Verifica: esegui apriPrestito — funziona ancora.
Commit: git commit -m "refactor: rinomina variabili locali con nomi leggibili"
Passo 3 — sostituisci il ciclo for con Array.find:
// da: ciclo for
// a:
const strumento = strumenti.find(s => s.id === strumentoId);
Verifica: esegui il test dei casi limite — STRUMENTO_NON_TROVATO funziona ancora.
Commit: git commit -m "refactor: sostituisce ciclo for con Array.find"
Passo 4 — estrai la creazione del nuovo prestito in una funzione:
function creaNuovoPrestito(strumentoId) {
return {
id: crypto.randomUUID(),
strumentoId,
dataApertura: new Date().toISOString().split("T")[0],
dataChiusura: null
};
}
Verifica: il prestito viene creato correttamente.
Commit: git commit -m "refactor: estrae creaNuovoPrestito come funzione separata"
Passo 5 — aggiungi una riga vuota tra le due fasi dell’operazione (commento separatore):
export function apriPrestito({ strumentoId }, archivioStrumenti, archivioPrestiti) {
// fase 1: aggiorna lo strumento
const strumenti = archivioStrumenti.caricaTutti();
const strumento = strumenti.find(s => s.id === strumentoId);
if (!strumento) throw new Error("STRUMENTO_NON_TROVATO");
if (strumento.stato !== "disponibile") throw new Error("STRUMENTO_NON_DISPONIBILE");
strumento.stato = "in-prestito";
archivioStrumenti.salva(strumenti);
// fase 2: crea il prestito
const prestiti = archivioPrestiti.caricaTutti();
const nuovoPrestito = creaNuovoPrestito(strumentoId);
prestiti.push(nuovoPrestito);
archivioPrestiti.salva(prestiti);
return nuovoPrestito;
}
Verifica: il flusso completo funziona.
Commit: git commit -m "refactor: aggiunge commenti di separazione fasi in apriPrestito"
Esempio JS — il risultato finale
// DOPO — apriPrestito leggibile dopo il refactoring
function creaNuovoPrestito(strumentoId) {
return {
id: crypto.randomUUID(),
strumentoId,
dataApertura: new Date().toISOString().split("T")[0],
dataChiusura: null
};
}
export function apriPrestito({ strumentoId }, archivioStrumenti, archivioPrestiti) {
// fase 1: verifica disponibilità e aggiorna strumento
const strumenti = archivioStrumenti.caricaTutti();
const strumento = strumenti.find(s => s.id === strumentoId);
if (!strumento) throw new Error("STRUMENTO_NON_TROVATO");
if (strumento.stato !== "disponibile") throw new Error("STRUMENTO_NON_DISPONIBILE");
strumento.stato = "in-prestito";
archivioStrumenti.salva(strumenti);
// fase 2: registra il prestito
const prestiti = archivioPrestiti.caricaTutti();
const nuovoPrestito = creaNuovoPrestito(strumentoId);
prestiti.push(nuovoPrestito);
archivioPrestiti.salva(prestiti);
return nuovoPrestito;
}
Il comportamento è identico. Il codice è molto più leggibile. Cinque commit separati, ognuno verificato.
Prova di comprensione
Rispondi per iscritto:
- Qual è la differenza tra un commit di refactoring e un commit di bugfix?
- Perché non fare tutto il refactoring in un unico commit grande?
- Cosa succede se il passo 3 (sostituzione del ciclo for) introduce un bug? Come lo identifichi?
- Hai eseguito i test dopo ogni passo? Cosa avresti perso se li avessi saltati?
Errori da evitare
- fare refactoring e aggiungere funzionalità nello stesso commit;
- fare passi troppo grandi — se un passo cambia più di 10 righe, è troppo grande;
- non verificare dopo ogni passo — la verifica è parte del processo, non un optional;
- scrivere messaggi di commit vaghi come “migliorato il codice”.
Prodotto da consegnare
La sequenza di commit nel log git (git log --oneline) che mostra i passi del refactoring. Come verifica: esegui git log --oneline e mostra i commit con i messaggi refactor: al docente.
Checklist di chiusura
- ogni passo di refactoring ha un commit separato;
- ogni commit ha un messaggio che inizia con
refactor:; - ho verificato il comportamento dopo ogni passo;
- il sistema funziona identicamente a prima del refactoring;
- i test dei casi limite passano ancora tutti.
Risultato atteso
Ho eseguito 5 passi di refactoring su apriPrestito.
Ogni passo ha un commit separato con messaggio refactor:.
Il comportamento è identico a prima — i test passano.
Il codice è più leggibile: nomi chiari, Array.find, funzione estratta.
git log --oneline mostra 5 commit di refactoring in sequenza.