Quando Riscrivere il Software: La Risposta Onesta
Quando riscrivere il software: le condizioni tecniche e di business che giustificano una riscrittura completa e i segnali d'allarme che indicano la scelta sbagliata.
In questo articolo:
- Perché la Domanda è Più Difficile di Quanto Sembri
- I Segnali che Giustificano Davvero una Riscrittura
- I Segnali che Non Giustificano una Riscrittura
- Perché le Riscritture Falliscono e Come Ridurre il Rischio
- La Checklist Pre-Riscrittura
- Conclusione
Quando riscrivere il software è una delle decisioni più conseguenti che un leader di ingegneria prende. La risposta onesta è: raramente, e quasi mai nel modo in cui i team propongono inizialmente. Questo articolo copre le condizioni specifiche che giustificano effettivamente una riscrittura, i segnali che i team scambiano per giustificazioni, e cosa richiede un processo di riscrittura responsabile anche quando la decisione è corretta.
Perché la Domanda è Più Difficile di Quanto Sembri
La domanda “dovremmo riscrivere questo?” di solito arriva dopo un periodo di frustrazione. I rilasci sono lenti. I bug sono frequenti. Gli ingegneri si lamentano che il codice è impossibile con cui lavorare. La risposta intuitiva è ricominciare da zero, perché ricominciare da zero sembra una via di fuga dai problemi accumulati.
Il problema è che la frustrazione è reale ma la diagnosi è spesso sbagliata. Rilasci lenti, bug frequenti e codice difficile sono sintomi. Possono avere diverse cause. La causa potrebbe essere architetturale: il design fondamentale del sistema non può supportare le capacità richieste. Potrebbe essere la qualità del codice: l’architettura è a posto ma l’implementazione è scarsa. Potrebbe essere il processo: la pipeline di deployment è rotta, il testing è inadeguato, o il coordinamento del team è il collo di bottiglia. Oppure potrebbe essere organizzativa: il team non ha le competenze o la capacità per mantenere il sistema efficacemente.
Una riscrittura affronta la prima causa. Non affronta la seconda, la terza o la quarta. I team che riscrivono senza affrontare la causa sottostante scoprono che il nuovo sistema, costruito dallo stesso team con le stesse pratiche, accumula gli stessi problemi entro 18 mesi.
Il processo di software due diligence è progettato per distinguere tra queste cause prima che venga presa una decisione. L’intervento corretto dipende dalla diagnosi corretta.
I Segnali che Giustificano Davvero una Riscrittura
Ci sono condizioni specifiche e verificabili in cui una riscrittura è genuinamente la scelta giusta.
Il runtime è end-of-life senza percorso di aggiornamento. La versione del linguaggio o del framework non riceve più patch di sicurezza, e l’aggiornamento richiederebbe comunque modifiche all’intero codebase. Se il costo dell’aggiornamento è uguale o superiore al costo della riscrittura, la riscrittura offre benefici aggiuntivi: un’architettura più pulita, una toolchain moderna e nessun vincolo legacy.
Il vincolo architetturale è fondamentale e non può essere affrontato in modo incrementale. Il sistema è single-tenant e deve diventare multi-tenant. Il modello di dati codifica assunzioni incompatibili con il nuovo comportamento richiesto, e modificare quelle assunzioni richiederebbe di modificare ogni modulo. La migrazione incrementale non può colmare questo divario perché non esiste uno stato intermedio valido.
Il sistema è genuinamente piccolo e la specifica comportamentale è completa. Un sistema con 20.000 righe di codice che gestisce un problema ben definito con documentazione completa e copertura dei test può essere riscritto in sicurezza. Un sistema con 500.000 righe di codice con comportamento non documentato e nessun test non può.
Il codebase è genuinamente non manutenibile a causa di vincoli tecnologici, non della qualità del codice. Il linguaggio non ha analisi statica, nessun sistema di tipi, nessun tooling moderno. Ogni modifica è un’indagine manuale su centinaia di file senza una rete di sicurezza automatizzata.
Queste condizioni sono specifiche e verificabili. Non sono “il codice è disordinato” o “agli ingegneri non piace lavorarci”.
I Segnali che Non Giustificano una Riscrittura
Le false giustificazioni più comuni per le riscritture, e cosa indicano effettivamente:
“Il codice è impossibile da capire.” Indica documentazione mancante, nomi scadenti e standard di code review inadeguati. Non indica che l’architettura sia fondamentalmente rotta. Il refactoring con documentazione e standard di denominazione migliorati affronta questo.
“Ogni modifica rompe qualcos’altro.” Indica accoppiamento stretto e copertura dei test inadeguata. Questi sono problemi di qualità del codice, non incompatibilità architetturali. L’introduzione di seam, la scrittura di test di caratterizzazione e il refactoring dei moduli più accoppiati affronta questo.
“Potremmo costruirlo meglio ora.” Questo è quasi certamente vero. È anche vero che il nuovo sistema, costruito con la conoscenza attuale, avrà i suoi problemi di cui i futuri ingegneri si lamenteranno. La domanda non è se una riscrittura produrrebbe inizialmente un sistema migliore. È se la riscrittura vale il costo e il rischio.
“La morale è bassa a causa del cattivo codebase.” I problemi di morale hanno cause organizzative, non solo tecniche. Una riscrittura intrapresa per migliorare la morale migliorerà la morale durante la riscrittura (scrivere nuovo codice è divertente) e spesso abbasserà la morale dopo la riscrittura quando il nuovo sistema ha i suoi problemi e il team si rende conto che i problemi fondamentali non erano tecnici.
Perché le Riscritture Falliscono e Come Ridurre il Rischio
Quando una riscrittura è genuinamente giustificata, il rischio è comunque sostanziale. I pattern di fallimento sono prevedibili.
L’inflazione dell’ambito accade quando la riscrittura viene usata come opportunità per ridisegnare il sistema. Resistere a questo. L’obiettivo di una riscrittura è riprodurre il comportamento del sistema corrente in un’implementazione migliore, non costruire un sistema migliore.
Il problema della specifica è inevitabile. Il comportamento del sistema legacy è più complesso di quanto appaia. Pianificare per questo. Prima di scrivere una riga di nuovo codice, scrivere test di caratterizzazione sul sistema legacy che definiscano il suo comportamento. Questi test sono i criteri di accettazione per il nuovo sistema.
Il requisito dell’operazione parallela non è negoziabile. Il nuovo sistema dovrebbe eseguire in shadow mode accanto al sistema legacy prima che venga cambiato qualsiasi traffico. Confrontare gli output. Identificare le differenze. Correggerle.
Pianificare per il cutover incrementale, non big bang. Anche se la riscrittura è giustificata, il cutover dovrebbe usare lo strangler fig pattern: instradare una piccola percentuale di traffico al nuovo sistema, monitorare, espandere.
La Checklist Pre-Riscrittura
Prima di impegnarsi in una riscrittura, rispondere a ognuna di queste domande in modo specifico:
- Quale specifico vincolo tecnico rende impossibile il refactoring o più costoso della riscrittura?
- Si hanno test di caratterizzazione che coprono il comportamento del sistema legacy nelle aree che vengono riscritte?
- Il team ha la capacità di mantenere il sistema legacy mentre costruisce quello nuovo?
- Esiste un piano per il cutover incrementale, o è una sostituzione big bang?
- Il business ha accettato che la velocità delle funzionalità scenderà durante la riscrittura?
- Qual è il piano se la riscrittura impiega il doppio del tempo stimato?
Se una qualsiasi di queste domande non ha una risposta specifica, la riscrittura non è pronta per iniziare.
Conclusione
Quando riscrivere il software: quando specifici vincoli tecnici verificabili rendono il miglioramento incrementale impossibile o più costoso della sostituzione. Non quando il codice è disordinato, non quando gli ingegneri sono frustrati, non quando un nuovo framework sembra attraente. La checklist pre-riscrittura non è opzionale. I test di caratterizzazione, l’operazione parallela, il cutover incrementale e la disciplina dell’ambito sono ciò che separa le riscritture di successo dalla maggioranza che non riesce a consegnare i benefici promessi.
Hai un codebase con questi problemi? Parliamo del tuo sistema