Il codice legacy non si riscrive: si mette sotto PHPStan e test, un livello alla volta, mentre continua a rilasciare

Per software house con un gestionale PHP o Laravel di dieci anni, dove nessuno osa più toccare certe cartelle. Il debito tecnico si riduce con numeri che possono solo migliorare, non con un mese di stop.

Ti riconosci in almeno due di queste?

Rispondi a mente, senza dirlo a nessuno.

  • C'è una cartella che "funziona, meglio non toccare", e ogni nuovo assunto la scopre da solo.
  • Un errore di tipo (null dove serviva un oggetto) arriva in produzione una volta al mese.
  • I test ci sono, ma nessuno sa quali passano davvero; la CI è rossa da settimane e nessuno la guarda più.
  • Avete provato PHPStan: 4.000 errori al primo giro, e il tentativo è finito lì.
  • Il cliente chiede la conformità NIS2 e la prima domanda è "chi ha toccato questo file, e quando?".

Se hai detto sì almeno due volte, il problema non sono gli sviluppatori: è che manca una rete di sicurezza che cresca da sola.

Quanto costa davvero il debito tecnico?

Fai il conto sulla tua software house.

  • Un bug di tipo in produzione al mese: mezza giornata per trovarlo, mezza per correggerlo, un cliente per assorbirlo. Dodici l'anno.
  • Ogni sviluppatore nuovo che impara "cosa non toccare" per prova ed errore: settimane di onboarding che un'analisi statica ridurrebbe a giorni.
  • Una CI rossa ignorata è una CI che non esiste: tutto il tempo speso a scriverla è perso.
  • La riscrittura completa costa i mesi di riscrittura più i mesi in cui il vecchio resta senza rete.

Come si porta PHPStan su codice legacy senza fermarsi?

  1. Livello basso più baseline: PHPStan parte al livello che passa e mette gli errori esistenti in un file di baseline. Da quel momento la CI blocca solo gli errori nuovi. Nella repo di questo sito: 350.000 righe, livello 3, un baseline di 796 errori che può solo calare.
  2. Perimetri al massimo: i moduli nuovi e quelli più delicati (pagamenti, accessi, SEO) girano a livello massimo senza baseline, con copertura 100%. Il resto sale di un livello al mese.
  3. Test di caratterizzazione prima di toccare il legacy: descrivono cosa fa il codice oggi, giusto o sbagliato che sia, così la correzione non cambia il comportamento per sbaglio.
  4. Mutation testing sul perimetro: Infection cambia il codice di proposito e controlla che i test se ne accorgano; un test che non fallisce mai non protegge.
  5. Larastan per Laravel: capisce Eloquent, le relazioni e i facade, e toglie i falsi positivi che avevano fatto abbandonare PHPStan la prima volta.

Cosa trovate nella CI dopo il primo mese?

  • PHPStan verde a ogni push, con un baseline che nel mese è sceso e non può risalire.
  • I test che contano (quelli del perimetro) al 100% di copertura e con un punteggio di mutation testing minimo.
  • Un elenco scritto delle cartelle "da non toccare", ora con test di caratterizzazione: si possono toccare.
  • Per la NIS2 lato software: chi ha cambiato cosa e quando, per ogni file, con la CI a testimone. La pagina NIS2 e penetration test lato codice spiega il resto, con la scadenza del 31 ottobre 2026.

Chi lo fa, e perché ti puoi fidare

Quattordici anni di PHP e Laravel in cinque software house (fintech, privacy, viaggi, pubblica amministrazione), gli ultimi sei da tech lead; JavaScream open source e articoli su Red Hot Cyber sulla sicurezza applicativa. Il metodo è lo stesso scritto in una proposta europea valutata 12,3 su 15: TDD con copertura 100% sui moduli nuovi, PHPStan al livello massimo, mutation testing. Entro nel vostro repository lunedì, con la vostra pipeline.

Quanto costa?

A giornate, con tariffe di mercato (Assintel Report 2025: media 508 € al giorno per i freelance ICT in Italia, profili senior sopra): da 500 a 650 € al giorno per un senior Laravel nel vostro team, da 600 a 750 € per sicurezza applicativa e penetration test con report. La prima settimana è a giornate e si può fermare: se dopo cinque giorni non vedete numeri migliori, avete comunque il report. Il listino completo e la pagina senior Laravel per software house.

Il passo giusto è piccolo: 30 minuti gratuiti con accesso in lettura al repository o a un log di una giornata. Ne esce un documento con i tre punti da cui partire, vostro anche se non proseguite.

Domande frequenti su PHPStan e codice legacy

Come si riduce il debito tecnico senza fermare chi lavora?

PHPStan con baseline (blocca solo gli errori nuovi), test di caratterizzazione prima di toccare il legacy, un livello in più al mese e perimetri al massimo sui moduli delicati. I rilasci continuano.

PHPStan ha dato 4.000 errori: da dove si comincia?

Si mettono nel baseline e si parte dal livello che passa. Da quel giorno la CI blocca gli errori nuovi; il baseline scende un po' a ogni ticket e non può risalire. Larastan toglie i falsi positivi di Laravel.

Cos'è un test di caratterizzazione?

Un test che descrive cosa fa il codice oggi, anche quando è sbagliato. Serve a toccare il legacy senza cambiarne il comportamento per sbaglio; poi si correggono i difetti uno per volta, con il test aggiornato.

A cosa serve il mutation testing?

Infection modifica il codice di proposito e controlla che i test se ne accorgano. Un test che non fallisce mai non protegge: il punteggio di mutation dice quanto valgono davvero i test, non quante righe toccano.

Quanto tempo ci vuole per avere PHPStan verde in CI?

Il baseline e la CI verde si fanno nella prima settimana. Salire di livello e allargare il perimetro al massimo è lavoro continuo, di solito un livello al mese, senza fermare i rilasci.

C'entra con la NIS2?

Sì, lato software: la NIS2 chiede di sapere chi ha cambiato cosa e quando, e di gestire le vulnerabilità. Una CI con analisi statica e test è la prova più semplice da mostrare, con la scadenza delle misure al 31 ottobre 2026.

Quanto costa un senior per il codice legacy?

A giornate, da 500 a 650 euro al giorno; la prima settimana si può fermare e lascia comunque il report. I 30 minuti iniziali sono gratuiti.