Lavorare con l'AI sul codice

Lavorare con l'AI sul codice

In questo corso l'AI si usa, ma in momenti precisi e con regole precise. L'obiettivo non è evitarla: è imparare a darle istruzioni chiare e a controllare quello che produce, come fareste con un collega veloce ma distratto.

Le regole del corso

Momento AI Perché
Fase "senza pattern" di ogni ticket No Il punto è sentire il problema e provarci con quello che sapete. Se lo risolve l'AI, la fatica non è vostra e il confronto non serve a niente
Fase AI di ogni ticket, dopo la teoria Sì, con lo strumento della coppia Chiedete all'assistente di rifattorizzare la vostra soluzione verso il pattern, poi rileggete il diff. Nel confronto dite cosa avete chiesto
Caccia agli smell del primo giorno Solo nella seconda parte Prima cercate voi, poi vedete cosa trova l'AI e cosa si inventa
Esame No È uno scritto, in aula

Strumenti diversi danno risultati diversi, ed è un vantaggio: nel confronto vedremo come lo stesso problema viene risolto da assistenti diversi.

Il contesto del progetto

Un assistente lavora bene solo se conosce il progetto. TicketHub contiene tre file pensati per questo:

  • AGENTS.md descrive il progetto, il glossario, i comandi e le regole di lavoro. Lo leggono da soli Copilot, Cursor e Codex.
  • CLAUDE.md importa AGENTS.md e aggiunge le istruzioni per Claude Code.
  • docs/contesto-ai.md contiene un blocco da incollare all'inizio della conversazione, se usate una chat nel browser che non legge i file del progetto.

Le regole principali di AGENTS.md:

  • si lavora in TDD: prima un test che fallisce, poi il codice minimo, poi il refactoring con i test verdi;
  • la cartella vendor/ contiene gli SDK dei fornitori e non si modifica;
  • lo scope è il ticket: i problemi trovati fuori scope vanno in DEBITO.md, non si correggono;
  • niente astrazioni che il ticket non richiede;
  • niente dipendenze npm nuove senza chiedere;
  • i test esistenti non si modificano per farli passare;
  • prima di dire "fatto" devono passare npm test, npm run test:e2e, npm run typecheck, npm run lint e npm run build.

Come scrivere la richiesta

Una richiesta buona ha quattro parti:

  1. Contesto. Quale ticket, quali file. Incollate il testo del ticket e i file che contano, o indicateli se l'assistente legge il progetto.
  2. Obiettivo. Cosa deve fare, detto con le parole giuste. Qui il nome del pattern visto in teoria fa la differenza.
  3. Vincoli. Cosa non deve toccare, quali test devono restare verdi, quali regole del progetto valgono.
  4. Forma della risposta. File completi o diff, e una spiegazione breve delle scelte.

Un modello da adattare per la fase AI di un ticket:

Sto lavorando al ticket in tickets/T0N.md di TicketHub. La nostra soluzione è nel ramo
corrente: i file che contano sono <elenco dei file>.

Rifattorizza la soluzione applicando <il pattern visto in teoria>, in modo che <il cambiamento
che deve diventare facile, per esempio la variazione del ticket>.

Vincoli:
- rispetta le regole di AGENTS.md;
- non modificare vendor/ e non toccare file fuori da quelli elencati;
- i test esistenti non si cambiano e devono restare verdi;
- niente astrazioni che il ticket non richiede.

Mostrami il diff completo e spiegami in poche righe quali classi hai creato e perché.

Come rileggere il codice generato

Il codice dell'assistente va letto come quello di un collega prima di accettarlo. Questa checklist vale per ogni diff:

  • Lo scope è quello del ticket. Non ci sono file toccati senza motivo, rinomine o "miglioramenti" non richiesti.
  • I test esistenti sono intatti. Se un test è cambiato, c'è un motivo scritto nel ticket.
  • Non ci sono astrazioni inutili. Ogni interfaccia, classe base o factory nuova ha almeno un motivo concreto nel problema di oggi.
  • vendor/ è intatta.
  • I nomi dicono cosa fanno le cose.
  • Il codice compila e i test passano davvero. Lanciateli voi, non fidatevi della frase "ho verificato che funziona".
  • La spiegazione corrisponde al codice. Se l'assistente dice di aver fatto una cosa, controllate che nel diff ci sia.

Gli errori tipici

  • Inventare. API, opzioni di configurazione, metodi di librerie che non esistono, scritti con grande sicurezza.
  • Risolvere un altro problema. Il codice è giusto, ma risponde a una domanda diversa da quella che avete fatto.
  • Strati per il futuro. Interfacce, factory e classi astratte per casi che nessuno ha chiesto.
  • Cambiare il test invece del codice. Il test diventa più permissivo e passa, il bug resta.
  • Darvi ragione. Se insistete su un'idea sbagliata, spesso l'assistente la asseconda invece di dirvelo.
  • Codice plausibile che non gira. Sembra giusto, ha la forma giusta, e non compila o non passa i test.

Tutti questi errori hanno una cosa in comune: si vedono solo se si legge il codice e si lanciano i test.

Perché i pattern aiutano

Chi conosce un pattern sa chiederlo con precisione. "Rendilo più pulito" produce qualcosa a caso. "Avvolgi questa fonte dati con un oggetto che ha la stessa interfaccia e comprime i dati prima di scriverli" produce quasi sempre quello che serviva.

E chi conosce un pattern sa riconoscere quando l'assistente lo applica male: un "Decorator" che non ha la stessa interfaccia dell'oggetto che avvolge, una "Factory" che crea un solo tipo e serve solo ad allungare il codice. Il vocabolario dei pattern accorcia le richieste e accorcia le revisioni.

Riferimenti