modulo 07 / lezione 44

Leggere e verificare codice generato

Dipendenze inutili, librerie inventate, API che non esistono

Verificare che il codice generato si basi su strumenti reali, installati e necessari.

75 min Vibe Coding

Dipendenze inutili, librerie inventate, API che non esistono

Tre errori distinti del codice generato dall’AI: aggiunge dipendenze non necessarie, inventa librerie/funzioni/opzioni che non esistono, mescola API di versioni diverse. Tutti tre producono codice plausibile a vista e non funzionante (o pericoloso) in esecuzione. Verificare è obbligatorio, non opzionale.

Perché questa lezione conta

Modelli AI sono ottimi pattern matcher. Hanno visto migliaia di esempi di “regex per email”, “fetch con axios”, “validazione con joi”. Quando devono produrre codice nuovo, riempiono con pattern simili. Spesso il pattern è giusto. Spesso usa una versione obsoleta, una libreria che hai sostituito, un metodo che il modello pensa esista perché era logico aspettarselo. Verifica = filtro.

Obiettivo operativo

Alla fine devi saper:

  1. controllare se import e funzioni esistono davvero in versione installata;
  2. distinguere dipendenza necessaria da decorativa;
  3. costruire una checklist di verifica prima del merge.

Nucleo della lezione

1. Cosa controllare

Quattro check sistematici per ogni codice generato:

Import esistente: ogni import X from 'pkg' → pkg è in package.json? Versione installata supporta l’import? Verifica:

  • aprire package.json, cercare il package;
  • aprire node_modules/pkg/package.json per leggere “main”/“exports”;
  • documentazione ufficiale del pkg per quella versione.

Modelli capita inventino package plausibili (@vercel/auth, @stripe/react-native-stripe-sdk) che non esistono o sono diversi.

Funzione esistente: pkg.someMethod() esiste in versione installata? Le firme corrispondono? Documentazione ufficiale, non blog post (che possono essere outdated).

Opzione esistente: someMethod({ foo: true, bar: ... }) — foo è un’opzione valida? Documentazione.

API obsoleta: il modello a volte usa API di anni fa. React class components, Express middleware vecchio, Webpack 4 config. Verifica versione del framework + che API usata sia per quella versione.

2. Riconoscere allucinazioni

Sintomi tipici di codice “inventato”:

  • Nome plausibile ma mai sentito: useDebounceCallback, formatDateLocale, validateBusinessHours. Non esistono? Verifica.
  • Opzione che “ha senso”: axios.post(url, data, { timeout: 5000, retry: 3 }). retry non è opzione standard di axios. Verifica.
  • Mix di versioni: import { Redirect } from 'react-router-dom' (v5) accanto a useNavigate (v6). Incompatibili. Verifica versione installata.
  • Esempio “perfetto” su libreria di nicchia: se la libreria ha 100 stelle GitHub, modello probabilmente non l’ha vista; output è interpolazione. Sospetto alto.
  • Codice che gira solo se aggiungi dipendenza X: il modello introduce X “perché aiuta” ma non era richiesta.

Pattern: più un metodo “sembra che dovrebbe esserci”, più rischio di allucinazione.

3. Quando aggiungere una dipendenza

Domande prima di accettare nuova lib:

  • Risolve un problema reale? Il task richiede capacità non banali (parsing complesso, crittografia, framework UI)? Se sì, lib può essere giustificata.
  • Sostituisce poche righe comprensibili? Se la libreria fa 5 righe di codice che potresti scrivere a mano, valuta: scriverlo evita debito di dipendenza. Esempi: clipper di stringa, generazione UUID semplice, debounce.
  • Manutenuta? Ultima release < 1 anno? Issue chiuse? Stelle non sono garanzia, ma trend di abbandono è warning.
  • Dimensione bundle? Per progetti web client, verifica con bundlephobia o pacchetto. Una lib da 200KB per usare 1 funzione = NO.
  • Trasitive insane? npm ls per vedere quante dipendenze tira. Centinaia per una libreria piccola = bandiera.
  • Compatibilità licenza? GPL, AGPL possono essere problematici per progetti commerciali. MIT/Apache/ISC sono ok per la maggior parte dei casi.
  • Sicurezza? npm audit non è infallibile ma offre un primo segnale.

Default: NO nuove dipendenze. Sì solo se le domande sopra hanno risposta positiva.

Caso guidato

Diff AI:

+ import { createMagicTable } from "react-smart-table-pro";

Il modello dice: “Ho aggiunto una tabella avanzata con sorting e filtri”. Prima di accettare:

  1. La libreria esiste? Cerca nel registry o nella documentazione ufficiale. Nome plausibile non significa reale.
  2. È installata? Controlla package.json e lockfile.
  3. L’API usata esiste nella versione installata? Molti errori nascono da esempi di versioni diverse.
  4. Serve davvero? Se la tabella ha 20 righe e due colonne, sorting manuale è più comprensibile.
  5. Che costo porta? Bundle, CSS globale, accessibilità, manutenzione, licenza.

Decisione possibile:

Rifiuto nuova dipendenza.
Motivo: sorting e filtro testuale sono implementabili con `Array.sort` e `filter`.
Richiesta alternativa: mantenere componente esistente, aggiungere funzioni pure `sortRows` e `filterRows`, con test unitari. Nessun cambio a package.json.

Prompt di correzione:

Rimuovi la dipendenza proposta. Implementa sorting e filtro senza librerie esterne. Mantieni il diff entro il componente tabella e un file di test. Spiega eventuali limiti.

Il criterio non è “mai dipendenze”. Il criterio è: ogni dipendenza deve comprare più valore di quanto costa in rischio.

Procedura pratica

Per ogni PR/commit con codice generato:

  1. Leggi diff di package.json/package-lock: nuove dipendenze? quali?
  2. Per ognuna: verifica che sia necessaria (le 7 domande sezione 3).
  3. Per ogni import nei file modificati: pkg esiste? versione corrisponde?
  4. Per ogni funzione/opzione “che non avevo mai sentito”: documentazione ufficiale, conferma esistenza.
  5. Per codice che usa pattern “datato”: verifica versione installata.
  6. Esegui: npm test, npm run build. Se gira, è almeno sintatticamente vero. Se non gira, indagare.

Laboratorio guidato

Esempio diff sospetto:

import { useDebounce, useToast } from 'react-hooks-utils'
import axios from 'axios'

async function searchUsers(query: string) {
  const debouncedQuery = useDebounce(query, 300)
  const { showToast } = useToast()
  
  const response = await axios.get('/api/users', {
    params: { q: debouncedQuery },
    timeout: 5000,
    retry: 3,
    cache: true,
  })
  
  if (response.error) {
    showToast({ type: 'error', message: response.error.message })
    return []
  }
  return response.data
}

Verifiche:

  1. react-hooks-utils: esiste? È una libreria reale? Cerca su npm. → Probabilmente non esiste. Cerca alternative reali (use-debounce, react-hot-toast).
  2. useDebounce in funzione async non React → uso scorretto di hook (regola degli hook).
  3. axios.get con retry e cache: non sono opzioni standard di axios. Sono inventate.
  4. response.error: axios usa try/catch con error.response, non response.error. Pattern di fetch nativo confuso con axios.

Risultato: codice plausibile, completamente non funzionante. Refactor necessario, basato su API reali.

Output atteso

Una checklist personale “verifica dipendenze pre-merge”:

□ Diff di package.json controllato
□ Ogni nuova dipendenza giustificata (le 7 domande)
□ Ogni import esiste in versione installata
□ Ogni funzione/opzione confermata da doc ufficiale
□ Test passa
□ Build pulita
□ Bundle size accettabile (per client)
□ License compatibile

Studio passo passo

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

  1. Prima lettura: chiarisci l’obiettivo: verificare che il codice generato si basi su strumenti reali, installati e necessari. Se non riesci a riscriverlo in una frase tua, rileggi il nucleo della lezione.
  2. Seconda lettura: trasforma i contenuti in domande operative:
  • Controllare package manager, import, documentazione ufficiale, versioni, API disponibili e dimensione del pacchetto.
  • Riconoscere hallucinations: metodi plausibili ma inesistenti, opzioni non supportate, esempi presi da versioni diverse.
  • Valutare se una dipendenza risolve un problema reale o sostituisce poche righe comprensibili.
  1. Applicazione: svolgi il laboratorio: analizzare un diff con una nuova libreria e decidere se accettarla, sostituirla o chiedere una soluzione senza dipendenze. L’output da ottenere è: una checklist per validare import, librerie e chiamate API prima del merge.

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 preso almeno una volta un caso di “libreria inventata” e l’ho riconosciuto;
  • ho un default “NO nuove dipendenze” senza approvazione;
  • verifico documentazione ufficiale per opzioni che non ho mai usato;
  • conosco bundle size delle dipendenze frontend del mio progetto.

Errori comuni

Accettare nuove dipendenze “perché in PR”. PR non significa giustificate. Verifica.

Fidarsi di esempi blog/StackOverflow. Possono essere outdated o riferiti a versioni diverse. Documentazione ufficiale è autorità.

Non leggere package.json. Non vedi cose installate. Modello propone roba che si scontra.

Mix di versioni. Codice di un mix di tutorial vecchi/nuovi. Apparentemente sensato, eseguito spacca.

Dipendenze per task piccoli. lodash.debounce per usare debounce in un file. Scrivi 5 righe.

Niente lockfile. Build non riproducibile. Stesso codice, comportamento diverso fra macchine.

Audit ignorato. npm audit mostra vulnerabilità, le ignori. Segnali deboli sono comunque segnali.

Prompt di lavoro

Rivedi questo diff con focus su dipendenze e API.

[INCOLLA DIFF]

Contesto:
- stack: [...]
- versioni installate principali: [...]
- package.json prima del diff: [contenuto rilevante]

Verifiche richieste:

1. Per ogni nuovo import (incluso da pkg già presente): è valido nella versione installata?
2. Per ogni nuova dipendenza in package.json: è giustificata? Alternative più leggere o senza dipendenza?
3. Per ogni funzione chiamata di libreria esterna: esiste nella versione? Confermi opzioni?
4. Pattern "datato" (es. React class, callback al posto di async): è coerente con versioni installate?
5. Codice "plausibile ma sospetto": righe dove dovrei verificare doc ufficiale.

Output: lista numerata di problemi/dubbi, severità (blocking / sospetto / nit), suggerimento per ognuno.

NON proporre riscrittura. Voglio sapere cosa è solido e cosa è da verificare.

Esercizio finale

Apri il package.json del tuo progetto principale. Per ogni dipendenza top-level (non transitive), rispondi: la sto davvero usando? Quante volte è importata? Una dipendenza con 0 import nel codice di prodotto è da rimuovere. Spesso si scoprono 3-5 dipendenze morte. Pulizia in 10 minuti, bundle ridotto, complexity in meno.