modulo 07 / lezione 46

Leggere e verificare codice generato

Review del diff: leggere modifiche riga per riga

Trasformare la lettura del diff in una procedura pratica, così da non accettare codice solo perché l'app sembra funzionare.

75 minVibe Coding

Review del diff: leggere modifiche riga per riga

Un’app che “sembra funzionare” può avere appena introdotto una dipendenza inutile, cancellato una validazione, spostato una regola critica nel client o rotto un caso limite che non hai provato. Nel vibe coding il diff è il punto in cui l’entusiasmo deve diventare disciplina. Non stai giudicando la risposta dell’AI: stai giudicando ciò che ha cambiato nei file.

Perché questa lezione conta

Il modello può spiegare benissimo una modifica che in realtà non ha fatto, oppure può fare una modifica corretta insieme a tre modifiche laterali non richieste. La review del diff serve proprio a separare il racconto dal fatto. Ogni riga aggiunta, rimossa o spostata è una decisione tecnica: alcune sono innocue, altre cambiano comportamento, sicurezza, manutenzione o costo futuro.

Senza una procedura, la review diventa una scansione veloce: guardi i nomi dei file, leggi due punti familiari, lanci l’app e premi avanti. Con una procedura, invece, sai in che ordine guardare, cosa cercare e quando fermare il ciclo prima che il danno si accumuli.

Obiettivo operativo

Alla fine devi saper:

  1. leggere un diff generato dall’AI in un ordine prevedibile;
  2. distinguere modifiche di comportamento, di struttura, di configurazione e di rumore;
  3. annotare cosa accetti, cosa rifiuti e cosa deve essere verificato prima del commit.

Nucleo della lezione

1. Prima domanda: il diff corrisponde al task?

La prima review non è tecnica, è di confine. Chiediti: “questo diff fa solo ciò che avevo chiesto?”.

Esempio: hai chiesto “aggiungi validazione al form contatti”. Il diff modifica:

  • ContactForm.tsx
  • validateContact.ts
  • ContactForm.test.ts
  • package.json
  • tailwind.config.js
  • Header.tsx

I primi tre file sono plausibili. Gli ultimi tre sono sospetti. Forse servono, ma devono giustificarsi. Un cambio a package.json può essere corretto se aggiunge una libreria di validazione necessaria; può essere eccessivo se bastavano cinque righe di controllo. Un cambio a Header.tsx probabilmente è fuori scope.

Regola pratica: ogni file modificato deve avere una frase di giustificazione collegata al task. Se non riesci a scriverla, il file va controllato con attenzione o escluso.

2. Ordine di lettura consigliato

Non leggere il diff dall’alto al basso se l’ordine dei file è casuale. Usa questo ordine:

  1. File rimossi: una cancellazione è spesso più rischiosa di un’aggiunta. Controlla che non siano spariti test, validazioni, tipi o utility usate altrove.
  2. File di configurazione: package.json, lockfile, config build, env example, routing, middleware. Piccole modifiche qui possono cambiare tutta l’app.
  3. Dipendenze: ogni nuova libreria deve rispondere a “serve davvero?”, “è mantenuta?”, “è compatibile?”, “quanto pesa?”, “introduce rischio?”.
  4. Contratti condivisi: tipi, schema, API, interfacce, DTO. Se cambiano, cambia il modo in cui molte parti si parlano.
  5. Logica di dominio o backend: qui guardi regole, validazione, autorizzazione, trasformazioni, errori.
  6. UI e stato: componenti, form, loading, errori, accessibilità, eventi.
  7. Test: controlla che testino comportamento reale e non solo che il codice nuovo esista.
  8. Documentazione: verifica che README o commenti non promettano cose non vere.

Questo ordine mette prima le modifiche con più impatto sistemico. La UI può sembrare più visibile, ma spesso i bug peggiori stanno in config, tipi e confini.

3. Cosa cercare riga per riga

Durante la lettura segna ogni riga con una categoria mentale.

Comportamento reale: cambia ciò che l’utente o una API possono fare. Esempi: nuova condizione if, nuovo redirect, nuova query, nuovo messaggio di errore, nuovo stato.

Sicurezza: tocca auth, ruoli, token, cookie, validazione, sanitizzazione, query, upload, segreti. Ogni riga qui merita sospetto sano.

Persistenza: salva, cancella, migra o interpreta dati. Controlla compatibilità con dati vecchi e casi mancanti.

Struttura: sposta responsabilità tra moduli. Chiediti se il codice diventa più facile o più difficile da testare.

Rumore: formattazione massiva, rinomini non richiesti, riordino import, cambi stile. Il rumore aumenta il costo della review e spesso nasconde modifiche vere.

Speculazione: codice per scenari futuri non richiesti. “Già che c’ero ho predisposto…” è una frase pericolosa quando arriva da un agente.

4. Segnali rossi tipici nei diff AI

Questi pattern non significano automaticamente “rifiuta”, ma richiedono pausa.

  • Nuova dipendenza per un problema risolvibile con codice semplice.
  • Lockfile enorme per una modifica piccola.
  • Validazione spostata dal server al client.
  • try/catch che ingoia l’errore e mostra messaggio generico senza log utile.
  • Fallback permissivi: return true, return [], || "", as any.
  • Tipi allargati invece di corretti: unknown trasformato in any.
  • Test che verificano dettagli interni e non comportamento.
  • Cancellazione di casi limite “per semplificare”.
  • Commenti che spiegano intenzioni ma codice che non le implementa.
  • Refactor laterali dentro un bugfix.

Quando trovi uno di questi segnali, non continuare in automatico. Scrivi un commento di review e decidi se correggere subito, chiedere spiegazione o rifiutare il diff.

Procedura pratica

Per ogni diff generato:

  1. Leggi il task originale: una frase. Se non esiste, scrivila prima di revisionare.
  2. Conta i file modificati: chiediti se il numero è proporzionato.
  3. Classifica i file: config, dipendenze, contratti, logica, UI, test, docs.
  4. Leggi prima rimozioni e configurazioni.
  5. Leggi la logica cercando cambi di comportamento.
  6. Leggi test e verifica che coprano il comportamento nuovo.
  7. Annota tre esiti: accetto, correggo, blocco.
  8. Esegui verifiche mirate: comandi, test manuali, DevTools, log.
  9. Commit solo dopo review + verifica.

Il punto non è diventare lenti. Il punto è diventare regolari: stessa procedura, meno sorprese.

Laboratorio guidato

Task: “aggiungi validazione email lato server al form newsletter”.

Diff simulato:

+ import validator from "email-validator";

  export async function subscribe(input) {
-   await db.newsletter.insert({ email: input.email });
+   if (!input.email) return { ok: false, error: "Email richiesta" };
+   if (!validator.validate(input.email)) {
+     return { ok: false, error: "Email non valida" };
+   }
+   await db.newsletter.insert({ email: input.email.toLowerCase() });
+   return { ok: true };
  }

Prima lettura: sembra corretto. Seconda lettura:

  • nuova dipendenza per validare email: serve davvero o basta una validazione minima?
  • input non è tipizzato: cosa succede se input è null?
  • toLowerCase() normalizza, bene, ma manca trim();
  • non controlla duplicati;
  • non c’è try/catch o gestione errore DB;
  • non c’è test.

Commento di review:

La validazione lato server va nella direzione giusta, ma il diff non è ancora accettabile:
1. evita nuova dipendenza per una validazione minima o motiva perché serve;
2. tipizza input e gestisci input nullo/non oggetto;
3. normalizza con trim + lowercase prima di validare;
4. aggiungi test per vuoto, malformato, maiuscole/spazi, duplicato;
5. verifica comportamento in caso errore DB.

Questa è review utile: non dice “non mi piace”, indica rischi e prossimi passi verificabili.

Output atteso

Una checklist personale di review del diff, usata prima di accettare modifiche AI. Deve stare in un file breve, ad esempio docs/ai-diff-review.md, e contenere:

  • ordine di lettura;
  • segnali rossi;
  • domande per sicurezza/dati/test;
  • criterio per accettare o rifiutare.

Studio passo passo

Studia questa lezione in tre passaggi, senza correre subito al prompt o al codice.

  1. Prima lettura: chiarisci l’obiettivo: trasformare la lettura del diff in una procedura pratica, così da non accettare codice solo perché l’app sembra funzionare. Se non riesci a riscriverlo in una frase tua, rileggi il nucleo della lezione.
  2. Seconda lettura: trasforma i contenuti in domande operative:
  • Ordine di lettura: file aggiunti, file rimossi, dipendenze, configurazione, logica, test e documentazione.
  • Segnali di rischio nel diff: modifiche fuori scope, cancellazioni silenziose, fallback troppo permissivi, formattazioni massive.
  • Annotare decisioni: cosa accetto, cosa chiedo di cambiare, cosa verifico manualmente e cosa blocca il merge.
  1. Applicazione: svolgi il laboratorio: revisionare un diff simulato con errori nascosti e produrre una lista di commenti tecnici ordinati per priorità. L’output da ottenere è: una checklist di code review per diff generati dall’AI, pronta da usare prima di ogni commit.

Prima di passare alla lezione successiva, controlla di avere un artefatto concreto: una tabella, un prompt, una checklist, un mini report, un diff commentato o una decisione scritta. Nel vibe coding la comprensione resta astratta finché non produce una traccia verificabile.

Checklist di verifica

  • so spiegare perché il diff vale più della risposta dell’AI;
  • controllo file rimossi, configurazione e dipendenze prima della UI;
  • riconosco almeno cinque segnali rossi tipici dei diff generati;
  • non accetto lockfile, config o auth modificati senza capirli;
  • lascio commenti di review specifici, non impressioni generiche;
  • committo solo dopo review e verifica.

Errori comuni

Leggere solo i file familiari. Il bug spesso vive nel file che non volevi aprire: config, middleware, schema, lockfile.

Fidarsi dei test generati. Un test può passare perché assertisce poco. Leggi il test come leggi il codice.

Ignorare le rimozioni. Una riga cancellata può togliere una protezione costruita settimane prima.

Accettare formattazioni massive. Se il modello riformatta tutto, chiedi diff più piccolo. La review deve restare leggibile.

Commentare in modo vago. “Da migliorare” non guida nessuno. “La validazione vive solo nel client: spostarla nel server e aggiungere test su richiesta diretta API” è utile.

Prompt di lavoro

Fai review di questo diff come revisore severo ma pratico.

Task originale:
[descrizione]

Diff:
[incolla diff o riassunto file modificati]

Voglio:
1. file fuori scope o sospetti;
2. rischi di sicurezza/dati;
3. problemi di test;
4. complessità inutile;
5. decisione: accetta / correggi / rifiuta;
6. massimo 8 commenti, ordinati per priorità.

Non riscrivere codice finché non lo chiedo.

Esercizio finale

Prendi l’ultimo diff generato da AI nel tuo progetto. Non eseguirlo subito. Prima costruisci una tabella con tre colonne: file, motivo della modifica, rischio. Poi leggi il diff seguendo l’ordine della lezione. Alla fine scrivi una decisione di review in 5 righe: cosa accetti, cosa correggi, cosa verifichi. Se non riesci a giustificare un file, quello è il punto da investigare prima del commit.