Il paradosso delle decisioni ragionevoli
Quasi nessun team accumula debito tecnico per negligenza. Lo accumulano prendendo decisioni che, nel momento in cui vengono prese, sono ragionevoli. C'è una scadenza, un contesto parzialmente noto, una pressione legittima. La soluzione più semplice funziona. Si procede.
Il problema non è quella decisione. Il problema è che la stessa logica si applica alla decisione successiva, e a quella dopo ancora, e a quella dopo ancora. Ciascuna di queste decisioni è difendibile presa singolarmente. L'effetto cumulativo di tutte non lo è, ma nessuno è incaricato di osservare l'effetto cumulativo. I sistemi software non mancano di segnali — la CI pipeline, gli strumenti di analisi statica, il tasso di failure in produzione forniscono feedback continuo. Mancano però di un meccanismo che converta automaticamente il costo aggregato del debito in un numero comprensibile al management. Il costo cumulativo delle decisioni locali resta invisibile finché non è troppo tardi.
Capire il meccanismo di accumulo non serve per colpevolizzare chi ha deciso in passato. Serve per capire dove introdurre quei meccanismi di feedback che oggi mancano, prima che il costo diventi insostenibile.
Tre pattern di sedimentazione
Il debito non si accumula in modo uniforme. Nella nostra esperienza, abbiamo osservato che tende a sedimentarsi attraverso tre dinamiche ricorrenti — non categorie della letteratura, ma pattern che ritroviamo con frequenza nei team con cui lavoriamo. Riconoscerli è utile perché ognuno richiede una risposta diversa.
Il primo pattern è la compressione da velocità. Un team deve rilasciare in tempi stretti — può essere una demo, un contratto, una finestra di mercato. La scorciatoia tecnica è razionale: si evita il refactoring che sarebbe necessario, si duplica logica che andrebbe estratta, si bypassa un'astrazione che rallenta ma garantisce manutenibilità. Il risultato immediato è corretto. Il costo è differito. Se la compressione si ripete ogni due-tre sprint, il costo differito si accumula senza mai essere ripagato, perché c'è sempre una ragione urgente per non farlo adesso.
Il secondo pattern è la fossilizzazione da crescita. Un'architettura viene disegnata in un momento preciso della crescita dell'organizzazione, per rispondere ai vincoli di quel momento. Sei sviluppatori, un solo prodotto, tre clienti. L'architettura è corretta in quel contesto. Il problema è che il contesto cambia — venti sviluppatori, quattro prodotti, cento clienti — ma l'architettura resta. Non perché qualcuno abbia deciso di non aggiornarla; semplicemente nessuno ha avuto il mandate esplicito di farlo, e il sistema ha continuato a funzionare abbastanza bene da non giustificare un intervento urgente. La fossilizzazione è il debito più costoso perché è il più invisibile: il sistema funziona, ma ogni modifica richiede workaround che nessuno si aspettava.
Il terzo pattern è la sedimentazione da turnover. Ogni sviluppatore che entra in un team eredita decisioni prese da altri, in contesti che non ha vissuto. Le ragioni originali di quelle decisioni sono nella memoria delle persone, non nel codice. Quando quelle persone lasciano — e lasciano sempre prima o poi — le ragioni scompaiono. Chi arriva dopo lavora su un sistema che ha una storia ma non ha documentazione di quella storia. Le decisioni successive si sovrappongono alle precedenti senza comprenderle. Il debito si stratifica.
Il disallineamento strutturale: chi accumula non è chi paga
C'è un meccanismo organizzativo che aggrava tutti e tre i pattern: chi prende le decisioni che creano debito non è lo stesso che ne paga il costo, e spesso non lo è nemmeno nel tempo.
Il team che sceglie la scorciatoia per rispettare la scadenza di marzo non sarà probabilmente quello che farà manutenzione due anni dopo. Il management che ha prioritizzato le feature rispetto al refactoring non vedrà il rallentamento produttivo che quella scelta ha causato finché non sarà troppo tardi per attribuirlo a quella decisione specifica. Lo sviluppatore che ha introdotto la dipendenza circolare potrebbe non lavorare più in quel progetto quando quella dipendenza bloccherà un'integrazione critica.
Questo disallineamento non è un difetto morale delle organizzazioni. È una conseguenza naturale di come vengono distribuite responsabilità e incentivi nel tempo. I sistemi di incentivi ottimizzano per obiettivi a breve termine; i costi del debito tecnico si manifestano a medio-lungo termine. Finché non esiste un meccanismo che rende i costi futuri visibili nel presente, la struttura degli incentivi tende sempre verso l'accumulo.
La risposta non è colpevolizzare chi ha accumulato. È creare i meccanismi che rendano i costi futuri visibili prima che si materializzino.
La psicologia dell'invisibilità
Oltre al meccanismo organizzativo, c'è un meccanismo psicologico che rende il debito difficile da vedere anche per chi è dentro il sistema.
Il debito si accumula per incrementi piccoli. Nessun singolo commit trasforma un sistema sano in uno insostenibile. La transizione avviene gradualmente, attraverso centinaia di modifiche ciascuna delle quali è marginalmente peggiorativa ma individualmente non allarmante. Il cervello umano è ottimizzato per rilevare cambiamenti rapidi, non derive lente. Lo stesso meccanismo che rende difficile accorgersi che si è ingrassati di dieci chili in un anno rende difficile accorgersi che il cycle time è raddoppiato in dodici mesi.
C'è poi il problema del contesto locale. Ogni sviluppatore ha una visione profonda della propria area del sistema e una visione parziale delle altre. Il debito che rallenta la delivery spesso non sta nell'area dove uno sviluppatore lavora di più; sta nelle intersezioni, nelle dipendenze tra moduli, nei confini dove la responsabilità è ambigua. Nessuno vede il sistema nella sua totalità: il CTO ne vede la struttura ad alto livello, gli sviluppatori ne vedono le parti specifiche. Il debito sistemico vive negli spazi intermedi.
Infine c'è l'effetto della normalizzazione. Quando il cycle time medio è sempre stato tre settimane, tre settimane diventa il riferimento normale. Nessuno si chiede se potrebbe essere una. Quando ogni rilascio richiede un giorno di coordinamento manuale, quello diventa il processo normale. Le deviazioni dalla norma sono visibili; la norma stessa smette di essere messa in discussione. Il debito tecnico che si è sedimentato nel corso di anni cessa di essere percepito come tale: è semplicemente "come funzionano le cose qui".
I segnali precoci che di solito vengono ignorati
Il debito manda segnali prima di diventare un problema grave. Il problema è che quei segnali vengono quasi sempre interpretati come problemi locali e temporanei, non come sintomi di un accumulo sistemico.
Il primo segnale è la varianza nelle stime. Non le stime sbagliate occasionali, che sono fisiologiche, ma la crescita sistematica del delta tra stima e consuntivo sprint dopo sprint. Quando il team sottostima regolarmente del 40-60%, c'è quasi sempre una ragione strutturale: il sistema è meno prevedibile di quanto sembra dall'esterno, perché le dipendenze nascoste moltiplicano gli effetti collaterali di ogni modifica. Questo viene interpretato come un problema di stima, ma è un problema di complessità.
Il secondo segnale è la localizzazione del sapere. Quando solo una o due persone conoscono davvero una parte del sistema, quella parte è a rischio. La conoscenza localizzata è sia effetto del debito — le aree più complesse richiedono anni per essere comprese, quindi pochi riescono a comprenderle davvero — sia causa di accumulo ulteriore, perché chi non conosce non può intervenire con sicurezza. I nuovi sviluppatori impiegano mesi prima di contribuire in autonomia: non perché siano meno capaci, ma perché il sistema è meno leggibile.
Il terzo segnale è l'asimmetria nelle code review. Quando certi moduli ricevono review superficiali perché "è meglio non toccare troppo quella parte", il debito è già insediato. Le review superficiali non proteggono il sistema; rallentano solo l'accumulo senza fermarlo. Un team che ha smesso di fare review approfondite in certe aree ha già accettato implicitamente che quelle aree sono fuori controllo.
Dalla velocità di accumulo alla velocità di impatto
Non tutto il debito accumulato ha lo stesso impatto. C'è debito che rallenta marginalmente aree periferiche, e debito che blocca il cuore del sistema. La differenza tra i due dipende da quanto frequentemente quell'area del codice deve essere modificata e da quante dipendenze la attraversano.
Un modulo legacy che fa una cosa sola, è stabile da anni e non è sul percorso critico della crescita può restare com'è indefinitamente senza che il debito diventi urgente. Lo stesso livello di complessità in un modulo che deve cambiare ogni sprint, che è attraversato da ogni nuova feature e da cui dipendono dieci altri moduli, è un blocco operativo già adesso.
La domanda giusta per valutare l'urgenza non è "quanto debito abbiamo in quell'area?" ma "quanto frequentemente dobbiamo modificare quell'area, e quanto ci costa ogni modifica rispetto a quanto dovrebbe costare?" Il delta tra il costo attuale e il costo atteso è il numero che misura l'impatto del debito su quella specifica area. Calcolarlo su tutte le aree critiche del sistema è il primo passo per smettere di stimare il debito e iniziare a gestirlo.
Vale la pena rendere esplicita una distinzione che cambia il modo in cui si valuta l'urgenza di intervento: il debito tecnico non ha costi fissi. Si paga alla modifica, non esiste in astratto. Un sistema con alto debito ma bassa frequenza di modifica ha un debito latente — presente ma silenzioso, senza impatto operativo immediato. Il debito diventa attivo ogni volta che il team deve intervenire su quell'area: è lì che si manifesta il costo reale. Non tutti i sistemi con debito elevato richiedono attenzione immediata, ma tutti i sistemi ad alta frequenza di modifica con debito elevato sì. Il delta di cui sopra non è solo una metrica: è lo strumento per distinguere dove il debito è già operativo da dove è ancora dormiente.
Cosa fare concretamente
Tre azioni per chi vuole iniziare a rendere visibile l'accumulo prima che diventi insostenibile.
- Misura il trend del cycle time negli ultimi sei mesi: non la media, il trend. Un cycle time che cresce trimestre su trimestre senza un corrispondente aumento nella complessità delle feature è il segnale più affidabile di accumulo in corso. Se non hai il dato storico, chiedi al team: "quanto tempo impiegava questa categoria di modifica sei mesi fa?" La memoria collettiva è meno precisa di un dato strumentato, ma è meglio di niente come punto di partenza.
- Mappa le aree di sapere localizzato: in quale parte del sistema la conoscenza è concentrata su una o due persone? Quelle sono le aree ad alto rischio, indipendentemente dalla qualità del codice. La localizzazione del sapere è sia un sintomo di debito sia un moltiplicatore del rischio: quando quella persona non è disponibile, quella parte del sistema diventa opaca a tutti gli altri.
- Crea un momento di revisione periodica dell'effetto cumulativo: non una code review, che valuta singole modifiche. Un momento dedicato, ogni due-tre mesi, a guardare l'andamento delle metriche nel tempo e a chiedersi dove il delta tra stima e consuntivo è cresciuto. Le organizzazioni che gestiscono bene il debito non sono quelle che evitano ogni scorciatoia; sono quelle che si fermano periodicamente a capire dove sono arrivate.
La prospettiva QMates
Il pattern più comune che incontriamo non è un team che ha smesso di lavorare bene. È un team che ha lavorato bene in un contesto, e quel contesto è cambiato senza che il sistema cambiasse con lui. L'architettura è rimasta quella disegnata due anni fa; l'organizzazione ha triplicato le dimensioni. I bounded context definiti per un prodotto servono tre prodotti diversi. I processi di rilascio pensati per un team di sei sono gestiti da venti persone con le stesse procedure manuali.
Quando entriamo in un'organizzazione, la prima cosa che misuriamo non è la qualità del codice. Misuriamo il disallineamento: tra come il sistema è strutturato e come il business funziona oggi, tra come i team sono organizzati e come il codice distribuisce le responsabilità, tra la velocità che il sistema permetteva e la velocità che l'organizzazione richiede adesso. Il debito tecnico che conta non è il codice brutto; è il gap tra il sistema che hai e il sistema che ti serve per crescere al ritmo a cui stai crescendo.
Il secondo articolo di questa serie ha descritto il meccanismo di accumulo. Il terzo si occupa dei segnali concreti che permettono di riconoscere dove il debito ha già iniziato a rallentare la delivery, prima che diventi un'emergenza.