modulo 22 di 24 / Ore 41-60

Moduli 17-24 / Checkpoint 60 ore

Confrontare varianti tecniche senza dogmi

Come valutare due approcci tecnici nel Registro con criteri concreti — leggibilità, testabilità, complessità — senza preferenze ideologiche.

30 minArchitettura del software

Confrontare varianti tecniche senza dogmi

Questa lezione appartiene al Modulo 22 — Valutazione e riflessione tecnica.

Il lavoro continua il progetto guida, il Registro del laboratorio scolastico. Questa lezione insegna a confrontare due approcci tecnici diversi usando criteri oggettivi invece di preferenze personali o mode del momento.

Obiettivo della lezione

Scegliere due varianti tecniche reali che si presentano nel Registro — come array vs Map per gli strumenti, o localStorage vs archivio in memoria — e confrontarle su tre criteri: leggibilità, testabilità, complessità aggiunta. Documentare la scelta con motivazioni concrete.

Alla fine devi avere: una scheda di confronto compilata per almeno una coppia di varianti, con la decisione motivata.

I tre criteri di valutazione

Senza criteri espliciti, la scelta tecnica dipende dalla familiarità o dall’ultima cosa letta su internet. I tre criteri utili per il Registro sono:

Leggibilità — il codice che usa questa variante è più facile da capire per qualcuno che legge il progetto per la prima volta? Un mese dopo averlo scritto, capirai ancora perché funziona?

Testabilità — posso verificare questa variante senza browser, senza localStorage, senza dipendenze esterne? I test sono brevi e diretti?

Complessità aggiunta — questa variante richiede più codice, più file, più concetti da imparare? Il costo in complessità è giustificato dal problema che risolve?

Varianti tipiche nel Registro

Queste sono coppie di varianti concrete che si presentano nel Registro del laboratorio:

  • array vs Map per cercare strumenti per ID
  • throw new Error("codice") vs oggetto di risultato { ok, errore } nei casi d’uso
  • localStorage vs archivio in memoria per i test
  • funzione pura vs classe per il modello Strumento
  • find + mutazione vs map con copia per aggiornare uno strumento

Procedura guidata

  1. Scegli una coppia di varianti presenti nel tuo Registro.
  2. Scrivi il codice di entrambe le varianti (anche se una è solo abbozzata).
  3. Valuta le tre varianti su leggibilità, testabilità, complessità aggiunta — con una nota per ognuno.
  4. Scegli la variante preferita e scrivi la motivazione in una frase.
  5. Verifica che la scelta sia coerente con le scelte precedenti del progetto.

Attività in classe

Compila questa scheda per almeno una coppia di varianti:

## Confronto varianti — [nome della coppia]

Variante A: [descrizione]
Variante B: [descrizione]

Leggibilità — A: / B:
Testabilità — A: / B:
Complessità aggiunta — A: / B:

Scelta: A / B
Motivazione in una frase:
Coerente con il resto del progetto? sì / no — perché:

Spiegazione guidata per studiare

Il “dogma” in una scelta tecnica è quando la motivazione è “si fa così” o “questo approccio è migliore” senza riferimento al contesto. Array è meglio di Map? Dipende. Per cercare per ID con molte operazioni di ricerca, Map è O(1) invece di O(n). Per un registro con 50 strumenti, la differenza non si misura. Usare Map per eleganza aggiunge complessità senza beneficio.

L’antidogmatismo non significa relativismo — significa ancorare la scelta ai criteri reali del progetto. Se la testabilità è il criterio principale (e nel Registro lo è), la variante più testabile vince anche se è meno elegante.

Passo per passo nel progetto

Esempio 1: array vs Map per cercare uno strumento per ID

// Variante A — array con Array.find
export function trovaPerId(id) {
  return strumenti.find(s => s.id === id) ?? null;
}

// Variante B — Map con Map.get
const mappaStrumenti = new Map(strumenti.map(s => [s.id, s]));
export function trovaPerId(id) {
  return mappaStrumenti.get(id) ?? null;
}

Valutazione:

  • Leggibilità: A è più leggibile — find è familiare a tutti. B richiede capire come costruire la Map.
  • Testabilità: uguale — entrambe sono funzioni pure senza dipendenze esterne.
  • Complessità aggiunta: B aggiunge la costruzione della Map e il problema di tenerla sincronizzata con l’array.
  • Scelta per il Registro: A. Con meno di 100 strumenti, il costo di find è trascurabile. La Map aggiunge complessità senza beneficio misurabile.

Esempio 2: throw vs oggetto di risultato

// Variante A — throw con stringa di errore
export function apriPrestito({ strumentoId }, archivio) {
  const strumento = archivio.trovaPerId(strumentoId);
  if (!strumento) throw new Error("STRUMENTO_NON_TROVATO");
  // ...
}

// Variante B — oggetto di risultato
export function apriPrestito({ strumentoId }, archivio) {
  const strumento = archivio.trovaPerId(strumentoId);
  if (!strumento) return { ok: false, errore: "STRUMENTO_NON_TROVATO" };
  // ...
  return { ok: true, prestito };
}

Valutazione:

  • Leggibilità: A è più diretto per casi semplici. B è più esplicito ma richiede che il chiamante controlli ok.
  • Testabilità: B è più facile da testare — non bisogna wrappare in try/catch.
  • Complessità aggiunta: B richiede che ogni punto di chiamata controlli if (!risultato.ok).
  • Scelta per il Registro: dipende dalla coerenza con il resto del progetto. Se hai già usato throw, mantieni quella scelta. Non mescolare i due approcci nello stesso progetto.

Esempio 3: find + mutazione vs map con copia

// Variante A — mutazione diretta dell'array
export function apriPrestito({ strumentoId }, archivio) {
  const strumenti = archivio.caricaTutti();
  const strumento = strumenti.find(s => s.id === strumentoId);
  strumento.stato = "in-prestito"; // mutazione
  archivio.salva(strumenti);
}

// Variante B — map con copia
export function apriPrestito({ strumentoId }, archivio) {
  const strumenti = archivio.caricaTutti();
  const aggiornati = strumenti.map(s =>
    s.id === strumentoId ? { ...s, stato: "in-prestito" } : s
  );
  archivio.salva(aggiornati);
}

Valutazione:

  • Leggibilità: A è più diretto. B è più verboso ma rende esplicito che non si modifica l’originale.
  • Testabilità: B è più prevedibile — non c’è rischio di effetti collaterali sull’array originale.
  • Complessità aggiunta: B crea un nuovo array ad ogni operazione — costo minimo per un registro piccolo.
  • Scelta per il Registro: entrambe sono accettabili. Scegli A per semplicità se il progetto è piccolo, B se vuoi evitare bug sottili di mutazione.

Esempio JS — scheda di confronto documentata

/*
 * DECISIONE TECNICA — 2025-10-15
 * 
 * Problema: come aggiornare lo stato di uno strumento in apriPrestito
 * 
 * Variante A: mutazione diretta (find + strumento.stato = ...)
 * Variante B: map con copia ({ ...s, stato: ... })
 * 
 * Leggibilità: A più diretto, B più esplicito
 * Testabilità: equivalente — entrambe verificabili senza browser
 * Complessità: A minore (meno codice)
 * 
 * Scelta: A — il progetto è piccolo, la mutazione è localizzata e controllata.
 * Se il progetto crescesse con operazioni concorrenti, passeremmo a B.
 */

Prova di comprensione

Rispondi per iscritto:

  • Qual è la differenza tra scegliere per “eleganza” e scegliere per “leggibilità”?
  • Se un compagno ti dice “Map è sempre meglio di array per la ricerca per ID”, come risponderesti?
  • Perché la coerenza con il resto del progetto è un criterio valido nella scelta tecnica?
  • Hai trovato nel tuo Registro un punto dove le due varianti producevano codice di qualità molto diversa? Quale?

Errori da evitare

  • scegliere la variante “più moderna” senza verificare che sia più leggibile o testabile;
  • mescolare due approcci diversi nello stesso progetto per lo stesso problema;
  • non documentare la scelta — chi legge il codice in futuro non sa perché hai scelto così;
  • ottimizzare per un caso d’uso che non esiste ancora nel progetto.

Prodotto da consegnare

Una scheda di confronto compilata per almeno due coppie di varianti, con la decisione motivata. Come verifica: mostra la scheda al docente e spiega verbalmente i criteri usati.

Checklist di chiusura

  • ho confrontato almeno due coppie di varianti su criteri espliciti;
  • ogni scelta ha una motivazione in una frase che fa riferimento al contesto del Registro;
  • non ho usato “si fa così” o “è più elegante” come motivazione;
  • le scelte sono coerenti tra loro nel progetto;
  • ho documentato le decisioni nel codice o nel README.

Risultato atteso

Ho confrontato due coppie di varianti nel Registro.
Coppia 1: [descrizione] — ho scelto [variante] perché [criterio concreto].
Coppia 2: [descrizione] — ho scelto [variante] perché [criterio concreto].
Le scelte sono documentate nel codice con un commento di decisione.