Perché ci sono sempre bug e li devo pagare (quasi sempre) io?

, , , , ,

Dietro le quinte, il lavoro di un team di sviluppo e di gestione dell’operatività di un prodotto digitale è caratterizzato da molte soddisfazioni così come da molti problemi frustranti.

Dal punto di vista delle soddisfazioni, una di quelle che personalmente mi stimolano di più è quella di poter creare, spesso da zero, qualcosa che genera un risultato anche molto rilevante per un cliente.

Tra le frustrazioni ci sono invece quelle relative al fatto che è impossibile produrre software senza difetti o riuscire a servire sempre correttamente una richiesta operativa di un utente, anche con le migliori intenzioni, così come riuscire a far sì che un’infrastruttura abbia un uptime del 100% in un anno è pressoché infattibile e, in ultima istanza, anti economico.

In generale molti di questi problemi rimangono poco visibili agli utenti finali e ai committenti, se il team è ben organizzato e ci sono dei processi di controllo adeguati.

Tuttavia, proprio per la natura del software e dei sistemi che lo fanno girare su Internet, e in generale della complessità di una piattaforma digitale, è inevitabile imbattersi in bug, incidenti e problemi di comunicazione.

Per un perfezionista questa è appunto una grossa frustrazione, così come lo è per il cliente che si aspetta di ottenere qualcosa di funzionante e di farsi capire quando chiede supporto.

La verità, se hai un team che lavora per te, è che devi accettare che questa è la normalità ed è importante impostare correttamente le tue aspettative o quelle dei tuoi utenti, così come degli stessi specialisti che ci lavorano.

Così come il mondo fisico che ci circonda è imperfetto, incompleto e temporaneo, così lo è anche il mondo del digitale.

E’ del tutto evidente a chiunque abbia mai scritto un programma o abbia provato a gestire un progetto di sviluppo, molto probabilmente è capitato anche a te: non importa quanto ci si impegna e quanto si sia circondati da esperti, il software avrà comunque dei bug. Alcuni vengono scoperti, altri no, ma sono comunque esistenti.

L’obiettivo deve dunque essere quello di sviluppare e gestire software e sistemi in modo da minimizzare le imperfezioni, che ci saranno a prescindere.

Da questo punto di vista, limitandosi allo sviluppo software, ci sono varie pratiche e metodi che assicurano un’elevata qualità e aiutano a mitigare la presenza di anomalie.

Ad esempio, il Test Driven Development, dove si scrivono dei test ancor prima di realizzare il codice, dopodiché si scrive il codice in grado di far passare questi test.

Questo aiuta a dimostrare che il codice che stiamo scrivendo faccia quello che ci si aspetta, inoltre serve a intercettare future regressioni (che significa in sostanza tornare indietro in termini di qualità) quando si scrive codice che impatta in quello già esistente.

Come beneficio ulteriore, il fatto che il codice sia scritto in un modo facilmente testabile è un segno che potenzialmente è anche ben architettato e progettato, anche se non è una garanzia.

Per essere testabile, il codice deve essere infatti scritto in un certo modo che “costringe” i programmatori a non prendere una serie di brutte scorciatoie.

Inoltre, dopo aver scoperto e sistemato un bug, andrebbero scritti anche i test per verificare che questi bug non si presentino più.

Un’altra pratica importante è quella del pair programming, cioè quella di programmare in coppia lavorando sullo stesso codice, alternandosi nella scrittura.

Questo aiuta molto nel far sì che uno sviluppatore si accorga di un problema anche se l’altro programmatore nella coppia non se n’era accorto.

In più, i buchi nell’esperienza di uno dei programmatori sono più facilmente coperti dall’esperienza dell’altro, e viceversa. Anche un programmatore molto esperto ha inevitabilmente delle lacune.

Quello dello sviluppo in coppia è quasi sempre visto dai clienti e da chi gestisce un gruppo di lavoro come un grosso spreco di risorse, praticamente come un raddoppio di costi.

Se questo è ciò che pensi, ti stai sbagliando di grosso. Il pair programming non aumenta i costi, li riduce. Il problema nasce dal fatto di “contare le ore” invece che apprezzare la qualità e i minori problemi che ci saranno (facendoti risparmiare le TUE ore).

Un ulteriore metodo per migliorare la qualità del software è quello di sottoporlo all’integrazione continua, in termini tecnici chiamata continuous integration: quando il codice viene inviato nel cosiddetto repository remoto, oppure ad intervalli con un certa frequenza, i test vengono lanciati in automatico senza che debba farlo manualmente qualcuno.

Se ci sono problemi e il software non passa i test, non può neanche essere inviato in produzione.

Ma anche impiegando tutte queste pratiche, è del tutto realistico pensare che ci possano comunque essere dei casi mancanti, dei problemi latenti o degli errori di progettazione.

Oppure potrebbe essere sfuggito un requisito del committente, che magari non è neanche mai stato espresso né raccolto correttamente.

O, ancora, solo dopo averlo realizzato, ci si accorge che il sistema ha un comportamento che non è realmente quello desiderato, anche se tecnicamente corretto.

Oltre ad essere imperfetta, una piattaforma digitale soffre anche del problema di essere del tutto temporanea e volatile.

Per capire meglio cosa intendo, possiamo fare un paragone con la versione più antica di questo problema, che chi è più grande conosce sicuramente.

Tanti anni fa, ad esempio, i programmi e i dati venivano memorizzati su floppy disk e hard disk che avevano la tendenza a corrompersi o smagnetizzarsi (e comunque neanche oggi le memorie sono del tutto sicure).

Oggigiorno questo è un problema molto meno sentito, sia perché si usano supporti e file system più affidabili oltre a sistemi ridondati, sia perché molti di questi dati e codici si sono spostati sul cloud (quindi da problema tuo è diventato problema, almeno in teoria ma non sempre nella pratica, di qualcun altro), ma si verifica comunque ad esempio in forma di migrazioni di piattaforme e aggiornamenti che possono fare perdere informazioni.

Ad esempio, l’aggiornamento dei linguaggi o l’utilizzo di piattaforme che ad un certo punto non vengono più supportate rendono più concreto il problema della temporaneità.

Un’azienda che ha realizzato qualche anno fa la propria piattaforma digitale, fino a poco tempo fa perfettamente funzionante, si potrebbe trovare nella condizioni di doverla modificare aggiungendo nuovi componenti o integrarsi a sistemi terzi che richiedono tuttavia la versione aggiornata del framework utilizzato per costruire la piattaforma.

E’ del tutto possibile e frequente che se il framework o il CMS ha qualche anno e non è mai stato aggiornato, non sia più possibile effettuare questo tipo di operazioni senza un grosso e costoso lavoro di migrazione.

Questo è un problema anche in termini di sicurezza: avere codice non aggiornato o non aggiornabile espone ad attacchi di ogni genere, che più passa il tempo e più sono costosi per l’impatto devastante che possono avere visto che si sta spostando quasi tutto sul digitale.

Non si può risolvere il problema della temporaneità, ma lo si può mitigare riducendo la quantità di sistemi terzi integrati, ad esempio componenti, librerie di codice ed API esterne, e utilizzando degli strumenti di package management (Composer in PHP, npm per Javascript, e così via).

Inoltre, se ci si aspetta che la propria piattaforma continui ad essere sicura e sempre pronta per essere migliorata ed estesa, è necessario pianificare del tempo per un’adeguata manutenzione, per aggiornare i pacchetti software che la compongono e per migrarla quando necessario alle nuove versioni del framework o prodotto utilizzato alla base.

Non è qualcosa che puoi pensare di accantonare, perché magari non c’è budget in quel momento o perché ci sono funzionalità più importanti da consegnare.

Quando arriverà il momento, sarà troppo tardi e sarà un bagno di sangue che sistemare ti costerà molto di più che se non fosse stato fatto a tempo debito.

Infine, non accade quasi mai che un prodotto sia realmente concluso e che ogni funzionalità sia stata realizzata.

Questo perché chi ha in mente un prodotto ha tipicamente più idee di quante risorse ne abbia per realizzarlo. E se sei un imprenditore o un manager, sono abbastanza sicuro che questo descriva anche la tua situazione.

O anche perché una volta che un prodotto arriva nelle mani degli utenti, molte delle assunzioni iniziali che hanno portato a realizzarlo in un certo modo si rivelano non adeguate se non errate ed è necessario adattarlo, considerando anche le mutevoli condizioni del mercato e i prodotti della concorrenza che evolvono a loro volta.

Questo, peraltro, è in linea con quanto affermo normalmente sulla necessità di non ragionare a progetto quando si realizza una nuova piattaforma o servizio digitale, perché quasi mai ha realmente una fine nel breve/medio termine.

In sostanza, sebbene sia più facile focalizzarsi sui problemi che si pongono quando si sviluppa un prodotto digitale, accettare il fatto che quest’ultimo non sarà mai perfetto, permanente e completo, né che potrà stare in piedi da solo, è la chiave per non creare aspettative irrealizzabili e frustrazione, focalizzandosi invece sul modo per mitigare questi problemi.

Se quindi la presenza di bug, il verificarsi di incidenti e inefficienze nell’operatività quotidiana sono inevitabili in fase di sviluppo, esercizio e manutenzione di un prodotto digitale, d’altra parte si pone una domanda fondamentale: chi deve pagare questi problemi?

Sotto questo aspetto, non è raro che i clienti (interni o esterni) pensino che a dover pagare per i bug e i problemi di questo genere debba essere il team di sviluppo.

E’ un ragionamento naturale e del tutto comprensibile. Ma molto pericoloso e, in realtà, controproducente per il cliente.

Pensare solamente di prendersela con il team di sviluppo, magari sanzionandolo in qualche modo, non è affatto l’approccio corretto, per i motivi che indicherò più avanti.

Potrebbe sembrarlo nel breve termine, ma non lo è nel medio/lungo termine: potrebbe anzi essere un disastro finanziario.

Prima di spiegare i motivi, è necessario saltare alle conclusioni e anticipare la risposta corretta e definitiva alla domanda “chi paga i bug”: è il cliente a dover pagare i bug e i problemi, ma a sua volta il team deve imparare da questi ultimi. E’ essenziale che le due parti vadano di pari passo.

Mi rendo perfettamente conto che questa risposta può stupire e rendere confusi, in particolare se detta da me.

Chi mi conosce e usufruisce dei servizi miei e della mia azienda, sa perfettamente che Innoteam offre una serie di garanzie uniche ed è orientata al risultato finale al punto che gestiamo le attività per conto dei clienti con ruoli di responsabilità. Quindi perché i clienti dovrebbero pagare questi errori?

La confusione e lo stupore nascono dal fatto che quasi sempre c’è un equivoco di fondo su cosa il cliente sta pagando effettivamente.

E’ infatti facile rimanere intrappolati nella mentalità che un rilascio o una consegna di uno sviluppo di un fornitore o di un team di sviluppo debbano essere corredati da una garanzia che copre eventuali bug.

E’ del tutto normale che un cliente abbia l’aspettativa di ottenere ciò per cui sta pagando, è ciò che mi aspetto anche io stesso.

Il punto è che confusione proprio su questo aspetto: è l’aspettativa ad essere errata, non ciò che si sta ottenendo.

Per farti capire cosa intendo, è importante comprendere che lo sviluppo di software su misura non deve essere confuso con l’acquisto di un’applicazione standard già pronta o l’abbonamento ad un servizio online.

In questi ultimi casi è giusto aspettarsi un’esperienza sostanzialmente priva di bug già inclusa nel prezzo, o comunque solo con problemi minori.

Il prezzo comprende infatti già il margine del produttore e i costi sostenuti da quest’ultimo per lo sviluppo, il test, la correzione delle anomalie, oltre a una fetta di costi futuri di ricerca e sviluppo per l’evoluzione del software e la sua manutenzione/correzione di problemi.

Gli eventuali bug devono quindi essere risolti con i futuri aggiornamenti distribuiti dalla software house (o applicati direttamente se si tratta di un’applicazione online in modalità SaaS).

E’ a questo che serve la garanzia nei prodotti software standard.

Quando invece si lavora sulla progettazione e sullo sviluppo di un software e un’infrastruttura su misura, come avviene normalmente in un prodotto digitale complesso, si sta pagando qualcosa di ben diverso, soprattutto se è la primissima versione del prodotto o una nuova caratteristica importante in un prodotto già esistente.

In questi casi, l’azienda che commissiona lo sviluppo e la manutenzione corre una serie di rischi molto importanti.

Ad esempio, quello di costruire il prodotto giusto, finanziarlo, pianificarlo correttamente, integrarsi con l’esterno e impiegare approcci e tecnologie ancora non consolidati se non addirittura ancora da dimostrare. Tutti questi rischi si presentano praticamente in ogni prodotto o servizio digitale degno di nota.

Il motivo vero, quindi, per il quale si paga un team tecnologico, è quello di mitigare questi rischi, non quello di renderlo finanziariamente responsabile se qualcosa va storto in uno di quei punti.

Da questo punto di vista non bisogna fare confusione tra rischio di impresa, che è perlopiù a carico del committente, e rischio tecnologico, che è invece perlopiù a carico del team di sviluppo.

E’ per questi motivi che un’iterazione di sviluppo o un rilascio non corrispondono automaticamente alla garanzia di ottenere un prodotto finito e senza anomalie.

In questo contesto, il team deve dare il massimo nel costruire un prodotto di qualità, e quest’ultima si ottiene nel lungo termine grazie a ciò che si scopre dai prototipi, dai rilasci in beta e dai veri e propri rilasci pubblici in produzione.

I bug vanno trattati come un risultato inevitabile che si scopre in un ciclo più lungo nel processo di sviluppo rispetto a quello delle singole iterazioni di lavoro.

Come scrivevo prima, però, è importante che il team sia focalizzato sulla qualità e che faccia tesoro dei problemi affrontati e dei bug risolti.

Solo in questo caso dovresti essere disposto a pagare i bug di tasca tua.

Per capire se è questo il caso, devi assicurarti che il team usi le tecniche e le pratiche corrette, che sono quelle che ho elencate precedentemente.

Mi riferisco, quindi, alla creazione dei test automatici con un’ampia copertura del codice scritto, all’utilizzo della continuous integration, al pair programming e così via.

Solo se il tuo prodotto è un colabrodo e il tuo team non segue queste pratiche orientate alla qualità dovresti rifiutarti di pagare i bug, e quindi sbarazzarti del team stesso.

Altrimenti, se il team sta lavorando in buona fede e ha adottato queste pratiche, devi considerare i bug come una parte essenziale dello sviluppo che si verifica a valle del lavoro iniziale.

E’ quindi essenziale disporre di un team di cui ti puoi fidare e adottare una mentalità aperta, comprendendo che non si può ottenere una garanzia implicita quando c’è un rilascio.

Altrimenti succede quello che mi è capitato più volte di vedere in prima persona, portando tra le altre cose a quella che si chiama “lenta marcia della morte”.

Mi riferisco a quei casi in cui ad un fornitore si chiede di pagare di tasca propria i bug, rimanendo peraltro nei tempi concordati, o ai propri dipendenti di fare gli straordinari magari gratis per sistemare i problemi, sempre rimanendo nei tempi pianificati.

Per esperienza posso garantire che in entrambi i casi ciò che si ottiene punendo il team (perché queste sono una forma di punizione e non semplici richieste) è il contrario di ciò che si pensa e non si fa altro che creare disaccordo.

Sempre rimanendo nella premessa che si sta avendo a che fare con un team credibile e non con degli incompetenti, si può dare per scontato che gli sviluppatori stiano usando le best practice e il proprio giudizio professionale per bilanciare la qualità con le esigenze delle consegne.

Quello che succede quando si penalizzano gli sviluppatori quando ci sono dei bug è che questo giudizio professionale viene compromesso perché in reazione poi si dà troppa importanza alla qualità.

Il risultato è che lo sviluppo procede in modo più lento, perché il team avrà paura delle conseguenze di altri errori ed esagererà con i test automatici andando ben oltre al proprio senso dei rendimenti marginali, cioè oltre al punto per il quale tale sforzo non vale la pena, risultando in costi eccessivi rispetto ai risultati.

Ho visto persone terrorizzate che dedicavano ore di analisi eccessivamente approfondite per evitare tirate di orecchie, con il morale a pezzi e un rendimento al minimo.

Un altro effetto collaterale è quello di incentivare di fatto il team a non cercare i bug in fase di sviluppo per non doverne dare evidenza, portando a problemi successivi ancora più gravi quando il software è in produzione e correggere le anomalie diventa molto più costoso.

In conclusione, per ottenere un prodotto di qualità bisogna accettare che ci saranno dei bug e che bisogna incentivare gli sviluppatori a trovarli e a metterli nel backlog, che è la scaletta di lavoro ordinata per priorità.

I bug vanno quindi trattati come gli altri task, vanno stimati quando è opportuno e vanno messi nel backlog come se fossero delle normali funzionalità da sviluppare ai quali dedicare tempo e risorse.

Per fare questo è importante lavorare con un team di persone capaci e finanziarlo per lasciargli dare il massimo nel costruire il tuo prodotto digitale.

Loading Facebook Comments ...
0 commenti

Lascia un Commento

Vuoi partecipare alla discussione?
Fornisci il tuo contributo!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *