Vai al contenuto principale
Torna al blog
vibe coding

Ereditare codice sviluppato con il vibe coding: guida per CTO e sviluppatori

di ···9 min di lettura
Elementi in porcellana dalle connessioni intricate diventano tre moduli ordinati, collegati da canali di vetro con accenti turchesi.

La demo funziona e i primi utenti sono arrivati. Poi una modifica al prezzo interrompe le prenotazioni, una correzione ai permessi coinvolge tre schermate e nessuno sa perché due servizi calcolino lo stesso importo in modo diverso. Avete appena ereditato il repository.

Per uno sviluppatore o un CTO, riprendere questa base di codice inizia da una domanda: possiamo prevedere le conseguenze della prossima modifica? La risposta dipende dalle regole aziendali, dai confini tra i moduli e dagli strumenti disponibili per verificarne il comportamento.

Il nostro articolo sui vantaggi e limiti del vibe coding aiuta a scegliere quando usarlo. La guida alla ripresa di un'applicazione affronta l'audit e la preparazione alla produzione. Qui entriamo nel repository: test, vocabolario, moduli, decisioni architetturali e migrazioni.

Il rischio: codice che il team non sa più spiegare

Il codice generato può essere ben progettato, revisionato e testato. Un'applicazione scritta interamente a mano può accumulare gli stessi problemi. L'origine del codice dice poco sulla sua capacità di evolvere: occorre esaminarne il comportamento e le decisioni che ne determinano la struttura.

Il rapporto DORA 2025 descrive l'IA come un amplificatore dei punti di forza e delle debolezze di un'organizzazione. Questa osservazione non valuta il vostro repository. Per un progetto di ripresa, ne ricaviamo una priorità: migliorare comprensione e verifica prima di accelerare nuovamente la produzione di codice.

Un sintomo merita particolare attenzione: nessuno sa spiegare una regola senza ricostruire il funzionamento dell'intera applicazione o chiedere a un modello di farlo. Una spiegazione plausibile resta un'ipotesi finché il codice eseguito, i test e gli esperti del settore non la confermano.

Prima del refactoring: stabilire una versione di riferimento

Partite da un ambiente riproducibile, con una versione del codice identificata, dipendenze con versioni bloccate e dati di test. Verificate che il team sappia distribuire e ripristinare il servizio, poi seguite un percorso critico dalla schermata fino all'archiviazione dei dati e ai servizi esterni.

Se scoprite dati esposti, accessi non autorizzati o segreti compromessi, affrontate questo rischio prima di riordinare l'architettura. Riorganizzare le cartelle non rende sicura un'applicazione vulnerabile.

Scegliete quindi un primo ambito: una funzionalità aziendale che cambia spesso, causa incidenti o blocca un rilascio. I cinque interventi seguenti possono partire da questo ambito ed estendersi successivamente al resto dell'applicazione.

1. Migliorare la testabilità prima di cambiare le regole

I test di caratterizzazione descritti da Michael Feathers registrano ciò che un programma fa realmente. Permettono di rilevare cambiamenti di comportamento durante una ripresa, anche quando mancano le specifiche originali. Non dimostrano che quel comportamento sia desiderabile.

Consideriamo un'applicazione fittizia per le prenotazioni, che useremo nel resto dell'articolo. Prima di riordinarne il codice, osservate una prenotazione confermata, un annullamento e una richiesta ripetuta dopo un'interruzione della connessione. Registrate risposte ed effetti: stato della prenotazione, scritture nella banca dati e notifiche inviate.

Separatamente, concordate i risultati attesi con gli esperti del settore. Se il comportamento attuale consente due conferme per l'ultimo posto disponibile, conservate una riproduzione del difetto e scrivete un test per il risultato corretto. Un errore noto non deve diventare un requisito con il pretesto di preservare il comportamento esistente.

La testabilità migliora quando le dipendenze sono controllabili. Separate il calcolo di una scadenza dalla lettura dell'orologio, e la decisione di confermare dalla chiamata al fornitore di pagamento. Testate le regole senza accedere alla rete; nei test di integrazione verificate anche gli adattatori reali e i vincoli della banca dati.

  • Regole aziendali: scadenza, annullamento, rimborsi parziali e variazioni di prezzo.
  • Integrazioni: richieste simultanee per l'ultimo posto, risposte tardive ed eventi duplicati.
  • Percorsi critici: conferma mostrata all'utente corretto e accesso negato a un'altra organizzazione.

Per il CTO, il primo risultato atteso è una modifica utile consegnata con la protezione di questi test. La copertura complessiva può aggiungere informazioni, ma non sostituisce le verifiche sui rischi effettivi del prodotto.

2. Stabilire un linguaggio di dominio condiviso

Un'applicazione può chiamare lo stesso concetto «prenotazione» nell'interfaccia, «ordine» nell'API e «sessione» nella banca dati. Può anche usare «cliente» per indicare una persona autenticata, un'organizzazione e un account di fatturazione. Questa ambiguità finisce per influire su permessi e regole aziendali.

Il linguaggio condiviso del Domain-Driven Design, illustrato da Martin Fowler a partire dal lavoro di Eric Evans, avvicina il vocabolario degli sviluppatori a quello degli esperti del settore. Si evolve insieme alla comprensione del dominio.

Per il nostro sistema fittizio di prenotazione, un primo incontro di lavoro potrebbe produrre queste definizioni:

TermineSignificato concordatoRegola da verificare
OpzioneUn posto riservato temporaneamenteHa una scadenza esplicita
PrenotazioneUna riserva confermataRispetta la capacità disponibile
PagamentoUn'operazione di pagamentoIl suo stato è distinto da quello della prenotazione
OrganizzazioneIl perimetro di accesso di un teamNon può leggere le prenotazioni di un'altra organizzazione

Queste definizioni vanno validate per il prodotto concreto. Un pagamento fallito annulla la prenotazione o apre un periodo per regolarizzarlo? Il codice, da solo, non può decidere quale comportamento vuole l'azienda.

Riportate i termini concordati nei tipi, nelle operazioni, nei test e nella documentazione del dominio. Mantenete esplicite le corrispondenze con le API precedenti. Due domini possono legittimamente usare parole diverse: uniformarle a forza introdurrebbe un'altra ambiguità.

Un agente di programmazione deve ricevere queste definizioni e le relative invarianti prima di proporre una modifica. Offrono anche a chi revisiona il codice criteri concreti per accettare o rifiutare la proposta.

3. Creare moduli profondi con contratti semplici

Un modulo profondo offre funzionalità significative attraverso un'interfaccia relativamente semplice. Nel suo confronto con Robert C. Martin, John Ousterhout spiega perché moltiplicare le piccole funzioni possa disperdere la complessità anziché ridurla.

Nel nostro esempio, ogni schermata potrebbe verificare la disponibilità, calcolare il prezzo, creare una prenotazione e inviare una notifica. Aggiungere file di utilità lascia comunque a ogni chiamante la responsabilità di coordinare correttamente questi passaggi.

Un'operazione aziendale come confirmBooking può esporre un contratto più utile: identità autenticata, prenotazione interessata, chiave di idempotenza e risultati possibili. Il modulo coordina le regole di conferma; chi lo chiama può distinguere un posto non disponibile, un accesso negato e un pagamento in sospeso.

Un'interfaccia breve, da sola, non basta. Il contratto deve descrivere effetti ed errori. Una transazione locale non può rendere atomica una chiamata a un fornitore esterno: stato intermedio, ripresa dopo un errore e prevenzione dei duplicati devono restare espliciti.

Cercate responsabilità coerenti: prenotazioni, fatturazione e identità. Possono essere distribuite insieme nella stessa applicazione. Estrarre microservizi aggiungerebbe vincoli di rete e di gestione che richiedono una giustificazione separata.

Criterio di accettazione: una modifica alle regole di conferma cambia il modulo e i suoi test; i chiamanti restano stabili finché il contratto non cambia. Numero e lunghezza dei file dicono poco senza verificare questo comportamento.

4. Spiegare le decisioni inattese con gli ADR

Il codice mostra come funziona una soluzione, ma a volte ne lascia invisibile la motivazione. Perché conservare due identificatori? Perché elaborare un evento in modo asincrono? Perché accettare temporaneamente due formati?

Un Architecture Decision Record, o ADR, conserva una decisione significativa, il suo contesto, lo stato e le conseguenze. Michael Nygard propone documenti brevi, versionati insieme al codice, mantenendo accessibili le decisioni precedenti quando vengono sostituite.

Un ADR per il nostro esempio fittizio potrebbe contenere:

  • Contesto: il fornitore può inviare più volte lo stesso evento di pagamento.
  • Decisione: registrare l'identificatore dell'evento e renderne idempotente l'elaborazione.
  • Opzione scartata: presumere che ogni invio rappresenti un nuovo pagamento.
  • Conseguenze: definire vincoli di unicità nella banca dati, ripresa dopo un errore e test per invii simultanei.
  • Stato: accettato, con collegamenti all'implementazione e ai test corrispondenti.

Durante una ripresa, un agente può aiutare a trovare le tracce di una decisione. Se manca la cronologia, indicate che la motivazione deve ancora essere confermata. Una giustificazione inventata oggi non è la memoria del progetto.

Riservate gli ADR alle scelte significative. Una condizione locale può richiedere soltanto un nome più chiaro o un commento che ne spieghi il vincolo. Una documentazione utile evita che una modifica futura elimini una protezione il cui scopo è stato frainteso.

5. Automatizzare le migrazioni ripetitive

Una volta validato il nuovo contratto, possono restare decine di chiamate da aggiornare. È un buon caso per un codemod: una trasformazione del codice che potete esaminare, testare e ripetere.

jscodeshift offre strumenti per trasformare più file JavaScript o TypeScript attraverso la loro struttura sintattica. Questo permette di intervenire su forme precise del codice anziché sostituire testo indiscriminatamente.

Nel nostro esempio, una trasformazione potrebbe sostituire le chiamate al vecchio servizio di prenotazione i cui parametri corrispondono al nuovo contratto. I casi ambigui devono restare alla revisione manuale. Un albero sintattico, da solo, non dimostra che due operazioni abbiano lo stesso significato aziendale.

  • Testate la trasformazione su esempi prima e dopo, inclusi i file che deve ignorare.
  • Esaminate una simulazione su un ambito limitato, controllando importazioni, alias e firme.
  • Applicate le modifiche per gruppi, poi eseguite controllo dei tipi, test e revisione delle differenze.
  • Verificate che una seconda esecuzione lasci il risultato invariato e individuate le vecchie chiamate rimaste.

Una migrazione del codice non migra automaticamente i dati. Per modifiche incompatibili alle API o allo schema, il modello Parallel Change descritto da Danilo Sato distingue tre fasi: estendere, migrare ed eliminare il vecchio contratto.

Introducete un nuovo formato che supporti la transizione, migrate i componenti che lo usano e i dati, poi verificate che non restino lettori o scrittori del vecchio formato. Solo dopo eliminate quest'ultimo. Se entrambi i sistemi scrivono contemporaneamente, definite anche come rilevare e riconciliare le divergenze.

Il ritorno alla versione precedente deve considerare i dati trasformati e gli effetti esterni. Ripristinare il commit precedente non basta dopo aver eliminato una colonna o inviato una notifica.

Le decisioni che spettano al CTO

Decidete per singola funzionalità aziendale. Un'interfaccia utilizzabile può essere mantenuta mentre il modulo dei permessi richiede una sostituzione. L'approccio Strangler Fig descritto da Martin Fowler offre un metodo per sostituire il sistema gradualmente e valutare i risultati durante la transizione.

Situazione osservataDecisione possibileEvidenza richiesta
Comportamento compreso, stabile e verificatoMantenereLa modifica successiva resta locale e verificabile
Regole affidabili, dipendenze troppo accoppiateEseguire un refactoring gradualeI test del comportamento restano validi
Sottosistema fragile con confini identificabiliIsolare, poi sostituireContratto verificato e strategia di migrazione
Modello incompatibile con le esigenze e correzione troppo costosaValutare la riscrittura dell'ambito interessatoConfronto che includa dati, transizione e gestione operativa

Prima di finanziare una ripresa completa, scegliete un progetto pilota limitato: per esempio, rendere affidabile la conferma di una prenotazione e consegnare una modifica reale alle sue regole. Stimate separatamente comprensione, riduzione dei rischi, refactoring e migrazione. Registrate le incognite e fissate un momento per rivalutare l'approccio.

Misurate il tempo necessario per consegnare quella modifica, le regressioni, il lavoro di revisione e la capacità del team di diagnosticare gli errori. Un repository con più test e documenti, ma ancora difficile da modificare, non ha raggiunto l'obiettivo.

Continuare a usare l'IA dopo la ripresa

Gli agenti restano utili per mappare le dipendenze, proporre casi limite e preparare trasformazioni ripetitive. Richiedete riferimenti precisi ai file, ipotesi esplicite e modifiche abbastanza contenute da poter essere revisionate.

I risultati attesi dai test devono derivare da regole validate o da comportamenti osservati e compresi dal team. Generare implementazione e valutazione a partire dalla stessa ipotesi può semplicemente riprodurre due volte un errore.

Il primo obiettivo della ripresa è concreto: un'altra persona del team sa spiegare, modificare, testare e distribuire una funzionalità aziendale senza riscoprire l'intera applicazione. Tutti e cinque gli interventi sostengono questa autonomia.

Per preparare una ripresa con Appik Studio, mostrateci il percorso che vi blocca e la prossima modifica necessaria. Possiamo definire l'analisi attorno a quella modifica, ai rischi associati e alle parti del prodotto da conservare.

Fonti e riferimenti

Torna al blogGaspard Chevassus · CEO, Appik Studio

CONTATTI

contact@appik-studio.ch
+41 78 693 58 72

STUDIO APPIK

Avenue de Béthusy 26,

1005, Lausanne, Svizzera.

46.52°N · 6.63°E

FacebookLinkedIn

Appik Studio SARL, Copyright © 2026|Informativa sulla privacy|Chi siamo

Appik Studio è un team senior con sede a Losanna. Progettiamo e sviluppiamo applicazioni mobile, web e IA per startup, laboratori di ricerca e istituzioni svizzere.