IT/EN

Riscrittura o refactoring: un framework decisionale per i CTO del mid-market

WWG
Pubblicato
Tempo di lettura16 min di lettura
Riscrittura o refactoring: un framework decisionale per i CTO del mid-market

La scelta tra riscrittura e refactoring non è quasi mai una decisione puramente tecnica. Sbagliarla significa finanziare due sistemi contemporaneamente: la vecchia piattaforma che continua a far funzionare l'azienda e la nuova piattaforma, in ritardo, incompleta e politicamente protetta proprio perché ci si è già speso troppo. Secondo McKinsey e la University of Oxford (2012), i grandi progetti IT del loro campione hanno superato il budget in media del 45% e hanno generato il 56% di valore in meno rispetto alle previsioni. (mckinsey.com)

In sintesi

  • La maggior parte delle proposte di riscrittura di un sistema legacy confonde il rischio architetturale con il rischio di conoscenza.
  • L'assenza di test impedisce di fare refactoring in sicurezza, ma impedisce anche di verificare una riscrittura.
  • Una riscrittura completa è giustificata solo quando il sistema attuale non può essere reso sicuro, supportabile o modificabile in modo economicamente sostenibile.
  • Lo strangler fig pattern si adatta spesso meglio al flusso di cassa del mid-market, perché sostituisce il rischio a fette.
  • Prima di approvare il budget, valutate codice, dipendenze, logica di business, processo di rilascio e costo del cutover.

Perché “l'architettura è sbagliata” di solito non è il vero motivo?

“L'architettura è sbagliata” spesso significa che il team non comprende più il sistema abbastanza bene per modificarlo con sicurezza. È anzitutto un problema di persone chiave e di trasferimento di conoscenza. Una riscrittura può mascherarlo per un anno, per poi ricrearlo su uno stack più moderno, con ancora meno persone che capiscono il sistema sostitutivo.

L'argomento più solido contro le riscritture resta “Things You Should Never Do, Part I” di Joel Spolsky, pubblicato su Joel on Software nell'aprile del 2000. Spolsky citava Netscape 6.0, Borland, dBase per Windows, Quattro Pro, Microsoft Access, Microsoft Word per Windows e Project Pyramid per dimostrare che i team sottostimano sistematicamente la conoscenza incorporata nel codice funzionante. (joelonsoftware.com)

La sua tesi centrale ha resistito bene al tempo: il codice vecchio contiene correzioni di bug, casi limite, cicatrici operative e decisioni di business che nessuno ha documentato. Quando gli sviluppatori lo definiscono “confuso”, potrebbero stare reagendo al carico cognitivo più che a un difetto oggettivo. Leggere un sistema è più difficile che scriverne uno nuovo; questo non rende il nuovo più economico.

Nelle aziende mid-market, la spinta verso la riscrittura nasce di solito da quattro fonti:

  • Nessuno capisce il codice. Gli autori originali se ne sono andati e gli sviluppatori attuali evitano i moduli a rischio più alto.
  • Lo stack sembra fuori moda. Assumere è più difficile, gli strumenti sembrano vecchi e i nuovi responsabili associano la modernità alla credibilità.
  • Il team originale non ha lasciato una mappa. Le regole di business vivono nei ticket, nei vincoli del database, nei job pianificati e nella tradizione orale del supporto.
  • Un nuovo responsabile vuole ripartire da zero. È umano, ma non è un business case.

Queste motivazioni non sono irrazionali: sono semplicemente incomplete. Un CTO dovrebbe tradurle in un linguaggio di rischio che un CEO o un CFO possa valutare: rischio di dipendenza, rischio di continuità, rischio di reperimento delle competenze, rischio di difetti, rischio di rilascio e costo opportunità.

Il pericolo è che la riscrittura di un sistema legacy crei l'illusione del controllo. I primi sei mesi sembrano produttivi, perché il team costruisce rapidamente componenti greenfield. Poi arrivano le parti difficili: eccezioni, particolarità della reportistica, workflow specifici per singoli clienti, integrazioni, migrazione dei dati, regole di autorizzazione, riconciliazione e cutover.

Secondo Flyvbjerg, Budzier, Lee, Keil, Lunn e Bester (2022), gli sforamenti di costo dei progetti IT seguono una distribuzione a code spesse: gli sforamenti estremi si verificano più spesso di quanto si aspetterebbe un manager che ragiona su un rischio distribuito normalmente. (arxiv.org) È per questo che “questa volta la riscriviamo come si deve” non basta. La domanda non è se l'architettura esistente sia brutta. La domanda è se sostituirla riduca il rischio complessivo per il business più rapidamente di quanto farebbe capirla e migliorarla.

Che cosa può risolvere il refactoring e dove si ferma?

Il refactoring può migliorare modificabilità, leggibilità, modularità, testabilità e design locale senza alterare il comportamento esterno. Non può salvare un modello di dominio radicalmente sbagliato, eliminare ogni rischio di piattaforma o rendere sicuro per sempre un runtime non più supportato. Un piano di refactoring di un'applicazione legacy deve rispettare questi limiti, altrimenti diventa una riscrittura mascherata.

Martin Fowler definisce il refactoring come la ristrutturazione del software senza modificarne il comportamento osservabile. (martinfowler.com) È una definizione importante, perché molte proposte di “refactoring” non sono affatto refactoring: sono modifiche funzionali, cambi del modello dati, migrazioni di framework, riscritture di integrazioni e ridisegni del deployment raccolti sotto una parola che suona meno costosa.

Un buon refactoring funziona quando il comportamento del sistema è nel complesso corretto ma il costo del cambiamento sta crescendo. Può aiutare quando un flusso di checkout è troppo intricato, quando un modulo di pricing contiene regole duplicate o quando il confine di un servizio è diventato poco chiaro. Può anche ridurre il rischio di onboarding, trasformando una struttura implicita in concetti nominati e in giunzioni più piccole.

Il refactoring è la scelta di default quando:

  • le regole di business sono valide ma difficili da individuare;
  • la piattaforma è ancora supportabile;
  • i difetti nascono da complessità locale e non da un guasto sistemico;
  • il team è in grado di aggiungere test sui flussi critici;
  • la domanda di cambiamento è costante e non esistenziale.

Non è una bacchetta magica. Il refactoring non può rendere sicuro un database il cui fornitore non esiste più, non può cambiare un modello dati che contraddice il business e non può annullare un decennio di ipotesi di prodotto sbagliate. Non può nemmeno garantire il rilascio se l'organizzazione continua a interrompere gli sviluppatori con fix urgenti in produzione.

Una riscrittura completa diventa più credibile quando il sistema attuale blocca operazioni di business necessarie, e non semplicemente rallenta l'ingegneria. Alcuni esempi: un modello di dominio che non riesce a rappresentare i contratti attuali, un'architettura dei dati che impedisce gli adempimenti di reporting obbligatori, un runtime che non può ricevere aggiornamenti di sicurezza. Anche in quei casi, la “riscrittura completa” va trattata come l'opzione su cui grava l'onere della prova, non come il punto di partenza.

L'avvertimento di Spolsky è utile proprio perché non sostiene che tutto il codice vada salvato: sostiene che i team buttano via conoscenza funzionante con troppa leggerezza. (joelonsoftware.com) Per un CTO, la mossa pratica è distinguere la complessità recuperabile dall'impossibilità strutturale. La prima merita refactoring. La seconda può giustificare la sostituzione, ma solo dopo che le evidenze dimostrino che la riparazione incrementale costerebbe più di una migrazione controllata.

Quali cinque domande decidono quando riscrivere il codice legacy?

Cinque domande decidono quando riscrivere il codice legacy: potete verificare il comportamento, conoscete le regole di business, la piattaforma è supportata, potete permettervi il funzionamento in parallelo e oggi il fatturato passa da quel sistema? Le risposte trasformano un dibattito emotivo sull'architettura in una decisione su flusso di cassa, continuità e rischio di rilascio.

Partite dalla verificabilità. Se non esiste copertura automatica sui flussi critici, non potete modificare in sicurezza il sistema vecchio. Ma lo stesso fatto indebolisce la tesi della riscrittura: non potete nemmeno dimostrare che il nuovo sistema si comporti correttamente. Il primo investimento è spesso la copertura dei test come prerequisito per un refactoring sicuro, non un nuovo codebase.

In secondo luogo, chiedetevi dove vive la logica di business. Se le regole di pricing, eleggibilità, evasione, gestione dei sinistri, regolazione o reporting esistono solo nella testa delle persone, la riscrittura diventerà un costoso progetto di archeologia. Gli sviluppatori riscopriranno le regole attraverso difetti in produzione, discussioni tra stakeholder e collaudi in fase avanzata.

In terzo luogo, valutate il supporto della piattaforma. Runtime non più supportati, librerie senza patch, sistemi operativi vecchi e versioni di database abbandonate cambiano il profilo di rischio. Questo non significa automaticamente “riscrivere tutto”: può voler dire rehosting, aggiornamento del runtime, isolamento delle dipendenze o sostituzione del solo strato non sicuro più sottile.

In quarto luogo, mettete alla prova l'ipotesi del funzionamento in parallelo. Una riscrittura completa richiede di norma un periodo in cui il sistema vecchio e quello nuovo coesistono. Questo significa infrastruttura duplicata, supporto duplicato, strumenti di riconciliazione, QA aggiuntiva, script di migrazione, piani di rollback e utenti di business in grado di confrontare gli output. Se il CFO non può finanziare questa sovrapposizione, il piano di rilascio è già sottocapitalizzato.

In quinto luogo, stabilite se oggi il fatturato passa da quel sistema. Una piattaforma critica per il fatturato non dovrebbe diventare un laboratorio, a meno che la situazione attuale non sia già intollerabile. Se il sistema fattura ai clienti, riceve ordini, calcola prezzi contrattuali, gestisce le scorte o sostiene processi regolamentati, la strategia di migrazione deve proteggere la continuità prima dell'eleganza.

Queste domande smontano anche le false certezze. Un team può dire “riscriviamo” perché non ci sono test. Ma l'assenza di test aumenta anche il rischio della riscrittura. Un responsabile di prodotto può dire che “il sistema vecchio blocca la crescita”, mentre il collo di bottiglia reale potrebbe essere il processo di deployment, la qualità dei dati o un workflow di approvazione manuale.

Secondo McKinsey e la University of Oxford (2012), i grandi progetti IT diventano più rischiosi al crescere della durata: la loro analisi ha rilevato che ogni anno aggiuntivo di durata del progetto aumenta lo sforamento dei costi del 15%. (mckinsey.com) È un dato rilevante per le riscritture, perché queste concentrano il valore in un cutover tardivo. Refactoring e strangler fig permettono invece di rilasciare riduzione del rischio già prima, dando ai vertici un controllo migliore sulla spesa.

Quale matrice decisionale dovrebbe usare un CTO tra riscrittura e refactoring?

Usate una matrice decisionale che valuti insieme verificabilità, conoscenza, supporto della piattaforma, sostenibilità economica del funzionamento in parallelo e criticità per il fatturato. Nessun singolo fattore decide da solo l'esito. Fate refactoring quando il comportamento è compreso e la piattaforma supportabile; usate lo strangler fig quando il rischio va ridotto in modo incrementale; riscrivete solo quando le fondamenta attuali non possono soddisfare in sicurezza le esigenze del business.

Esito Copertura dei test Logica di business Supporto della piattaforma Funzionamento in parallelo Esposizione del fatturato
Refactoring I flussi critici possono essere coperti prima di intervenire Le regole sono ricostruibili dal codice, dai test, dagli utenti o dalla documentazione Runtime e dipendenze sono ancora supportabili Non necessario oltre i normali controlli di rilascio Il fatturato passa dal sistema, quindi va minimizzato il cambiamento di comportamento
Strangler fig La copertura può essere costruita attorno alle giunzioni e alle fette migrate Le regole possono essere formalizzate un dominio alla volta Alcuni componenti sono rischiosi, ma non tutti richiedono sostituzione Sostenibile per capability, integrazioni o gruppi di utenti selezionati L'esposizione del fatturato è alta, quindi va ridotta l'ampiezza del cutover
Riscrittura completa Il comportamento esistente non è verificabile o non è più desiderato Le regole vanno riprogettate, non copiate La piattaforma di base non è supportata o blocca cambiamenti essenziali Il business può finanziare doppio esercizio, riconciliazione e rollback L'esposizione del fatturato è gestibile, isolata o già a un livello di rischio inaccettabile

La matrice è volutamente conservativa. Una riscrittura deve superare diverse soglie, perché concentra il rischio di rilascio. Se una sola colonna è critica, la risposta di norma non è una ricostruzione completa. Se sono critiche tre colonne o più, il CTO dovrebbe valutare seriamente la sostituzione.

Per esempio, un runtime non più supportato può giustificare da solo una migrazione tecnica, ma non necessariamente una nuova architettura di prodotto. Una copertura dei test insufficiente dovrebbe far scattare test harness e test di caratterizzazione, non un repository vuoto. Una logica di business non documentata dovrebbe far scattare discovery, documentazione e calcoli in shadow.

La casella più pericolosa è l'esposizione del fatturato. Se dal sistema legacy passa denaro ogni ora, il piano di riscrittura deve includere il costo di esercizio del sistema vecchio fino a quando il nuovo non si sarà dimostrato affidabile. È qui che le riscritture incontrano la finanza. Il budget di rilascio non è soltanto “costruire il sistema sostitutivo”: è costruire, validare, riconciliare, migrare, formare, esercire, monitorare e dismettere.

È per questo che CEO e CFO dovrebbero chiedere l'economia delle opzioni, non etichette tecniche. Qual è l'investimento minimo che riduce il rischio maggiore? Quale decisione diventerà irreversibile? Quale opzione preserva la liquidità se le condizioni di mercato cambiano? Quale opzione consente all'azienda di fermarsi presto portando a casa qualcosa di utile?

Secondo Spolsky (2000), Microsoft evitò un disastro strategico con Word per Windows perché continuò a lavorare sul codebase esistente mentre Project Pyramid falliva. (joelonsoftware.com) La lezione si applica direttamente alle riscritture nel mid-market: non date mai per scontato che il sistema sostitutivo arrivi prima che quello vecchio richieda un'altra modifica critica per il business.

Perché lo strangler fig è la terza opzione che i team mid-market dovrebbero considerare?

Lo strangler fig pattern sostituisce un sistema legacy in modo incrementale: si costruiscono nuove capability ai margini, si instrada verso il nuovo sistema una parte selezionata del comportamento e si dismettono i componenti vecchi nel tempo. Spesso si adatta al flusso di cassa del mid-market meglio di un refactoring puro o di una riscrittura completa, perché valore e riduzione del rischio arrivano in rilasci più piccoli.

Martin Fowler ha introdotto il post originale sulla Strangler Fig Application nel 2004 e ne ha aggiornato la terminologia nel 2024, spiegando la metafora della sostituzione graduale attorno a un sistema ospite esistente. (martinfowler.com) In termini pratici, si colloca un confine controllato attorno all'applicazione legacy, si intercettano eventi o richieste selezionati e si sposta una capability di business alla volta.

Questo approccio funziona bene quando il sistema attuale è troppo importante per essere fermato ma troppo costoso da mantenere invariato. Permette al CTO di sequenziare la migrazione per valore di business: prima l'onboarding dei clienti, poi la reportistica, più tardi il pricing, o qualunque capability generi il rischio maggiore. E offre al CFO gate di finanziamento progressivi, invece di una singola grande scommessa.

Un piano strangler efficace comprende di norma:

  • un livello di routing o un confine API;
  • intercettazione degli eventi o sincronizzazione dei dati;
  • gestione condivisa di identità e autorizzazioni;
  • riconciliazione tra gli output vecchi e nuovi;
  • metriche di migrazione per ciascuna capability;
  • un piano di dismissione dei moduli legacy.

Il pattern non è semplice. Introduce complessità temporanea, perché due mondi coesistono. Servono architettura disciplinata, test automatici, osservabilità e una pianificazione attenta del cutover. È per questo che l'infrastruttura per il funzionamento in parallelo e la pianificazione del cutover contano tanto quanto il codice applicativo.

L'argomento originale di Fowler non era che lo strangler fig costi meno in senso strettamente contabile, ma che rilasci frequenti riducono il rischio ed evitano molte funzionalità inutili che le riscritture con cutover unico tendono a generare. (martinfowler.com) Per un'azienda da 50 a 500 persone, la differenza è decisiva: il board può verificare i progressi ogni trimestre, invece di attendere 18 mesi per un lancio ad alta tensione.

Lo strangler fig è la risposta giusta quando il sistema contiene sia logica di business di valore sia vincoli tecnici reali. Accetta che una parte del codice legacy debba morire, ma si rifiuta di trattare l'intera applicazione come usa e getta. Se il sistema sostitutivo va costruito, affidatevi a un team dedicato per costruire il sistema sostitutivo una capability alla volta, e non come un universo parallelo isolato.

Che cosa fare prima di decidere tra riscrittura e refactoring?

Prima di decidere, fate svolgere una valutazione indipendente di codebase, dipendenze, regole di business, test, processo di rilascio, infrastruttura e modello economico del cutover. Senza evidenze, la scelta tra riscrittura e refactoring non è compiibile. La valutazione deve produrre opzioni, rischi, sequenze e intervalli di costo, non un verdetto già scritto.

Una valutazione credibile parte dal mappare il sistema com'è, non come le persone lo ricordano. Esaminate repository, pipeline di deployment, schemi di database, job pianificati, integrazioni, log, storico degli incidenti, ticket di supporto e cadenza dei rilasci. Intervistate sviluppatori, product owner, utenti dell'amministrazione, operations, assistenza clienti e chiunque conosca le eccezioni.

Poi classificate quello che avete trovato:

  • Rischio di conoscenza: poche persone comprendono i moduli chiave.
  • Rischio di verificabilità: i test non proteggono il comportamento critico.
  • Rischio di piattaforma: dipendenze o infrastruttura non sono supportate.
  • Rischio sui dati: il modello non riesce a rappresentare la realtà attuale del business.
  • Rischio di rilascio: i rilasci sono lenti, manuali o fragili.
  • Rischio commerciale: fatturato, contratti o conformità dipendono dal sistema.

L'output non dovrebbe essere un PDF di 90 pagine che nessuno legge, ma un dossier decisionale che un CTO possa inoltrare a un CEO o a un CFO: evidenze sullo stato attuale, percorso raccomandato, alternative scartate, sequenza di migrazione, ipotesi di budget, modello di staffing e costo di non fare nulla.

La valutazione deve anche distinguere “riscrivere” da “modernizzare”. La modernizzazione può significare test migliori, modularizzazione, aggiornamento delle dipendenze, automazione DevOps, migrazione al cloud, osservabilità o un programma strangler fig. Una riscrittura completa è solo uno degli strumenti di quell'insieme più ampio.

Secondo McKinsey e la University of Oxford (2012), le grandi iniziative IT di successo richiedono allineamento tra contenuto tecnologico, valore di business, stakeholder, team e controlli di progetto. (mckinsey.com) È esattamente per questo che la valutazione deve esaminare il processo di rilascio oltre al codice. Un'azienda che riscrive mantenendo la stessa titolarità confusa, la stessa QA debole e la stessa governance di prodotto sovraccarica riprodurrà gli stessi schemi di fallimento.

La domanda da porre in consiglio è semplice: quali evidenze vi farebbero cambiare idea? Se nessuna evidenza fermerebbe la riscrittura, la decisione è già diventata ideologica. Se le evidenze possono cambiare il percorso, potete scegliere razionalmente tra refactoring, strangler fig e riscrittura completa del sistema legacy.

Per la maggior parte delle aziende mid-market, il passo successivo giusto non è l'autorizzazione a ricostruire. È un software audit breve e indipendente che trasforma la frustrazione in fatti. Una volta che sapete cosa è davvero rotto, potete spendere sul vincolo reale invece che sulla narrazione che lo circonda.

Prima di approvare un budget di riscrittura, fate svolgere una valutazione indipendente e basata su evidenze del sistema di cui state discutendo. Mappiamo codice, dipendenze, regole di business, processo di rilascio e costo del cutover, e vi consegniamo un dossier decisionale che potete portare davanti a un CEO o a un CFO.

Contattaci

Fonti

  • Joel Spolsky, "Things You Should Never Do, Part I", Joel on Software, 2000 — joelonsoftware.com
  • Martin Fowler, "Original Strangler Fig Application", 2004 — martinfowler.com
  • Martin Fowler, "Strangler Fig", 2024 — martinfowler.com
  • Martin Fowler, "Definition Of Refactoring" — martinfowler.com
  • McKinsey & Company e University of Oxford, "Delivering large-scale IT projects on time, on budget, and on value", 2012 — mckinsey.com
  • Bent Flyvbjerg, Alexander Budzier, Jong Seok Lee, Mark Keil, Daniel Lunn, Dirk W. Bester, "The Empirical Reality of IT Project Cost Overruns: Discovering A Power-Law Distribution", 2022 — arxiv.org

FAQ

Domande Frequenti

Risposte pratiche per i CTO del mid-market che devono scegliere tra la riscrittura di un sistema legacy e una modernizzazione incrementale.

Il refactoring ristruttura il software senza modificarne il comportamento osservabile: il sistema continua a funzionare mentre il suo design interno migliora. Una riscrittura sostituisce il sistema, quindi il comportamento deve essere ricostruito e dimostrato di nuovo da zero. Molte proposte etichettate come refactoring sono in realtà modifiche funzionali, cambi del modello dati, migrazioni di framework o ridisegni del deployment raccolti sotto una parola che suona meno costosa.
Quando il sistema attuale non può essere reso sicuro, supportabile o modificabile in modo economicamente sostenibile. Esempi concreti: un modello di dominio che non riesce a rappresentare i contratti attuali, un'architettura dei dati che impedisce gli adempimenti di reporting obbligatori, o un runtime che non può più ricevere aggiornamenti di sicurezza. Se è vera solo una di queste condizioni, la risposta di norma non è una ricostruzione completa.
Non in sicurezza, ma l'assenza di test non è nemmeno un argomento a favore della riscrittura, perché significa anche che non potete dimostrare che il sistema sostitutivo si comporti correttamente. Il primo investimento è di solito una serie di test di caratterizzazione sui flussi critici, non un nuovo codebase.
È un approccio di sostituzione incrementale: si colloca un livello di routing o un confine API attorno all'applicazione legacy, si intercettano richieste o eventi selezionati, si sposta una capability di business alla volta e si dismettono i componenti vecchi man mano che vengono sostituiti. Si adatta bene al flusso di cassa del mid-market perché riduzione del rischio e valore arrivano a fette, invece che in un unico cutover tardivo.
Codebase, dipendenze, regole di business, copertura dei test, processo di rilascio, infrastruttura e modello economico del cutover, incluso il costo di far funzionare in parallelo il sistema vecchio e quello nuovo. L'output dovrebbe essere un dossier decisionale con evidenze sullo stato attuale, il percorso raccomandato, le alternative scartate, la sequenza di migrazione, le ipotesi di budget, il modello di staffing e il costo di non fare nulla.

Raccontaci il Problema

Mohamed Deramchi

Mohamed Deramchi

Fondatore & CEO di WWG

20+ anni di leadership IT, product e cloud consulting. Guida la strategia di delivery e la direzione tecnica senior.

Invia Il Tuo Brief

Inviando accetti la nostra privacy policy.

Coesione Italia 21-27 Lombardia - Cofinanziato dall'Unione europea - Regione Lombardia