modulo 19 di 24 / Ore 41-60

Moduli 17-24 / Checkpoint 60 ore

Manutenzione: nomi, confini e dipendenze leggibili

Rendere il Registro del laboratorio più facile da mantenere nel tempo: scegliere nomi precisi, rispettare i confini tra livelli e rendere esplicite le dipendenze.

25 min Architettura del software

Manutenzione: nomi, confini e dipendenze leggibili

Questa lezione appartiene al Modulo 19 — Prestazioni e manutenzione.

Cos’è la manutenibilità

Un progetto manutenibile è un progetto che un’altra persona — o te stesso tra tre mesi — riesce a capire e modificare senza rompere nulla di inaspettato.

La manutenibilità dipende da tre cose concrete:

  1. Nomi precisi — le funzioni e le variabili dicono cosa fanno
  2. Confini rispettati — ogni livello fa solo il suo lavoro
  3. Dipendenze esplicite — si vede chiaramente chi dipende da chi

Questa lezione esamina ognuno dei tre nel contesto del Registro del laboratorio.

1. Nomi precisi

Un nome vago obbliga chi legge a indovinare. Un nome preciso trasmette intenzione.

// ❌ Nomi vaghi — bisogna leggere il corpo per capire
function f(x) { return x.filter(s => s.stato === "disponibile"); }
function handle(e) { e.preventDefault(); doStuff(); }
function proc(cmd) { /* ... */ }

// ✅ Nomi precisi — intenzione chiara dalla firma
function filtraDisponibili(strumenti) {
  return strumenti.filter(s => s.stato === "disponibile");
}
function gestisciSubmitPrestito(evento) { /* ... */ }
function registraPrestito(comando) { /* ... */ }

Segnali di nome vago nel Registro:

  • data, item, obj, res, val come nomi di variabili locali
  • handle, process, do, run come prefissi di funzione
  • manager, helper, utils come nomi di moduli senza specificare cosa gestiscono

Regola pratica: se devi leggere il corpo di una funzione per capire cosa fa, il nome è insufficiente.

2. Confini rispettati

Un confine tra livelli è rispettato quando ogni modulo conosce solo ciò che deve conoscere.

// ❌ Confine violato — il dominio conosce localStorage
function creaStrumento({ id, nome, categoria }) {
  const strumento = { id, nome, categoria, stato: "disponibile" };
  localStorage.setItem(`str-${id}`, JSON.stringify(strumento)); // ← Infrastructure nel Domain
  return strumento;
}

// ✅ Confine rispettato — il dominio crea, l'infrastruttura salva
function creaStrumento({ id, nome, categoria }) {
  return { id, nome, categoria, stato: "disponibile" };
}
// Il salvataggio avviene nell'archivio, chiamato dal caso d'uso

Come verificare i confini nel tuo progetto:

Leggi ogni file e chiediti: “questo file importa o usa qualcosa che appartiene a un altro livello?”

FileNon dovrebbe usare
domain/strumento.jslocalStorage, fetch, document, alert
application/registraPrestito.jslocalStorage, fetch, document, innerHTML
infrastructure/archivioLocalStorage.jsregole di dominio, casi d’uso
presentation/ui.jslocalStorage, JSON.parse, regole di prestabilità

3. Dipendenze esplicite

Una dipendenza esplicita è visibile nella firma della funzione. Una dipendenza nascosta emerge solo leggendo il corpo.

// ❌ Dipendenza nascosta — archivio globale
let archivioGlobale = [];

function registraStrumento(strumento) {
  archivioGlobale.push(strumento); // ← dipendenza da variabile globale, non visibile dalla firma
}

// ✅ Dipendenza esplicita — archivio passato come parametro
function creaRegistraStrumento({ archivio }) {
  return function registraStrumento(strumento) {
    archivio.salva(strumento); // ← dipendenza visibile nella firma del costruttore
  };
}

Come trovare dipendenze nascoste:

Cerca nel codice:

  • variabili dichiarate fuori dalla funzione ma usate dentro
  • chiamate a localStorage o document dentro funzioni di dominio o application
  • import di moduli che appartengono a un livello diverso

Esercizio di revisione

Apri il tuo progetto e compila questa scheda per tre punti specifici:

## Revisione manutenibilità

Punto 1 — Nome impreciso trovato:
  - File e riga:
  - Nome attuale:
  - Nome proposto:
  - Motivazione:

Punto 2 — Confine violato trovato:
  - File e riga:
  - Livello del file:
  - Cosa usa che non dovrebbe:
  - Dove dovrebbe stare quel codice:

Punto 3 — Dipendenza nascosta trovata:
  - File e riga:
  - Dipendenza da: (variabile globale / modulo esterno / localStorage)
  - Come renderla esplicita:

Come prioritizzare

Non tutto va corretto subito. Usa questa priorità:

  1. Prima — dipendenze nascoste: rendono il codice impossibile da testare
  2. Poi — confini violati: propagano problemi quando si cambia un livello
  3. Infine — nomi imprecisi: rallentano la comprensione ma non rompono nulla

Procedura guidata

  1. Apri un file alla volta, partendo da domain/.
  2. Per ogni funzione: il nome descrive esattamente cosa fa?
  3. Per ogni import o uso di variabile esterna: è del livello giusto?
  4. Per ogni dipendenza: è visibile nella firma o nascosta nel corpo?
  5. Annota i problemi trovati — correggi uno alla volta, verifica dopo ogni modifica.

Attività in classe

## Manutenzione: nomi, confini e dipendenze

File analizzato:

Nomi imprecisi trovati:

Confini violati trovati:

Dipendenze nascoste trovate:

Una correzione applicata:

Verifica che il comportamento sia rimasto identico:

Spiegazione guidata per studiare

La manutenibilità non è una caratteristica astratta — è il risultato di scelte concrete: nomi che comunicano, confini che separano, dipendenze che si vedono.

Il punto centrale è: un progetto manutenibile è un progetto leggibile. Se una funzione si chiama f, se un caso d’uso usa localStorage direttamente, se una variabile globale viene modificata da tre posti diversi — il progetto è difficile da mantenere non perché è grande, ma perché è opaco.

Il rischio tipico è rimandare la pulizia dei nomi e dei confini perché “il codice funziona”. Funziona oggi. Tra tre mesi, quando bisogna aggiungere un nuovo stato o cambiare l’archivio, quel debito tecnico rallenta tutto.

Passo per passo nel progetto

  1. Cerca tutte le funzioni con nomi di una sola lettera o generici (f, handle, proc).
  2. Cerca localStorage fuori dalla cartella infrastructure/.
  3. Cerca variabili dichiarate con let o var fuori dalle funzioni che le usano.
  4. Per ogni problema trovato: è urgente (rompe l’architettura) o estetico (nome impreciso)?
  5. Correggi un problema urgente e documenta la modifica.

Esempio da leggere lentamente

// Prima della revisione — tre problemi in 8 righe
let dati = [];  // dipendenza globale nascosta

function proc(x) {  // nome vago
  if (x.s === "ok") {  // confine violato? cosa è "s"?
    dati.push(x);
    localStorage.setItem("d", JSON.stringify(dati));  // infrastruttura nel dominio
  }
}

// Dopo la revisione — ogni problema risolto
function creaArchivioStrumenti() {
  const lista = [];  // dipendenza locale, non globale

  function salva(strumento) {  // nome preciso
    lista.push(strumento);  // solo logica applicativa
    // il salvataggio su localStorage è in un adapter separato
  }

  return { salva, leggiTutti: () => [...lista] };
}

Prova di comprensione

  • Hai trovato nel tuo progetto una funzione con nome vago? Qual è il nome migliore?
  • C’è localStorage fuori dalla cartella infrastructure/? Dove?
  • Esiste una variabile globale modificata da più funzioni? Come renderla locale?

Errori da evitare

  • rinominare senza verificare che tutti i chiamanti siano aggiornati;
  • correggere nome e confine nello stesso commit senza test intermedi;
  • ritenere i nomi imprecisi un problema “estetico” — rendono il codice opaco;
  • dimenticare di aggiornare il README o i commenti quando si rinomina qualcosa.

Prodotto da consegnare

Può essere:

  • una lista di tre problemi di manutenibilità trovati nel progetto con proposta di correzione;
  • una correzione applicata (rinomina, spostamento di codice nel livello corretto) con verifica;
  • una nota nel README che descrive le convenzioni di naming adottate nel progetto.

Checklist di chiusura

  • Ho trovato almeno un nome vago e proposto un nome migliore
  • Ho verificato che localStorage non appaia fuori da infrastructure/
  • Ho identificato le dipendenze nascoste (variabili globali, import incrociati)
  • Ho corretto almeno un problema e verificato che il comportamento non sia cambiato
  • Le modifiche sono documentate (commit, nota nel README, commento nel codice)

Domande per la revisione

  • Dopo la revisione, riesci a capire cosa fa ogni funzione solo leggendo il nome?
  • I confini tra livelli sono più chiari ora?
  • Quali dipendenze hai reso esplicite? Che differenza fa?

Risultato atteso

Alla fine lo studente deve saper dire:

Ho trovato questi problemi di manutenibilità nel Registro:
- Nome vago: [funzione] → rinominata in [nome migliore]
- Confine violato: [file] usava [localStorage/fetch] → spostato in [livello corretto]
- Dipendenza nascosta: [variabile globale] → resa locale o passata come parametro
Ho verificato che il comportamento è rimasto identico dopo le correzioni.

Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.