←/articoli
5 min di lettura

Come ho migrato un'applicazione legacy a Laravel usando Claude Code (e un processo che si può ripetere)

Migrare un'app Zend Framework enterprise a Laravel con documentazione quasi assente. Ecco il workflow preciso che ho usato con Claude Code: dall'analisi della rotta alla PR, passando per spec, revisione con Codex, e subagent paralleli.


Come ho migrato un'applicazione legacy a Laravel usando Claude Code (e un processo che si può ripetere)

Il problema

Avevamo davanti un'applicazione enterprise in Zend Framework: anni di sviluppo, layer su layer di logica di business, documentazione praticamente assente. La migrazione a Laravel era necessaria — il framework non riceveva più aggiornamenti significativi, il team non conosceva più tutto il codice, e ogni rotta era un'incognita.

Il problema classico della migrazione legacy: non sai esattamente cosa fa il codice che devi riscrivere. Puoi leggerlo, ma ci vogliono ore per capire side effect nascosti, validazioni implicite, comportamenti che nessuno ha documentato.

Claude Code ha cambiato l'equazione.


Il workflow

Prima di entrare nei dettagli, ecco la struttura completa in sei step:

  1. Analisi della rotta — Claude Code legge il codice Zend e produce una mappa del comportamento
  2. Q&A interattivo — Claude fa domande sui comportamenti ambigui
  3. Scrittura della spec — documento strutturato con input, output, regole di business
  4. Revisione con Codex — secondo passaggio per trovare gap nella spec
  5. Plan + esecuzione — piano di implementazione eseguito con subagent paralleli
  6. Testing manuale e PR — lista di casi da verificare, fix finali, pull request

Step 1 — Analisi della rotta

Il punto di partenza è using-superpowers: una skill di Claude Code che stabilisce un workflow strutturato prima di toccare il codice. Una volta attivata, passo la rotta Zend che voglio migrare.

Claude legge controller, model, query, middleware, e produce un'analisi strutturata:

Rotta: POST /ordini/crea

Controller: OrdiniController::creaAction()
- Valida input (cliente_id, prodotti[], note)
- Recupera prezzi da catalogo (query diretta su tabella prezzi_listino)
- Calcola totale con sconto se cliente ha convenzione attiva
- Crea record ordine + righe ordine in transazione
- Invia email di conferma via servizio esterno
- Ritorna redirect a /ordini/{id}/riepilogo

Side effect identificati:
- Aggiorna campo ultimo_ordine_at su tabella clienti
- Log su tabella audit_ordini

Dopo l'analisi, Claude fa domande su tutto quello che non è esplicito nel codice:

"Il calcolo dello sconto usa sempre il listino corrente o quello attivo al momento dell'ordine?"

"L'email di conferma viene inviata anche se l'ordine viene creato da un admin?"

Queste domande valgono oro — sono esattamente le cose che un dev junior (o anche senior) si dimentica di chiedere.


Step 2 — La spec

Una volta chiarito il comportamento atteso, Claude produce una spec strutturata. Non è pseudocodice — è un documento leggibile che descrive input, output, regole di business, casi edge:

## Creazione ordine

**Input:** cliente_id (required), prodotti (array, min 1 item), note (optional)

**Regole:**
- Prezzi calcolati al momento della creazione (snapshot, non listino live)
- Sconto convenzione applicato se cliente.convenzione_attiva = true
- Transazione atomica: ordine + righe o niente
- Email inviata sempre, anche da admin

**Side effect:**
- clienti.ultimo_ordine_at aggiornato
- Riga in audit_ordini con user_id attore

**Output:** redirect a /ordini/{id}/riepilogo

A questo punto faccio una cosa che si è rivelata molto utile: passo la spec a Codex per una revisione indipendente. Codex in questo contesto non scrive codice — legge la spec e risponde a una domanda sola: "cosa manca o potrebbe essere ambiguo?"

Risultato tipico: trova 2-3 cose che Claude si è perso o ha dato per scontato. In un caso concreto ha notato che la spec non diceva cosa fare se un prodotto nel carrello non è più disponibile al momento della creazione. Piccola cosa, grossa rotta nel codice Laravel se non gestita.

Spec aggiornata, si procede.


Step 3 — Plan ed esecuzione con subagent

Con la spec approvata, Claude genera un piano di implementazione dettagliato: ogni task è indipendente dagli altri, con input e output chiari.

## Piano implementazione: POST /ordini/crea

Task 1: Migration + Model Ordine, RigaOrdine
Task 2: OrderService::create() — logica core
Task 3: OrderController + FormRequest validazione
Task 4: Listener email su evento OrdineCreato
Task 5: Feature test end-to-end

L'esecuzione avviene con la skill subagent-driven-development: ogni task viene eseguito da un subagent separato, con il contesto minimo necessario. Niente stato condiviso che si corrompe tra un task e l'altro — ogni subagent riceve la spec, il suo task specifico, e i file rilevanti.

In pratica: mentre un subagent scrive OrderService, un altro può già lavorare sulla migration. Il tempo totale si comprime significativamente rispetto a un'esecuzione sequenziale.


Step 4 — Testing manuale e PR

Prima di aprire la PR, chiedo a Claude di generare la lista dei casi da testare manualmente. Non unit test — quelli li ha già scritti il subagent — ma i casi che un tester umano deve verificare nell'interfaccia reale:

## Checklist testing manuale

Golden path:
- [ ] Ordine con cliente normale, più prodotti, nessuno sconto
- [ ] Ordine con cliente con convenzione attiva → sconto applicato

Edge case:
- [ ] Prodotto con quantità zero nel carrello → errore bloccante
- [ ] Cliente senza indirizzo email → ordine creato, nessuna email, nessun crash
- [ ] Submit doppio (doppio click) → un solo ordine creato

Admin:
- [ ] Ordine creato da admin → email inviata normalmente

Eseguo i test, applico eventuali fix, PR aperta. Code review classica.


Takeaway

Questo workflow non elimina il lavoro — lo riorganizza. Il costo più alto in una migrazione legacy non è scrivere il codice nuovo: è capire il codice vecchio. Claude Code abbatte quel costo in modo drastico.

La cosa più importante: il processo è riproducibile. Non dipende da quanto conosco il codebase, non dipende dall'umore del giorno. Ogni rotta passa dagli stessi step, produce gli stessi artefatti, finisce con gli stessi controlli.

Su un'applicazione enterprise con decine di rotte, la differenza è sostanziale.


Grazie per aver letto fin qui.

Se l'articolo ti è stato utile, iscriviti alla newsletter per ricevere il prossimo direttamente in casella, oppure aggiungi il feed RSS al tuo lettore.

// similarity

// iscriviti

Ricevi il prossimo articolo, via email.