Nel mondo del software, cinque anni possono significare sia un sistema ancora molto ben preparato per un ulteriore sviluppo, sia un problema tecnologico che, con ogni mese in più, costerà sempre di più.
La sola età dell'applicazione non è però un motivo per sostituirla.
È una delle cose più importanti da dire all'inizio.
Non esiste una soglia universale oltre la quale un'applicazione debba essere riscritta da zero. Esistono sistemi che funzionano da diversi anni e che hanno ancora un'architettura sensata, dipendenze aggiornate, una buona documentazione e un processo di rilascio collaudato. Esistono anche applicazioni molto più giovani il cui sviluppo è stato reso difficile da decisioni architetturali errate, mancanza di test, dipendenze non controllate o ulteriori rapide correzioni.
Il problema quindi non è il numero di anni.
Il problema è la capacità del sistema di continuare a cambiare.
La domanda più importante non è: "L'applicazione è vecchia?"
La domanda migliore è: "Quanto ci costa il prossimo cambiamento?"
Se aggiungere una nuova funzionalità richiede un numero sempre maggiore di ore, il coinvolgimento di più team, test manuali e soluzioni alternative ai limiti della vecchia architettura, il sistema comincia a generare un costo che non si vede nel codice stesso.
Questo è proprio uno dei sintomi pratici del crescente technical debt.
Il technical debt può essere inteso come il costo dei cambiamenti futuri derivante da decisioni tecniche precedenti. Martin Fowler lo descrive come lo sforzo aggiuntivo che bisogna sostenere nel modificare un sistema quando la sua qualità interna ostacola lo sviluppo.
Ed è proprio per questo che un'applicazione può continuare a funzionare correttamente e allo stesso tempo diventare sempre più difficile da sviluppare.
10 funzionalità dopo, il sistema appare completamente diverso
L'inizio di un progetto è spesso semplice.
Nasce un MVP.
Poi arrivano ulteriori requisiti:
- integrazione con il CRM,
- pagamenti online,
- pannello di amministrazione,
- applicazione mobile,
- nuovi ruoli utente,
- reporting,
- automazioni,
- API,
- integrazioni con servizi esterni,
- ulteriori versioni linguistiche.
Ogni cambiamento singolarmente può essere giustificato.
Il problema nasce quando l'architettura non era stata progettata pensando a una simile direzione di sviluppo.
Allora le funzioni successive non vengono più aggiunte a una struttura stabile.
Vengono aggiunte ai precedenti casi particolari, workaround e compromessi.
Come si riconosce che il sistema inizia a invecchiare?
Non bisogna aspettare il guasto completo.
I segnali di allarme compaiono molto prima.
1. La nuova funzionalità richiede sempre più tempo
Un tempo una funzionalità richiedeva pochi giorni. Oggi una modifica simile richiede diverse settimane.
Non deve per forza significare un team più lento.
Può significare che sempre più tempo viene assorbito dalla comprensione del sistema esistente e dalla sua protezione contro gli effetti del cambiamento.
2. Ogni cambiamento innesca un effetto domino
La modifica di un modulo provoca problemi in diversi altri punti.
È il segnale che i componenti sono troppo strettamente collegati o che i confini di responsabilità tra loro sono stati definiti male.
3. I test sono principalmente manuali
Se ogni cambiamento importante richiede il controllo manuale di decine di funzioni, il costo del rilascio aumenta.
Il problema non è la sola mancanza di automazione.
Il problema è la mancanza della possibilità di ottenere rapidamente un'informazione affidabile sul fatto che qualcosa sia stato rotto dalla modifica.
4. Il team ha paura di toccare determinati segmenti del sistema
È un indicatore molto pratico.
Se esistono moduli che gli sviluppatori evitano perché "nessuno sa esattamente cosa succederà dopo la modifica", il rischio tecnico è già un costo aziendale reale.
5. Il sistema dipende da tecnologie obsolete
Un vecchio framework di per sé non è un problema.
Il problema nasce quando:
- non è più supportato,
- è difficile trovare specialisti,
- le dipendenze non possono essere aggiornate in sicurezza,
- l'ambiente di esecuzione è problematico,
- l'integrazione con nuove soluzioni è difficoltosa.
Allora la tecnologia inizia a limitare le possibilità di business.
Bisogna sempre riscrivere l'applicazione da zero?
No.
Questo è uno degli errori più comuni nell'approccio al legacy software.
Una riscrittura completa può essere giustificata, ma è un'iniziativa ad alto rischio.
Un vecchio sistema spesso contiene decine o centinaia di regole di business, eccezioni e comportamenti che non compaiono nella documentazione. Riscrivendolo da zero, si può molto facilmente creare un sistema tecnicamente nuovo, ma incompleto dal punto di vista del business.
Per questo in molti casi una soluzione migliore è la modernizzazione graduale.
Una parte del sistema rimane attiva e le aree successive vengono gradualmente sostituite da nuovi componenti.
Questo approccio è noto tra l'altro come pattern Strangler Fig. Permette di modernizzare il sistema passo dopo passo, fornire valore prima e ridurre il rischio di una migrazione unica dell'intera soluzione.
Quando la modernizzazione ha senso?
Vale la pena prenderla in considerazione quando:
- il sistema continua a realizzare processi aziendali importanti,
- l'architettura consente di separare almeno una parte della funzionalità,
- i dati possono essere migrati o integrati in modo sicuro,
- il problema riguarda aree specifiche e non l'intera struttura,
- l'applicazione genera valore e la sua sostituzione completa sarebbe rischiosa,
- il sistema può essere modernizzato per fasi.
È una soluzione particolarmente valida nel caso di sistemi che non si possono semplicemente spegnere per alcuni mesi.
Quando la modernizzazione può non avere senso?
Esistono anche situazioni in cui continuare a salvare un vecchio sistema smette di essere economicamente conveniente.
Ad esempio quando:
- l'architettura è fondamentalmente incompatibile con i requisiti attuali,
- le tecnologie chiave non sono supportate,
- il sistema non ha test né documentazione affidabili,
- la sicurezza richiede una profonda riprogettazione,
- ogni cambiamento importante richiede interventi in quasi tutto il sistema,
- mancano persone che ne comprendano il funzionamento,
- i costi di manutenzione e sviluppo superano il valore di un ulteriore utilizzo.
Allora vale la pena calcolare non solo il costo della modernizzazione.
Bisogna calcolare anche il costo di restare con l'attuale soluzione.
L'applicazione più costosa non è sempre quella più costosa da mantenere
Si può avere un sistema la cui manutenzione mensile costa relativamente poco.
E allo stesso tempo ogni nuova funzionalità costa molte volte più di quanto dovrebbe.
È proprio per questo che la sola fattura per hosting, server o supporto non dice ancora quanto costi la tecnologia.
Il costo reale di un sistema comprende anche:
- tempo di sviluppo,
- tempo di test,
- costo degli errori,
- tempo di rilascio,
- costo dei fermi,
- difficoltà di reclutamento,
- rischio per la sicurezza,
- costo della perdita di conoscenza,
- ritardo nelle nuove funzionalità,
- vincoli di business derivanti dalla tecnologia.
A un certo punto la tecnologia smette di essere uno strumento a supporto del business.
Inizia a essere un limite per il business.
Come affrontare la decisione?
Prima che venga presa la decisione "riscriviamo tutto da capo", vale la pena effettuare un audit tecnico.
Dovrebbe includere almeno:
Architettura - come è suddiviso il sistema e come comunicano i suoi elementi.
Codice - qualità, complessità, ripetitività e punti particolarmente difficili da mantenere.
Dipendenze - framework, librerie, versioni e relativo supporto.
Sicurezza - vulnerabilità, modalità di gestione degli accessi e rischi derivanti da componenti obsoleti.
Test - livello di automazione e possibilità di introdurre modifiche in sicurezza.
CI/CD - modalità di build, test e rilascio dell'applicazione.
Dati - struttura del database, migrazioni, integrazioni e dipendenze.
Monitoraggio - se si sa cosa succede al sistema dopo il rilascio.
Processo di sviluppo - quanto costa realmente consegnare la funzionalità successiva.
Solo su questa base si possono considerare razionalmente tre scenari:
- manteniamo e sviluppiamo,
- modernizziamo per fasi,
- costruiamo un nuovo sistema.
Non esiste una sola risposta giusta. Esiste invece il modo giusto per arrivare alla risposta.
La tecnologia dovrebbe abilitare la crescita, non bloccarla
Una buona architettura non consiste nel fatto che il sistema sembri moderno.
Consiste nel fatto che si possa modificare quando lo richiede il business.
Per questo vale la pena guardare l'applicazione non solo attraverso il prisma del fatto che funzioni oggi.
Bisogna anche verificare, quanto costerà aggiungere nuove funzionalità tra un anno, due o cinque anni.
Perché un sistema che funziona, ma impedisce uno sviluppo efficiente, può essere un problema molto più grande di un sistema che semplicemente richiede una modernizzazione.



