modulo 07 / lezione 47

Leggere e verificare codice generato

Quando rifiutare il codice e ripartire dal prompt

Capire quando correggere localmente e quando il risultato è così fuori strada da richiedere una nuova richiesta.

75 min Vibe Coding

Quando rifiutare il codice e ripartire dal prompt

A volte il codice generato si corregge in 5 minuti. A volte è così sbagliato che correggerlo richiede più tempo che rigenerare. Distinguere i due casi è scelta strategica. Continuare a patchare codice errato a livello di struttura è come dipingere una casa che ha le fondamenta storte.

Perché questa lezione conta

Persistenza è virtù in molte cose, non in revisione di codice generato. Quando un output ha problemi strutturali, correggerlo riga per riga porta a Frankenstein: tracce delle scelte sbagliate originarie + tue patch sopra. Risultato peggiore di rigenerare con prompt più chiaro. Sapere quando rifiutare salva tempo e qualità.

Obiettivo operativo

Alla fine devi saper:

  1. distinguere problemi locali (correggibili) da strutturali (rigenerare);
  2. valutare costo di riparazione vs rigenerazione;
  3. scrivere prompt di ripartenza che non ripete lo stesso errore.

Nucleo della lezione

1. Criteri per rifiutare

Cinque casi in cui rifiuto è preferibile a fix:

Requisito centrale ignorato: il codice non fa la cosa che hai chiesto. Non un dettaglio, il punto. Esempio: chiedi paginazione, ricevi solo lista. Patch = riscrivere tutto.

Architettura sbagliata: il codice mette logica nel posto sbagliato (validazione client invece di server, regole nel componente invece di backend, stato derivato salvato come indipendente). Patch toccherebbe ovunque; meglio rigenerare con vincoli architetturali espliciti.

Sicurezza compromessa: SQL injection, XSS, segreti hardcoded, autorizzazione assente. Rischio è che fix locale sia incompleto. Rigenerazione con sicurezza esplicita nel prompt.

Complessità inutile: 200 righe per quello che ne richiede 30. Astrazioni non necessarie, wrapper, pattern enterprise per script. Patch lasciare residui. Rigenerare semplificando.

Scope drasticamente espanso: chiedo X, ricevo X+Y+Z+W. Tutto modificato, refactor laterali ovunque. Patch impossibile, reset.

Combinazione di 2+ → quasi sempre rifiuto.

2. Costo riparazione vs rigenerazione

Equazione mentale rapida:

Costo riparazione:

  • Tempo per leggere e capire codice esistente (può essere alto).
  • Tempo per identificare cosa va, cosa no.
  • Tempo per applicare modifiche evitando di rompere ciò che va.
  • Rischio: residui invisibili che emergono dopo.

Costo rigenerazione:

  • Tempo per scrivere prompt migliore (più vincoli, più chiarezza).
  • Tempo per generare di nuovo.
  • Tempo per verificare nuovo output.
  • Beneficio: codice “tuo” da inizio (non eredita scelte sbagliate).

Soglia: se la riparazione richiede più di 30% del tempo di rigenerazione, rigenera.

Eccezione: se ti serve imparare dal codice esistente (capirne pezzi specifici), riparare ha valore didattico anche se più lento.

3. Prompt di ripartenza

Errore frequente: rigenerare con stesso prompt. Ottieni stesso risultato. Il prompt deve includere ciò che hai imparato dal primo tentativo.

Struttura del prompt di ripartenza:

Ho rifiutato il tentativo precedente. Ecco perché:

[1-3 problemi specifici del primo tentativo]

Ecco cosa NON voglio:
- [pattern del primo tentativo da evitare]
- [librerie scelte e da evitare]
- [scope da non superare]

Ecco cosa è ok mantenere (se nulla, salta):
- [pezzi del primo tentativo che andavano bene]

Vincoli aggiuntivi rispetto al prompt originale:
- [vincoli emersi dopo aver visto cosa è andato male]

Ora ricomincia da zero seguendo i vincoli.

Senza questa struttura, il modello replica gli stessi pattern. Con questa struttura, evita esplicitamente quelli sbagliati.

Matrice decisionale

Usa questa matrice quando sei indeciso:

SegnaleCorreggi localmenteRigenera
Bug isolato in 1 funzionesìno
Requisito centrale ignoratonosì
Nomi brutti ma struttura correttasìno
Auth o permessi assentiraramentespesso
Dipendenza inutile aggiuntasì, se semplice rimozionesì, se ha contaminato architettura
8+ file modificati per task piccolonosì
Test mancanti ma codice chiarosìno
Modello dati sbagliatoraramentesì

Esempio: chiedi “aggiungi filtro per stato” e ricevi anche refactor globale del layout. Anche se il filtro funziona, il diff ha contaminazione. La scelta matura è rifiutare o chiedere una patch nuova limitata:

Rifiuto il diff perché modifica layout e componenti non richiesti. Riparti dal codice attuale e implementa solo il filtro per stato in `TaskFilters` e nella funzione `filterTasks`. Nessuna modifica CSS globale, nessuna rinomina, nessuna nuova dipendenza.

Al contrario, se il modello implementa il filtro nel file giusto ma dimentica il caso “tutti”, correggi localmente o chiedi patch minima. Non serve rigenerare tutto.

La decisione non è emotiva. È una stima di contaminazione: quanto del diff sbagliato entrerebbe nella base se lo accetti?

Procedura pratica

Dopo generazione che non torna:

  1. Pausa: non rispondere “fai meglio”.
  2. Diagnosi: i 5 criteri di rifiuto si applicano? Quanti?
  3. Calcolo costo: tempo riparazione stimato vs rigenerazione.
  4. Decisione: ripara o rigenera.
  5. Se rigenera: riparti da un checkpoint pulito (commit, branch o copia controllata), poi scrivi prompt di ripartenza. Usa comandi distruttivi solo se sai esattamente cosa stai eliminando.
  6. Se ripara: identifica le 2-3 modifiche necessarie, applicale localmente.
  7. Verifica esito del nuovo round.

Laboratorio guidato

Caso tipo: hai chiesto “implementa autenticazione semplice”. Output:

- Aggiunge libreria `passport` + 5 strategie + JWT + refresh token + sessione cookie + 2FA stub.
- Crea 12 file in `src/auth/`.
- Modifica `app.ts` con configurazione di tutto.
- Aggiunge `tsconfig` paths nuovi.
- Migrazione DB con tabella `users`, `sessions`, `tokens`, `auth_logs`.
- Test E2E che richiedono setup Docker.

Diagnosi:

  • Requisito ignorato: chiedevo “semplice”, ricevuto “enterprise”.
  • Architettura: complessa per scope.
  • Scope: drasticamente espanso (2FA, refresh, audit log non chiesti).
  • Complessità inutile: 5 strategie per 1 caso d’uso.

→ Quattro criteri di rifiuto. Decisione: rigenera.

Costo:

  • Riparazione: rimuovere 60% del codice, rivedere 10 file. ~3 ore.
  • Rigenerazione: prompt migliore, output mirato. ~1 ora.

Prompt di ripartenza:

Ho rifiutato il tentativo precedente. Problemi:
- 12 file per "auth semplice" è eccessivo
- libreria passport overkill, voglio implementazione esplicita
- 2FA, refresh token, audit log NON erano richiesti
- migrazione DB con 4 tabelle: troppe

NON voglio:
- libreria passport
- 2FA, refresh token, audit log (non richiesti)
- più di una tabella DB nuova
- più di 3 file modificati
- modifica a tsconfig

Voglio "auth semplice":
- email/password
- una tabella `users` (id, email, password_hash, created_at)
- 2 endpoint: POST /auth/signup, POST /auth/login
- sessione via cookie HttpOnly Secure
- bcrypt per hash
- max 3 file: handler, schema, client utility

Vincoli:
- TypeScript strict
- max 200 righe totali

Comincia con piano in 5 punti, aspetta OK.

Risultato: tipicamente prompt di ripartenza produce esito molto più aderente al primo tentativo, perché vincoli sono espliciti.

Output atteso

Un template “prompt di ripartenza” personale, riusabile. Salvato in snippet o note.

Studio passo passo

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

  1. Prima lettura: chiarisci l’obiettivo: capire quando correggere localmente e quando il risultato è così fuori strada da richiedere una nuova richiesta. Se non riesci a riscriverlo in una frase tua, rileggi il nucleo della lezione.
  2. Seconda lettura: trasforma i contenuti in domande operative:
  • Criteri di rifiuto: requisito centrale ignorato, architettura sbagliata, sicurezza compromessa, complessità inutile.
  • Costo della riparazione rispetto al costo della rigenerazione con specifica migliore.
  • Come scrivere un prompt di ripartenza: cosa non andava, cosa mantenere, cosa evitare, nuovo scope.
  1. Applicazione: svolgi il laboratorio: valutare tre output AI e decidere per ciascuno se accettare, correggere o rigenerare. L’output da ottenere è: una matrice decisionale accetta/modifica/rifiuta con motivazioni tecniche.

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

  • ho rifiutato almeno una volta codice generato (non solo chiesto modifiche locali);
  • so distinguere problemi locali da strutturali;
  • so tornare a un checkpoint pulito senza perdere lavoro utile o modifiche non collegate;
  • i miei prompt di ripartenza non sono semplicemente “fai meglio”.

Errori comuni

Patchare problemi strutturali. Codice diventa Frankenstein. Lavoro doppio.

Persistere su brutto inizio. Sunk cost: hai già investito tempo, vuoi salvare. Spesso meglio buttare.

Rigenerare senza prompt migliore. Stesso prompt = stesso risultato.

Non capitalizzare cosa è andato bene. Anche output cattivo può avere parti decenti. Riusa quelle.

Rifiutare per perfezionismo. Codice 80% giusto è ok. Rifiuto per il 100% è perfezionismo.

Dimenticare contesto. Prompt di ripartenza in nuova sessione: serve ricordare contesto del progetto, non solo problemi del primo tentativo.

Prompt di lavoro

Ho rifiutato il tentativo precedente di implementare: [task originale]

Problemi specifici trovati (1-3):
1. [...]
2. [...]
3. [...]

NON voglio (basandomi su cosa è andato male):
- [pattern/libreria/scope da evitare]

Ok mantenere (se applicabile):
- [parti decenti del primo tentativo]

Vincoli aggiuntivi (emersi dal primo tentativo):
- [vincoli rigidi]

Specifica originale (rimanata valida):
- [...]

Procedura:
1. Conferma di aver capito vincoli (parafrasa).
2. Piano in 3-5 punti.
3. Aspetta OK.
4. Implementa.

NON ricominciare con stesso pattern del primo tentativo.

Esercizio finale

Riguarda 3 generazioni AI degli ultimi mesi che hai pesantemente patchato. Per ognuna chiediti: quanto avrei risparmiato rigenerando con un prompt migliore? In 1-2 casi su 3, la risposta è “molto”. Quel pattern personale (riparazione automatica vs valutazione strategica) è esattamente la decisione che la lezione ti chiede di affinare.