Gli assistenti AI per lo sviluppo software, come Codex e Claude, possono ridurre in modo impressionante il tempo necessario per analizzare una codebase, proporre un refactoring, generare test o implementare una funzionalità. Ma proprio questa velocità introduce un rischio: confondere la capacità di produrre codice rapidamente con la capacità di prendere decisioni tecniche corrette per un progetto reale.
Nel mio lavoro cerco di evitare il flusso più immediato: requisito → prompt → codice. Prima di chiedere a un assistente di modificare il progetto, gli chiedo di analizzare il problema e formulare una proposta. Solo dopo una fase di confronto e refinement passo all'implementazione.
Il principio che cerco di mantenere
L'AI può comprimere enormemente il tempo di esecuzione, ma analisi, scelte tecniche e responsabilità del risultato devono restare sotto il controllo dello sviluppatore.
Il problema non è quanto velocemente l'AI scrive codice
Un coding assistant può produrre in pochi minuti modifiche che richiederebbero ore o giorni di lavoro manuale. È un vantaggio reale e sarebbe un errore ignorarlo.
Il punto è capire che cosa stiamo misurando. Se misuriamo soltanto il tempo necessario a generare una patch, l'approccio più veloce è quasi sempre chiedere direttamente all'AI di implementare la soluzione. Se invece misuriamo il tempo necessario a ottenere una modifica corretta, coerente con l'architettura, comprensibile dal team e sufficientemente sicura da arrivare in produzione, il quadro cambia.
In un progetto aziendale esistono vincoli che spesso non sono completamente descritti nel codice: convenzioni interne, scelte architetturali, compatibilità con sistemi legacy, requisiti operativi, modalità di deployment, aspettative del cliente e decisioni che derivano dalla storia del prodotto.
Un modello può individuare molti di questi elementi, ma non può sapere automaticamente quali siano negoziabili e quali invece rappresentino una precisa scelta aziendale.
Prima del codice: chiedere una proposta tecnica
Quando affronto una modifica non parto normalmente con un prompt del tipo "implementa questa funzionalità". Preferisco separare l'analisi dall'esecuzione.
Una richiesta iniziale può essere più simile a questa:
Analizza il requisito e il codice esistente.
Non modificare ancora nessun file.
Individua:
- componenti coinvolti;
- dipendenze;
- possibili regressioni;
- vincoli tecnici;
- alternative di implementazione;
- approccio che consiglieresti e relativi trade-off.Questa prima risposta non viene trattata come una specifica da accettare automaticamente. È una proposta da discutere.
Se l'assistente introduce una dipendenza che il progetto non vuole adottare, propone un pattern non coerente con il resto della solution o assume che sia possibile modificare una parte legacy che deve rimanere compatibile, aggiungo il vincolo e chiedo di rivalutare la soluzione.
Il brainstorming con l'AI è parte del lavoro, non un passaggio inutile
La fase che precede la scrittura del codice è una forma di brainstorming tecnico. L'assistente può diventare uno sparring partner con cui mettere alla prova un'idea prima di trasformarla in una modifica concreta.
In questa fase può essere utile chiedere:
- quali alternative esistono;
- quali failure mode non sono stati considerati;
- quali parti del codice esistente potrebbero essere impattate;
- se la soluzione aumenta l'accoppiamento;
- se esiste un approccio più incrementale;
- quali test servirebbero per verificare il comportamento;
- quali assunzioni sta facendo l'assistente.
Il risultato finale dell'analisi deve essere compatibile non soltanto con il requisito, ma anche con la filosofia tecnica dell'azienda o del cliente e con il modo in cui il progetto viene mantenuto.
Una domanda particolarmente utile
Quali assunzioni stai facendo che non puoi verificare direttamente dal codice che hai analizzato?
Refinement: restringere progressivamente il perimetro
Una buona proposta iniziale raramente è già quella definitiva. Possono emergere vincoli aggiuntivi oppure può essere necessario ridurre l'impatto della modifica.
Per esempio, dopo una prima analisi posso aggiungere indicazioni come:
Rivaluta la proposta considerando questi vincoli:
- non introdurre nuove dipendenze esterne;
- mantenere compatibilità con SQL Server legacy;
- non modificare il contratto pubblico dell'API;
- preferire una modifica incrementale;
- riutilizzare i pattern già presenti nella solution;
- mantenere semplice il rollback.Solo quando l'approccio è sufficientemente chiaro autorizzo la fase di implementazione.
Questo passaggio cambia il ruolo dell'assistente: non gli sto più chiedendo di decidere liberamente come risolvere il problema, ma di implementare una soluzione i cui confini sono stati prima discussi.
Un workflow in quattro fasi
| Fase | Obiettivo | Responsabilità principale |
|---|---|---|
| 1. Analisi | Comprendere requisito, codebase, dipendenze e rischi | AI + sviluppatore |
| 2. Brainstorming e refinement | Confrontare alternative e adattare la soluzione ai vincoli reali | Sviluppatore |
| 3. Implementazione | Applicare la soluzione concordata in modo circoscritto | AI sotto supervisione |
| 4. Revisione e test | Verificare codice, comportamento, regressioni e qualità | Sviluppatore |
Il flusso non è quindi prompt → codice, ma analisi → confronto → implementazione → verifica.
La generazione del codice arriva dopo una decisione tecnica
Quando la fase di analisi è conclusa, l'AI può esprimere al meglio il vantaggio di velocità. Può modificare più file coerentemente, generare boilerplate, aggiornare test, propagare una modifica ripetitiva o implementare un refactoring con una rapidità difficilmente raggiungibile manualmente.
Anche in questa fase preferisco mantenere il lavoro suddiviso in blocchi comprensibili. Una modifica molto ampia rende più difficile capire dove sia stato introdotto un comportamento inatteso e rende la code review più costosa.
Quando possibile chiedo quindi modifiche piccole e verificabili, mantenendo il diff leggibile e il rollback semplice.
Git rimane una delle reti di sicurezza più importanti
Usare un coding assistant non cambia le buone pratiche di versionamento. Anzi, le rende ancora più importanti.
Branch dedicati, commit coerenti e diff controllabili permettono di distinguere chiaramente il codice iniziale da quello generato o modificato durante la sessione.
Prima di accettare un intervento voglio poter rispondere a tre domande:
- quali file sono cambiati?
- perché ogni modifica è necessaria?
- posso annullare l'intervento senza dover ricostruire manualmente lo stato precedente?
Dopo il codice: la revisione non può essere delegata
La seconda fase in cui scelgo deliberatamente di rallentare è quella successiva alla generazione.
Leggo il diff, verifico che l'implementazione corrisponda all'analisi approvata e controllo che non siano state introdotte modifiche collaterali. Compilazione e test automatici sono importanti, ma non sostituiscono una revisione tecnica.
Controllo in particolare:
- coerenza con i pattern già usati nel progetto;
- gestione degli errori e dei casi limite;
- compatibilità con framework e infrastruttura esistenti;
- sicurezza e trattamento dei dati;
- performance e numero di accessi a database o servizi esterni;
- leggibilità e manutenibilità del codice;
- possibili regressioni su comportamenti non direttamente collegati al requisito.
Una regola semplice è questa: se non sapessi spiegare una modifica durante una code review, non dovrei portarla in produzione soltanto perché i test passano.
L'AI può scrivere i test, ma non dovrebbe essere l'unico giudice di se stessa
Gli assistenti sono molto utili per generare unit test, individuare edge case e costruire velocemente una prima suite di verifica. Tuttavia, quando lo stesso modello produce sia l'implementazione sia i test, esiste il rischio che entrambi condividano la stessa interpretazione errata del requisito.
Per questo i test generati vanno confrontati con il comportamento realmente richiesto, con eventuali characterization test del sistema esistente e con casi limite derivati dalla conoscenza del dominio.
Il fatto che codice e test siano coerenti tra loro non dimostra automaticamente che siano coerenti con il business.
Il caso del software legacy è ancora più delicato
In una codebase nuova molte decisioni sono esplicite e il perimetro è relativamente controllabile. In un'applicazione legacy, invece, il comportamento reale può dipendere da stored procedure, job schedulati, configurazioni, eventi dell'interfaccia, integrazioni esterne e convenzioni mai formalizzate.
In questi sistemi una modifica apparentemente elegante può essere tecnicamente corretta ma incompatibile con una dipendenza esistente.
È uno dei motivi per cui, anche quando utilizzo l'AI per accelerare l'analisi o il refactoring, preferisco interventi incrementali e verificabili. Lo stesso principio che applico alla modernizzazione di applicazioni .NET Framework vale anche per l'AI: prima comprendere il sistema, poi decidere quanto cambiare.
Dati, segreti e codice proprietario
Un assistente di sviluppo può avere accesso a una quantità significativa di informazioni: codice sorgente, file di configurazione, documentazione, log, schema del database e talvolta dati di esempio.
Prima di utilizzarlo in un contesto aziendale è necessario conoscere le policy del cliente e le modalità con cui lo strumento gestisce i dati. Non dovrebbero essere condivisi indiscriminatamente credenziali, connection string, token, dati personali o informazioni riservate.
La disponibilità tecnica di un tool non equivale automaticamente all'autorizzazione a utilizzarlo su qualsiasi repository.
"Così perdi parte della velocità dell'AI"
È un'obiezione che mi è capitato di sentire, e contiene una parte di verità.
Mi è successo che un assistente completasse in una decina di minuti un'attività che, sviluppata interamente a mano, avrebbe richiesto uno o due giorni. Se però considero il brainstorming iniziale, il refinement della proposta e la revisione successiva, posso dedicare ancora diverse ore alla stessa attività.
Quelle ore, però, non le considero tempo perso. Sono il costo della governance tecnica.
La produttività non consiste nel massimizzare il numero di righe generate al minuto. Consiste nel ridurre il tempo complessivo necessario per arrivare a software corretto, comprensibile, verificabile e coerente con il sistema in cui deve vivere.
La velocità che mi interessa
Non voglio che l'AI scriva codice il più velocemente possibile. Voglio comprimere il tempo di esecuzione senza delegarle le decisioni che devo essere in grado di motivare e mantenere.
Quando l'AI diventa davvero un moltiplicatore
Usata in questo modo, l'AI non sostituisce il lavoro senior: amplifica soprattutto la parte esecutiva.
Può esplorare rapidamente una solution, individuare riferimenti, produrre una prima mappa delle dipendenze, proporre alternative, generare implementazioni ripetitive e preparare test. Lo sviluppatore può concentrare più tempo su requisiti, trade-off, architettura e verifica.
È lo stesso principio che vale quando l'AI viene integrata direttamente in un software aziendale: il modello deve operare dentro confini applicativi chiari. Un esempio concreto è OiccAI, un assistente AI per siti web che utilizza contenuti e fonti autorizzate come base di conoscenza, applicando regole e fallback per mantenere le risposte entro il perimetro definito. Ne parlo anche nella guida su come integrare l'AI in un gestionale .NET senza perdere il controllo su dati e risposte.
Checklist pratica prima di accettare codice generato dall'AI
Prima
- Il requisito è chiaro?
- L'assistente ha analizzato il codice?
- Ha esplicitato rischi e assunzioni?
- Sono state considerate alternative?
Decisione
- La proposta segue i pattern aziendali?
- Rispetta i vincoli del cliente?
- Il perimetro è abbastanza piccolo?
- Il rollback è semplice?
Dopo
- Hai letto il diff?
- Compila senza nuovi warning?
- I test verificano il requisito reale?
- Sono stati controllati gli edge case?
Produzione
- Sai spiegare ogni modifica?
- Hai valutato sicurezza e performance?
- Sono esclusi dati e segreti non necessari?
- La soluzione resta manutenibile dal team?
FAQ
È sbagliato chiedere direttamente a Codex o Claude di implementare una funzionalità?
Non necessariamente. Per modifiche molto piccole e ben delimitate può essere ragionevole. Quando aumentano impatto, dipendenze o rischio, separare analisi e implementazione rende più semplice mantenere il controllo.
Usare questo processo non annulla il vantaggio di velocità?
Riduce la velocità apparente della sola generazione, ma può diminuire il tempo complessivo necessario per arrivare a una modifica affidabile. Soprattutto evita di risparmiare minuti nella scrittura per perderne molti di più nel debugging o nella gestione di regressioni.
Devo leggere davvero tutto il codice generato?
Per il codice destinato alla produzione, sì: il livello di revisione deve essere proporzionato al rischio, ma la responsabilità non può essere trasferita al modello.
Qual è il ruolo migliore per un coding assistant?
Per me è contemporaneamente analista, sparring partner e acceleratore dell'esecuzione. Non è il proprietario delle decisioni architetturali né il responsabile finale del software.
In sintesi
L'AI scrive velocemente. Il controllo tecnico deve restare umano.
Analizzare prima, discutere la proposta, implementare entro confini chiari e revisionare dopo permette di sfruttare Codex, Claude e altri coding assistant senza trasformare la velocità in una rinuncia alla comprensione del codice.
Guide correlate
Vuoi introdurre l'AI nel processo di sviluppo senza perdere governance tecnica?
Posso affiancare software house e team .NET nell'analisi di codebase esistenti, nella modernizzazione del software e nell'adozione pragmatica di strumenti AI all'interno di processi di sviluppo controllati.