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.

30 minArchitettura del software

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 apriPrestito in 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

  1. Scegli un punto del Registro con una responsabilità mista o una funzione troppo lunga.
  2. Scrivi il codice prima nella documentazione.
  3. Esegui il refactoring passo per passo.
  4. Scrivi il codice dopo.
  5. Scrivi motivazione e trade-off.
  6. Verifica che i test passino ancora.
  7. 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;
}
  1. 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.