Abbiamo visto nel precedente articolo cosa è il debito tecnico. In questo articolo vedremo quali sono le cause che portano alla sua formazione.
Prima di iniziare, una precisazione: il debito tecnico, le sue cause e le sue conseguenze sono tre oggetti distinti. Un po’ come nella diagnosi delle malattie, è importante non confondere il sintomo con la malattia, con la causa della malattia.
Facciamo un esempio: un paziente con la tosse cronica (sintomo), potrebbe avere una bronchite (malattia) causata dal fumo (causa). Allo stesso modo un team con un numero elevato di regressioni ad ogni sprint (sintomo) potrebbe avere per le mani un software reso fragile dall’assenza di test automatici (malattia) causata dalla pressione sul delivery (causa).
Non tutte le cause sono presenti contemporaneamente in un team. Ogni situazione è unica. Scommetto tuttavia che molti di voi avranno un “momento carramba” leggendo le prossime sezioni. Se invece siate così fortunati da aver sempre lavorato in contesti in cui queste cose non avvengono, mandatemi una cartolina. Ho sempre desiderato un francobollo dell’isola che non c’è.
Pressione sul delivery
Il tempo è sempre troppo poco: la concorrenza corre, i clienti reclamano e i team di sviluppo sono spesso sottoposti a pressioni per rilasciare features, bug fix, enhancement… se a questo sommiamo le note sindromi dello studente e la tendenza al gold plating, è facile capire come il tempo sia spesso un nemico, più che una risorsa.
Sottoposti a pressione, gli sviluppatori sono piú propensi a tagliare curve, a mettere in campo soluzioni “quick and dirty” o, come mi piace chiamarli, “porkaround”. La pressione sul delivery è la prima causa di formazione del debito tecnico. Prima in ordine e, nella mia modesta esperienza, prima come probabilità.
Questa causa presenta due diverse facce: se il debito viene contratto in modo conscio per ragioni valide (portare a casa la pagnotta), costituisce una strategia vincente ammesso che venga gestito. Se per contro viene contratto in modo sconsiderato, diventa l’anticamera del fallimento, soprattutto in presenza di team poco preparati che non si renderanno conto del degrado della qualità del prodotto o si dimenticheranno delle “pezze” messe in giro.
Si genera così un circolo vizioso da cui è difficile uscire: un software con molto debito è difficile da modificare, cosa che porta a bassa produttività e quindi ad aumento della pressione, che a sua volta porta ad altro debito e così via.
Disallineamento rispetto al business
Se la necessità di business non è chiara, se i requisiti sono espressi in modo vago, contraddittorio o incompleto, il team di sviluppo reagirà tipicamente in due modi:
- con soluzioni “troppo strette”, cioè mancanti di quei gradi di libertà che una miglior comprensione del contesto di business avrebbe permesso di individuare.
- con soluzioni “troppo larghe”, cioè con troppi gradi di libertà, con un aumento non necessario della complessità della soluzione.
In entrambi i casi, la capacità di far evolvere del sistema risulterà penalizzata, da cui il debito tecnico.
Scrivere requisiti è un lavoro. Indipendentemente dalla metodologia applicata, saper esprimere quale è il problema da risolvere è piú complesso che risolverlo: non c’è nulla di peggio per la motivazione di un team che arrivare a fine sviluppi con una implementazione perfetta di un sistema inutile.
Cambiamenti tecnologici
La tecnologia cambia. Il lock-in su un middleware, su uno stack tecnologico o su un certo hardware puó ridurre le opzioni di design, portando all’accumulo di debito.
Inoltre, la scarsa reattività nel tenere il passo con il cambiamento può portare a rischi di sicurezza: alzi la mano chi ha ancora in produzione una webapp basata su struts 1 che non è mai riuscito a portare su un framework moderno per mancanza di tempo.
Documentazione inefficace
Non c’è mai tempo per la documentazione. Da quando poi il credo Agile ha dichiarato “working software over comprehensive documentation”, vien quasi da vergognarsi a chiedere se c’è documentazione.
In realtà, come gli sviluppatori seri sanno da sempre, per la documentazione vale lo stesso principio di economia che vale per il codice: il minimo indispensabile, ma di qualità. La qualità si riassume in tre parole: accessibile, pertinente e aggiornata. Trovo il terzo punto particolarmente importante. La documentazione non aggiornata costituisce uno degli esempi piú perniciosi di sindrome della finestra rotta: basta che una persona consulti una volta documentazione non aggiornata per perdere ogni fiducia nell’utilità della stessa (e talvolta nel genere umano).
La mancanza di documentazione di qualità, è un fattore di rischio per la generazione di debito tecnico. Lo sviluppatore, di fronte a codice di cui non capisce la struttura, sarà portato a correre meno rischi possibili mettendo “pezze” dove è più sicuro di non fare danni… non necessariamente nel posto corretto. Il problema si fa particolarmente grave quando un team cresce e in presenza di turnover elevato.
Mancanza di test automatici
La mancanza di test automatici si fa sentire man mano che il sistema cresce. Ad ogni iterazione, in assenza di test automatici il team sarà costretto ad effettuare test di regressione manualmente, con conseguente perdita di tempo ed energie.
L’assenza di test automatici è inoltre il primo ostacolo al refactoring, portando alla sindrome del “se funziona, non toccarlo”. Il miglioramento viene fermato dalla paura.
Team inesperti/distribuiti/effimeri
Da ultimo, il team è la prima, vera causa della generazione di debito tecnico. Questa voce meriterebbe un articolo a sè.
Gli aspetti del team che maggiormente portano alla generazione del debito sono tre:
- Mancanza di esperienza: team costituiti da risorse junior, che magari non hanno mai lavorato insieme o che hanno preso in carico codice altrui (magari gravato da mancanza di test automatici e documentazione) genereranno debito senza neanche rendersene conto (debito non intenzionale).
- Team distribuiti: a volte penso che la distanza minima per passare alla definizione di team distribuito sia due scrivanie. Anche in presenza delle più moderne tecnologie di comunicazione, la distanza è un ostacolo rilevante al fluire delle informazioni. E il disallineamento tra team può facilmente portare interpretazioni errate di scelte di design.
- Team effimeri: la classica struttura a progetto, in cui un team si forma e crea qualcosa che poi viene passato ad un altro team, porta a focalizzarsi sul risultato immediato (maggior propensione a contrarre il debito). Tanto poi sarà un problema di qualcun altro. Un ottimo software può essere fatto a pezzi in brevissimo tempo, un progetto alla volta. Un team dedicato da maggiori garanzie di coerenza nelle scelte e di continuità nella qualità.
Conclusioni
Il debito tecnico si genera per diverse ragioni legate al processo, alle persone e a fattori tecnici. Diverse cause possono essere presenti contemporaneamente ed ogni team costituisce un caso a sé.
Partendo dai sintomi, che sono sempre i medesimi (insufficiente velocità e qualità), ogni team deve avere la lucidità e l’onestà intellettuale di guardarsi dentro ed intorno per individuare le ragioni che hanno portato alla generazione del debito.
Questo è ancora piú importante che individuare il debito stesso: del resto, non si asciuga il pavimento prima di aver chiuso il rubinetto.