Refactoring del codice legacy: perché la tua azienda ne ha bisogno per sopravvivere

Refactoring del codice legacy: perché la tua azienda ne ha bisogno per sopravvivere

In un progetto per un'azienda del settore manifatturiero, il gestionale PHP che gestiva ordini, magazzino e fatturazione era cresciuto per otto anni senza una strategia architetturale: funzioni da 400+ righe, query SQL inline con concatenazione di stringhe, zero test, dipendenze bloccate a versioni del 2017. Ogni modifica richiedeva giorni di test manuali perché nessuno sapeva quali effetti collaterali avrebbe prodotto. Abbiamo applicato un approccio incrementale ispirato allo Strangler Fig pattern di Martin Fowler: isolamento dei moduli critici con test di caratterizzazione, estrazione progressiva della logica in servizi tipizzati, migrazione graduale da PHP 7.2 a 8.3 con Rector per le trasformazioni automatiche. In sei mesi, senza mai interrompere l'operatività, il gestionale è passato da un codebase fragile a un'applicazione con copertura test al 72%, tempo di risposta dimezzato e costi di manutenzione ridotti a un terzo.

Perché il codice legacy diventa un rischio concreto per una PMI?

Il debito tecnico non è una metafora astratta - è un costo misurabile che cresce nel tempo. Il report Coding in the Red di CAST Software (2025), basato sull'analisi di oltre 10 miliardi di righe di codice, identifica Stati Uniti, Italia e Francia come i tre Paesi con il debito tecnico più elevato. Secondo Gartner, circa il 40% dei budget IT aziendali viene assorbito dalla manutenzione e dalla gestione del debito tecnico esistente, anziché essere investito in innovazione.

Per una PMI italiana con applicativi PHP sviluppati negli ultimi 10-15 anni, il debito tecnico si manifesta in forme concrete: funzioni con complessità ciclomatica superiore a 50 (la soglia raccomandata dal NIST è 10 per funzione), accoppiamento stretto tra moduli che rende impossibile modificarne uno senza romperne altri, assenza di test che trasforma ogni rilascio in una scommessa, e dipendenze su versioni PHP fuori supporto che accumulano vulnerabilità non corrette. Il passaggio da PHP 5 a PHP 8 non è solo un aggiornamento di versione - è il prerequisito per accedere all'ecosistema moderno di librerie, framework e strumenti di analisi.

Il costo del debito tecnico è asimmetrico: ogni euro di debito non affrontato oggi ne costa quattro quando il problema diventa critico - un bug in produzione, un data breach su codice non manutenuto, un fornitore che non riesce ad intervenire perché il codebase è incomprensibile.

Lo Strangler Fig pattern: modernizzare senza riscrivere

L'errore più comune nelle PMI è affrontare il refactoring come un progetto "big bang" - riscrivere tutto da zero. Nella mia esperienza, le riscritture totali falliscono nella maggioranza dei casi: richiedono mesi o anni di sviluppo parallelo, durante i quali il sistema legacy continua a evolversi, e il giorno del "go live" le differenze funzionali tra vecchio e nuovo sono ingestibili.

Lo Strangler Fig pattern, descritto da Martin Fowler nel 2004 e aggiornato nell'agosto 2024, propone l'approccio opposto: costruire il nuovo sistema progressivamente attorno al vecchio, spostando comportamenti uno alla volta dal legacy al moderno, fino a quando il vecchio sistema può essere rimosso. Il nome viene dai fichi strangolatori delle foreste pluviali australiane, che crescono attorno all'albero ospite fino a sostituirlo completamente.

In pratica, per un applicativo PHP legacy, questo significa: identificare il modulo con il rapporto più alto tra rischio e valore di business, isolarlo con test di caratterizzazione che ne catturano il comportamento attuale, estrarre la logica in classi o servizi moderni con tipizzazione strict, e instradare progressivamente il traffico dal vecchio al nuovo codice. Michael Feathers, nel suo Working Effectively with Legacy Code, definisce il codice legacy come "codice senza test" - e propone un algoritmo preciso per intervenire: identificare i punti di modifica, trovare i punti di test, spezzare le dipendenze, scrivere i test, e solo allora modificare il codice. L'audit tecnico dei primi 30 giorni è il punto di partenza operativo per mappare dove intervenire.

Gli strumenti per il refactoring sistematico del codice PHP

Il refactoring manuale di un codebase PHP legacy è lento e soggetto a errori. Gli strumenti di analisi statica e trasformazione automatica riducono drasticamente il lavoro meccanico, lasciando al programmatore le decisioni architetturali che richiedono giudizio umano.

Rector è lo strumento chiave per le trasformazioni automatiche: analizza l'AST (Abstract Syntax Tree) del codice PHP e applica regole di modernizzazione - conversione di sintassi obsoleta, aggiunta di type hint, rimozione di codice morto, aggiornamento delle API deprecate. Una configurazione Rector per un progetto legacy in fase di modernizzazione:

use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;

return RectorConfig::configure()
    ->withPaths([
        __DIR__ . '/app',
        __DIR__ . '/src',
    ])
    ->withSets([
        LevelSetList::UP_TO_PHP_84,
        SetList::CODE_QUALITY,
        SetList::DEAD_CODE,
        SetList::TYPE_DECLARATION,
    ])
    ->withSkip([
        __DIR__ . '/vendor',
        __DIR__ . '/storage',
    ]);

Con il set LevelSetList::UP_TO_PHP_84, Rector gestisce automaticamente la maggior parte delle trasformazioni meccaniche necessarie per migrare da PHP 5.6 fino a PHP 8.4: conversione di mysql_* in PDO, aggiunta di union types, sostituzione di each() con foreach, promozione dei costruttori. L'opzione --dry-run mostra il diff senza applicare modifiche, permettendo revisione umana prima di ogni trasformazione.

PHPStan al livello massimo (livello 10, introdotto con PHPStan 2.0) verifica la correttezza dei tipi, identifica codice morto e segnala potenziali errori runtime - una rete di sicurezza che intercetta i problemi introdotti dal refactoring prima che raggiungano la produzione. Il workflow consigliato è: PHPStan al livello corrente → Rector --dry-run → revisione del diff → applicazione → PHPStan al livello target → test suite. Ho descritto questo processo nel dettaglio nella guida pratica al refactoring del codice PHP legacy.

Errori che compromettono un refactoring

Il primo errore è refattorizzare senza test. Modificare codice legacy senza una rete di sicurezza è come operare al buio - ogni cambiamento può introdurre regressioni invisibili che emergono settimane dopo in produzione. I test di caratterizzazione, anche minimali, sono il prerequisito non negoziabile. L'introduzione di test automatici su codebase PHP legacy descrive come iniziare senza dover riscrivere tutto.

Il secondo è refattorizzare tutto contemporaneamente. Un refactoring efficace è incrementale - un modulo alla volta, con rilasci frequenti e verificabili. La tentazione di "sistemare tutto mentre ci siamo" produce branch di sviluppo che divergono per settimane dal codice in produzione, accumulando conflitti e rischi.

Il terzo è misurare il successo del refactoring solo in termini di "codice nuovo scritto". Le metriche che contano sono operative: riduzione del tempo medio per implementare una nuova funzionalità, riduzione del tasso di bug in produzione, riduzione del tempo di onboarding di un nuovo sviluppatore sul codebase, e miglioramento della copertura test. Un refactoring che dimezza la complessità ciclomatica media ma non migliora nessuna di queste metriche operative ha mancato l'obiettivo.

Il quarto, specifico per le PMI italiane, è affidare il refactoring a chi non conosce il dominio di business. Il codice legacy di un gestionale manifatturiero codifica anni di regole di business - calcoli di pricing, logiche di magazzino, workflow di approvazione - che spesso non sono documentate in nessun altro posto. Un refactoring che "pulisce" il codice ma altera una regola di business nascosta in un if annidato può causare danni operativi gravi. Il refactoring di moduli business-critical richiede competenza sia tecnica che di dominio.

Il refactoring del codice legacy non è un costo da rimandare - è l'investimento che determina se il tuo software resterà un asset competitivo o diventerà un vincolo che frena ogni evoluzione del business. Con il report CAST 2025 che posiziona l'Italia tra i Paesi con il debito tecnico più elevato al mondo, la domanda non è se affrontare il refactoring, ma quanto costa ogni mese in cui non lo fai. Per conoscere il mio approccio alla modernizzazione di applicativi legacy e al recupero del controllo su codebase senza documentazione, visita la mia pagina professionale. Se il tuo applicativo critico accumula debito tecnico e vuoi pianificare un percorso di refactoring strutturato e incrementale, contattami per una consulenza dedicata - partiamo dall'audit del tuo codebase.

Ultima modifica: