Negli articoli precedenti che riguardano questo spinoso argomento, abbiamo visto come nasce il debito tecnico e quali tecniche possono essere più efficaci per gestirlo.
Tuttavia è facile notare che, pur intervenendo a monte dello sviluppo, la gestione del debito tecnico resta costosa: si tratta di spendere prima, in maniera prevedibile, le risorse che altrimenti si sarebbero dovute pagare dopo, in maniera inaspettata e in aggiunta con gli interessi.
A questo punto è giusto chiedersi se non si possa trovare un metodo per risolvere all’origine il problema. Cioè: esiste un modo di scrivere software che, per sua natura, non genera debito tecnico?
La natura relazionale della programmazione
Per rispondere a questa domanda dobbiamo investigare la natura del problema, che, secondo la mia esperienza, risiede nella natura “relazionale” della programmazione: ogni software è una macchina estremamente complessa costituita da migliaia, a volte anche milioni, di ingranaggi (le righe di codice) che devono girare tutti insieme e in accordo.
Per fare un esempio semplice, possiamo osservare che bastano solo tre righe di codice JavaScript per iniziare a sviluppare relazioni e, quando esse non sono gestite, generare debito tecnico.
001 var n1 = 123;
002 var n2 = 234;
003 var sum = n1 + n2;
Vediamo quali relazioni vengono implicitamente definite nel codice precedente:
- La riga 3 dipende dalla 1 in quanto referenzia la variabile n1 in essa definita.
- La riga 3 dipende dalla 2 in quanto referenzia la variabile n2 in essa definita.
- La riga 3 dipende dalla 1 in quanto l’operatore + ha un senso specifico quando l’operando sinistro è un numero.
- La riga 3 dipende dalla 2 in quanto l’operatore + ha un senso specifico quando l’operando destro è un numero.
Ognuna delle precedenti dipendenze aggiunge una piccola parte di debito tecnico perché, quando dovremo modificare le prime due righe, qualcuno si deve ricordare di andare a modificare la riga 3 in accordo.
Nei casi reali, in cui si devono gestire da decine di migliaia fino a milioni di righe di codice, il numero di dipendenze cresce in modo più che lineare, arrivando quindi a dover gestire milioni di possibili modifiche conseguenti. Se poi si pensa che, effettuando queste ulteriori modifiche, anch’esse potranno generarne a loro volta di nuove, il compito diventa facilmente ingestibile o comunque molto costoso e rischioso.
Si può arrivare all’impossibilità di valutare l’impatto di una modifica sull’intero sistema. Quando si raggiunge questo punto, il debito tecnico è talmente alto da portare il sistema verso la stasi e quindi alla morte.
Risolvere il debito tecnico all’origine con la programmazione relazionale
Per evitare di arrivare a questa situazione, le tecniche di gestione del debito tecnico mirano da un lato a ridurre il numero di relazioni fra le varie righe di codice usando una buona ingegneria del software, dall’altro a rendere più basso il costo di valutazione degli impatti delle modifiche aumentando la documentazione e la comunicazione fra i membri del team.
Una diversa soluzione può essere quella di modificare il modo con cui viene creato il software. Invece di scrivere le righe di codice all’interno di un IDE che le memorizza in tanti file di testo (le classi), sviluppare usando un nuovo tipo di IDE, in grado di memorizzare l’intera struttura del progetto in un grafo, in cui ogni nodo rappresenta un “atomo” del progetto, cioè fino al singolo token della singola riga di codice, e ogni arco una relazione che tale atomo eredita dagli altri nodi.
Se questo tipo di IDE fosse in grado di inferire automaticamente le relazioni mentre il codice viene scritto, allora potrebbe avere tutte le informazioni per valutare cosa succede quando si modifica una determinata parte del sistema, o addirittura modificare tutto il resto del sistema automaticamente.
Queste premesse sono alla base della teoria della “programmazione relazionale” che ha portato alla progettazione dei sistemi di sviluppo Instant Developer Foundation e Instant Developer Cloud.
Nel prossimo articolo dettaglierò meglio come funziona la programmazione relazionale in pratica e quali risultati concreti si possono riscontrare nell’utilizzo quotidiano.