modulo 22 di 24 / Ore 41-60
Moduli 17-24 / Checkpoint 60 ore
Esercizio: refactoring avanzato documentato
Come documentare un refactoring avanzato nel Registro: prima/dopo del codice, motivazione della scelta, trade-off, verifica che il comportamento sia invariato.
Esercizio: refactoring avanzato documentato
Questa lezione appartiene al Modulo 22 — Valutazione e riflessione tecnica.
Il lavoro continua il progetto guida, il Registro del laboratorio scolastico. In questa lezione esegui un refactoring più complesso — estrazione di responsabilità, separazione di preoccupazioni — e lo documenti completamente: prima, dopo, motivazione, trade-off.
Obiettivo della lezione
Eseguire un refactoring avanzato su una parte complessa del Registro e documentarlo con: il codice prima, il codice dopo, la motivazione della scelta, i trade-off e la verifica che il comportamento sia invariato.
Alla fine devi avere: un file REFACTORING.md (o una sezione nel README) con il refactoring documentato in modo che il docente possa capire cosa è cambiato e perché.
Cosa distingue un refactoring avanzato
Un refactoring avanzato non rinomina variabili — cambia la struttura. Esempi nel Registro:
- separare la validazione dell’input dal caso d’uso in una funzione dedicata
- estrarre la logica di mappatura DTO ↔ dominio in un modulo separato
- separare la costruzione di un nuovo Prestito da
apriPrestitoin una funzione del dominio - dividere un adapter lungo in funzioni più piccole con responsabilità chiare
La caratteristica comune è che dopo il refactoring il codice ha meno responsabilità per modulo — ogni pezzo fa una sola cosa.
Il formato di documentazione
Per ogni refactoring avanzato, usa questo formato:
- titolo del refactoring (una frase)
- problema nel codice originale (perché era difficile da leggere o testare)
- codice prima
- codice dopo
- motivazione (perché questa struttura è migliore)
- trade-off (cosa si paga per questa struttura migliore)
- verifica (quale test o controllo dimostra che il comportamento è invariato)
Procedura guidata
- Scegli un punto del Registro con una responsabilità mista o una funzione troppo lunga.
- Scrivi il codice prima nella documentazione.
- Esegui il refactoring passo per passo.
- Scrivi il codice dopo.
- Scrivi motivazione e trade-off.
- Verifica che i test passino ancora.
- Aggiungi la documentazione al README o a
REFACTORING.md.
Attività in classe
Identifica il punto del tuo Registro più adatto al refactoring avanzato:
## Punto candidato al refactoring
File e funzione: ___
Problema: ___
Tipo di refactoring: estrazione funzione / separazione responsabilità / altro
Impatto stimato: quale livello cambia?
Spiegazione guidata per studiare
Documentare un refactoring è importante quanto eseguirlo. Senza documentazione, il refactoring sembra una modifica casuale al codice — il docente (e il te del futuro) non capisce perché la struttura è cambiata.
Il trade-off è la parte più difficile da scrivere — ma anche la più onesta. Un refactoring non è mai gratuito: aggiunge file, aggiunge livelli di indirezione, richiede più lettura per capire il flusso. Se non puoi nominare il trade-off, probabilmente non hai ancora capito completamente il refactoring che hai fatto.
Passo per passo nel progetto
Esempio concreto: estrazione della validazione da registraStrumento.
Codice originale con responsabilità miste:
// application/registraStrumento.js — PRIMA
export function registraStrumento({ nome, categoria }, archivio) {
// validazione (responsabilità 1)
if (!nome || nome.trim() === "") throw new Error("NOME_OBBLIGATORIO");
if (!categoria || categoria.trim() === "") throw new Error("CATEGORIA_OBBLIGATORIA");
if (nome.trim().length < 2) throw new Error("NOME_TROPPO_CORTO");
if (nome.trim().length > 80) throw new Error("NOME_TROPPO_LUNGO");
const categorie = ["misura", "saldatura", "perforazione", "alimentazione"];
if (!categorie.includes(categoria.trim())) throw new Error("CATEGORIA_NON_VALIDA");
// costruzione oggetto (responsabilità 2)
const nuovoStrumento = {
id: crypto.randomUUID(),
nome: nome.trim(),
categoria: categoria.trim(),
stato: "disponibile"
};
// persistenza (responsabilità 3)
const strumenti = archivio.caricaTutti();
strumenti.push(nuovoStrumento);
archivio.salva(strumenti);
return nuovoStrumento;
}
La funzione ha tre responsabilità: validare, costruire, persistere. Un test che vuole verificare solo la validazione deve passare anche un archivio.
Codice dopo il refactoring con responsabilità separate:
// domain/strumento.js — funzioni estratte nel dominio
const CATEGORIE_VALIDE = ["misura", "saldatura", "perforazione", "alimentazione"];
export function validaStrumento({ nome, categoria }) {
if (!nome || nome.trim() === "") throw new Error("NOME_OBBLIGATORIO");
if (nome.trim().length < 2) throw new Error("NOME_TROPPO_CORTO");
if (nome.trim().length > 80) throw new Error("NOME_TROPPO_LUNGO");
if (!categoria || !CATEGORIE_VALIDE.includes(categoria.trim())) {
throw new Error("CATEGORIA_NON_VALIDA");
}
}
export function creaStrumento({ nome, categoria }) {
validaStrumento({ nome, categoria });
return {
id: crypto.randomUUID(),
nome: nome.trim(),
categoria: categoria.trim(),
stato: "disponibile"
};
}
// application/registraStrumento.js — DOPO: solo coordinazione
import { creaStrumento } from "../domain/strumento.js";
export function registraStrumento({ nome, categoria }, archivio) {
const nuovoStrumento = creaStrumento({ nome, categoria }); // delega validazione e costruzione
const strumenti = archivio.caricaTutti();
strumenti.push(nuovoStrumento);
archivio.salva(strumenti);
return nuovoStrumento;
}
- Scrivi la documentazione del refactoring:
## Refactoring: estrazione validazione e costruzione in domain/strumento.js
Problema originale:
registraStrumento aveva tre responsabilità nello stesso file: validazione,
costruzione dell'oggetto e persistenza. Testare la validazione richiedeva
passare un archivio finto. Le regole di validazione erano lontane dal dominio.
Motivazione:
La validazione e le regole di costruzione appartengono al dominio —
non al caso d'uso. Spostarle in strumento.js permette di testarle
senza archivio e di riutilizzarle da altri casi d'uso futuri.
Trade-off:
Il flusso è più distribuito su due file — chi legge registraStrumento
deve aprire anche strumento.js per capire le regole di validazione.
Questo è accettabile per un dominio con regole non banali.
Verifica:
I test esistenti di registraStrumento passano ancora senza modifiche.
Sono stati aggiunti test diretti su validaStrumento e creaStrumento
senza archivio — molto più veloci da scrivere e leggere.
Prova di comprensione
Rispondi per iscritto:
- Quale responsabilità hai separato nel tuo refactoring?
- Qual è il trade-off che hai pagato per questa separazione?
- Come verifichi che il comportamento sia invariato dopo un refactoring che sposta codice tra file?
- Potresti testare la validazione prima del refactoring senza passare un archivio? E dopo?
Errori da evitare
- fare un refactoring che cambia il comportamento (non è refactoring, è una modifica);
- non documentare il trade-off — fa sembrare il refactoring sempre positivo senza costi;
- spostare codice senza capire le dipendenze — creare cicli di import;
- non eseguire i test dopo il refactoring.
Prodotto da consegnare
Il refactoring eseguito e documentato con il formato prima/dopo/motivazione/trade-off/verifica. Come verifica: mostra la documentazione al docente e spiega verbalmente il ragionamento.
Checklist di chiusura
- il refactoring è documentato con il codice prima e dopo;
- la motivazione spiega perché la nuova struttura è migliore, non solo diversa;
- il trade-off è nominato esplicitamente;
- i test passano ancora dopo il refactoring;
- la documentazione è nel README o in
REFACTORING.md.
Risultato atteso
Ho eseguito un refactoring avanzato su: [funzione e file].
Il problema originale era: [descrizione].
La nuova struttura separa: [responsabilità A] da [responsabilità B].
Il trade-off è: [descrizione onesta del costo].
I test passano. La documentazione è nel README.