Il concetto del gioco del Tetris è molto simile a quello di debito tecnico. L’affermazione può lasciare un po’ spiazzati, ma rappresenta il paragone più efficace per inquadrare in termini corretti i problemi che pone agli sviluppatori. Il ragionamento parte dall’esigenza, in fase di sviluppo, di dare priorità alle funzionalità che dovrebbero essere fornite nelle prossime release. In Tetris ogni release consegnata coincide con le linee rimosse/completate, dove più la release è complessa più linee vengono rimosse.
Uno scenario in costante cambiamento
Le esigenze aziendali sono sempre in evoluzione e ogni richiesta di nuove funzionalità comporta sempre dei compromessi nella code base, al fine di fornire tali funzionalità nei tempi richiesti dall’azienda. Per non dire di quando c’è un cambiamento strategico nel prodotto che non è supportato dall’architettura attuale e dobbiamo pensare alla migrazione o, peggio ancora, aggiungere logiche alla code base per mantenere le nuove e le vecchie funzionalità.
In Tetris, questi compromessi e queste decisioni prese nel codice sono gli spazi che rimangono in basso. Continuiamo a giocare, controllando il livello delle linee con questi gap. È il concetto normale del gioco. Nel caso del debito tecnico, accade la stessa cosa: gestiamo le lacune sapendo che alla fine avranno un impatto sui tempi di consegna delle prossime release.
In Tetris, con il passare del tempo i pezzi diventano più veloci, le lacune più complesse da risolvere e il tempo per risolverle si accorcia sempre di più. Nel debito tecnico succede la stessa cosa: i requisiti arrivano con un tempo di consegna previsto, le lacune aumentano e i tempi di consegna del rilascio si allungano. Non è un problema che si può risolvere aggiungendo altre persone.
Ecco perché si chiama debito tecnico: a un certo punto dovrà essere pagato, perché solo risolvendo il debito tecnico l’azienda rimarrà competitiva e genererà valore per il business.
Il concetto: cos’è?
Uno dei creatori del Manifesto Agile, Ward Cunningham, disse una volta che “alcuni problemi con il codice sono come un debito finanziario. Va bene prendere in prestito per il futuro, purché lo si paghi”. Questo è il Business as Usual, ed è normale a volte optare per una codifica più semplicistica e persino ingenua. Pur di poter rispettare la scadenza di un rilascio. A volte è una scelta tattica, soprattutto nelle metodologie di sviluppo agile, dove all’inizio delle prime consegne non si ha ancora un’idea completa e chiara per definire la migliore strategia di progettazione per la soluzione.
Un’altra citazione, questa volta di Martin Fowler dice che “mentre si programma, si impara. Spesso può essere necessario un anno di programmazione su un progetto prima di capire quale sarebbe stato l’approccio progettuale migliore”.
In definitiva, concettualmente un refactoring costante della code base sarebbe una pratica ottimale, in quanto la manterrebbe all’interno di un modello strettamente controllato. Quando uno sviluppatore trova una code base confusionaria e fuori dagli standard, non avrà alcuna motivazione a seguire una buona pratica e si limiterà ad aggiungere un’altra istruzione if al codice e a passare al compito successivo. Si tratta di una sorta di paradosso, che la maggior parte delle aziende non controlla.
Un’altra cosa è pensare sempre alla refactoring del passato, perché è nel passato che si trovano le lacune di Tetris. Un errore comune delle aziende tradizionali è cercare sempre di partire da una soluzione progettuale di base al momento zero. In questo modo, dopo un po’ di tempo i requisiti aziendali non saranno più allineati con il progetto iniziale, poiché non sappiamo come saranno i requisiti in futuro: dopotutto, il business è in costante evoluzione e ci sono sempre startup che sfidano l’attuale status-quo del mercato.
Quando fare il refactoring e pagare il debito?
Effettuare il refactoring in modo costante, rende la vostra code base sempre pronta a ricevere nuove funzionalità in tempi più brevi. Idealmente si dovrebbe fare ogni 4-6 settimane durante la Sprint Review. Meglio ancora se in tempi più brevi. È importante mantenere sempre questa strategia quando si tratta di un progetto a lungo termine, o quando l’applicazione presenta problemi costanti di funzionamento/produzione, un basso livello di riusabilità del codice e soprattutto quando la code base funziona con molte righe di codice con logica aziendale.
Abbiamo anche scenari di opportunità per il refactoring. Quando, ad esempio, vogliamo aggiungere test automatizzati (adozione di DevOps) o addirittura migrare il carico di lavoro nel cloud (modernizzazione dell’app) siamo di fronte a momenti ideali per una bella revisione del passato e per preparare la code base a essere più agile e produttiva, oltre a migliorare il morale del team che lavora a qualcosa di più snello e pulito.
Quando non rifattorizzare e lasciare il Debito Tecnico?
Di solito questo è consigliabile solo negli scenari in cui quell’applicazione verrà ritirata o sostituita da un’altra, come ad esempio un SaaS, che è uno dei percorsi possibili quando si parla di App Modernization. Un’accortezza da tenere sempre presente è quella di non usare il refactoring come soluzione tecnica a un problema culturale dell’azienda, perché il refactoring si trasformerà in una semplice riscrittura, e questo non deve essere l’obiettivo. Sarà solo una perdita di tempo.
Conclusione: non procrastinate!
In sostanza, il Debito Tecnico è sempre la causa di costi di sviluppo elevati, difficoltà a innovare il business, spesso un ostacolo all’aggiunta di funzionalità di sicurezza e, soprattutto, è il principale ostacolo alla Business Agility. In definitiva, prima paghiamo il Debito Tecnico, prima otteniamo i benefici in termini di qualità, facilitiamo l’esecuzione dei test e rendiamo la base di codice più facile da gestire.
SoftwareOne aiuta i propri clienti nel perseguire questa metodologia per eseguire una rapida valutazione e creare una roadmap per stabilire il giusto processo per mantenere più sana la vostra codebase.