La sovra ingegnerizzazione di un prodotto digitale consiste nello scrivere più codice e in modo più strutturato di quanto serve realmente, comportando costi e tempi anche molto più elevati del previsto.
Oppure opportunità perse per chi si occupa di sviluppare progetti su commessa.
Certe volte costruiamo delle portaerei, quando basterebbe un battello.
In questa puntata spiego come un CTO deve gestire il team per evitare questo tipo di problema fin troppo frequente.
Il sito di cui si parla nella puntata si trova all’indirizzo www.teamcheckup.it
Clicca il tasto play nel player qui sotto per ascoltare subito questa puntata del podcast.
Trascrizione
Ciao da Alex Pagnoni e benvenuto nel podcast di CTO Mastermind, il podcast dedicato ai CTO e ai responsabili dei team di sviluppo, a chi vorrebbe diventarlo e a Founder e imprenditori digitali.
In questo episodio parlerò di un argomento che si verifica in molti team di sviluppo, sia quelli che lavorano alla costruzione del prodotto digitale della propria azienda che di quelli che lavorano ai progetti dei loro clienti, e cioè come evitare la sovra ingegnerizzazione nello sviluppo di un prodotto digitale.
Nella puntata precedente ho parlato delle situazioni in cui, per vari motivi, invece di creare un MVP un team di sviluppo consegna quello che di fatto è un prototipo, quindi un caso di sotto ingegnerizzazione.
Però nella realtà di tutti i giorni esiste anche il fenomeno inverso, cioè quello della sovra ingegnerizzazione, che può portare a grandi problemi di costi, tempi e prestazioni di ciò che si sviluppa.
E per sovra ingegnerizzazione intendo la situazione in cui si sviluppa più codice o si costruisce più infrastruttura di quello che serve realmente per raggiungere gli obiettivi, un problema questo che è sia di management che di team di sviluppo e che va quindi affrontato da più punti di vista.
Il punto è che la sovra ingegnerizzazione corrisponde a codice che risolve problemi che non hai realmente o che potresti avere ma che nella realtà poi spesso non si verificano quasi mai, mentre so per esperienza che il problema della sovra ingegnerizzazione non è un’eccezione ma è piuttosto la norma.
Devo dire che trovare un equilibrio non è facile, in più il concetto di sovra ingegnerizzazione tende ad essere soggettivo.
In termini generali, possiamo trovarlo questo equilibrio accettando il fatto che buono abbastanza è meglio di perfetto, adottando quel livello ottimale di qualità e buone pratiche che consentono di ottenere comunque un prodotto funzionante, mantenibile e idoneo ad essere migliorato nel tempo.
Quindi il prodotto a livello tecnico non deve essere per forza il migliore, ma neanche il peggiore.
Piuttosto, bisogna adottare alcuni design pattern e un paio di principi dell’Extreme Programming che sono lo YAGNI, sigla che sta per “You Ain’t Gonna Need It”, cioè “non ne avrai bisogno”, e il refactoring.
Questo perché una delle cause di questo problema è proprio quello di aggiungere meccanismi, astrazioni e caratteristiche pensando proprio nell’ottica che potrebbe in futuro esserci bisogno, quando non è così.
Quindi, dando per scontato di disporre di un team di sviluppatori che conoscono le buone pratiche dello sviluppo, un CTO o un Manager dovrebbero chiedere al proprio team di sviluppare quanto basta per risolvere i bisogni e le esigenze attuali, con un livello adeguato a soddisfare clienti e utenti.
Se poi emerge la necessità di cambiare qualcosa o migliorarne la struttura, allora la strada è quella del refactoring incrementale.
Chiaramente qui l’esperienza è fondamentale e uno sviluppatore senior ha certamente in mente le conseguenze della sovra ingegnerizzazione.
Andando però un po’ più sotto alla superficie dell’intera questione, possiamo vedere la cosa da due punti di vista, quello dei requisiti e quello della soluzione a quei requisiti.
Molte volte il problema è appunto proprio quello dei requisiti.
Questo perché invece di iniziare ad implementare una soluzione e a sviluppare codice, il CTO e gli sviluppatori che ci lavorano dovrebbero fare un passo indietro e guardare alla radice del requisito chiedendone il perché, cioè la ragione d’essere.
Sicuramente lavorare usando il metodo delle user stories aiuta, anche se spesso si vedono user stories che altro non sono che una trasposizione della classica descrizione di una feature in formato di storia, senza identificarne correttamente gli utenti (che nella user story vengono spesso chiamati solo genericamente “utenti”, che è un errore fondamentale), e soprattutto senza identificare l’ultima parte che è quella relativa al beneficio che deve ottenere il rispettivo utente di quella user story.
Quindi, per ridurre il rischio di introdurre della sovra ingegnerizzazione dobbiamo comprendere pienamente il problema, e per capire questo problema dobbiamo chiarire il più possibile i requisiti chiedendo appunto “il perché” al committente.
Poi il tutto va chiaramente contestualizzato al disegno complessivo, perché la soluzione ad un requisito del tipo “aggiungere un bottone” potrebbe essere semplicemente scriverne il codice HTML ma anche utilizzare un framework o Angular se il tutto fa parte di un sistema più grande.
Uno sviluppatore potrebbe tranquillamente dire che la strada corretta è la prima mentre un altro potrebbe dire che quella corretta è la seconda, e in un certo senso hanno ragione tutti e due.
E’ in questo senso che affermo che il tema della sovra ingegnerizzazione è soggettivo e solo estraendo dal committente il disegno complessivo di ciò che va sviluppato si può ridurre questa soggettività.
Ma anche facendo così, qualcuno potrebbe dire che costruire delle fondamenta più solide è meglio che costruire una soluzione per così dire più “smart” ma meno raffinata che potrebbe avere più problemi nel lungo termine di un’implementazione che apparentemente sembra sovra ingegnerizzata.
E qui torniamo al concetto che una soluzione a questo specifico problema è proprio quella di seguire le tecniche dell’Extreme Programming come YAGNI, il TDD in cui si sviluppa solo ciò che serve a passare i test e infine la tecnica del refactoring.
Solo in questo modo eliminiamo il fatto della soggettività, perché avere codice testabile e testato è la più grande garanzia che scriviamo solo il codice necessario ma scritto in modo tale che si può ristrutturare.
Quindi un CTO o un responsabile di un team di sviluppo dovrebbe introdurre e agevolare il più possibile questi concetti all’interno del proprio team per ridurre la portata del problema.
L’altro aspetto parallelo a quello dei requisiti è poi quello della soluzione ai requisiti, cioè a come si sviluppa.
E qui la considerazione base è che una fetta di sovra ingegnerizzazione deriva dal fatto che agli sviluppatori martelliamo di continuo in testa l’importanza di progettare e architettare in modo appropriato il codice con vari design pattern e principi come quelli SOLID, e io sono il primo in tal senso, però una questione è farlo applicando il buon senso e un’altra è passare da un estremo all’altro.
In sostanza, agli sviluppatori abbiamo fatto una testa così dicendogli di strutturare bene il codice e alcuni sono anche rimasti scottati e magari rimproverati per aver scritto codice diciamo scadente, che per reazione poi passano all’opposto e lo scrivono troppo strutturato.
Qui bisogna capire che i design pattern e in generale i principi di sviluppo del software girano attorno al concetto di far sì che il codice sia facile da modificare e adattare.
Ricollegandomi al discorso requisiti, abbiamo infatti la certezza matematica che i requisiti in qualsiasi progetto cambieranno di continuo e ciò richiede ai tuoi sviluppatori di rimetter mano al codice originale e fare refactoring per implementare il nuovo requisito.
A sua volta però spesso la regola di rendere il codice facile da cambiare rende più difficile l’altra regola aurea di rendere il codice facile da capire, così come spesso il codice facile da leggere e comprendere è difficile da cambiare, non sempre ma spesso è così.
E quando il team di sviluppo procede col refactoring, inevitabilmente in molti casi il codice diventa più complesso.
Anche qui la soluzione è quella dello YAGNI.
E’ inutile progettare codice che fa da astrazione tra ad esempio MariaDB e PostgreSQL, quando nel fare ciò introduciamo uno strato che rallenta tutto e rende gioco forza meno potente ciò che possiamo fare perché eliminiamo i vantaggi peculiari di ciascun database.
In questi casi la duplicazione è migliore rispetto ad un’astrazione sbagliata.
Non vado oltre scendendo in ulteriori esempi e dettagli tecnici che portano ad avere sovra ingegnerizzazione , perché il mio messaggio è che quando è possibile bisogna seguire il principio KISS, cioè Keep It Simple Stupid.
Solo quando si è sicuri che una certa parte di codice potrebbe richiedere future modifiche per via di requisiti nuovo o che cambiano, allora bisognerebbe pensare a fare refactoring per rendere il codice più adatto ai cambiamenti, altrimenti è meglio lasciare tutto il più semplice possibile.
Allo stesso modo non per forza ci serve un’architettura a microservizi o un’infrastruttura su Kubernetes, quando il problema è più semplice della complessità introdotta nel risolverlo.
Siamo arrivati alla fine del podcast e ti ringrazio per aver ascoltato questa puntata.
Se vuoi saperne di più sull’argomento di oggi o vuoi riportare la tua esperienza, puoi scrivere nel gruppo Facebook del podcast cercando CTO Mastermind su Facebook.
Se invece hai bisogno di una mano ad approfondire il tuo prodotto o servizio digitale per verificare se anche nel tuo caso c’è un problema di sovra ingegnerizzazione, oppure se vuoi un affiancamento per te stesso o per il tuo team di sviluppo o hai bisogno di un aiuto specializzato per fare refactoring del tuo codice, puoi richiedere l’apposito servizio di Check Up di Axelerant.
Nei prossimi episodi porterò avanti tra gli altri l’argomento del refactoring che ho citato anche oggi, per capire quando è meglio ristrutturare un’applicazione già esistente o quando è meglio riscriverla da capo, questione questa che dà filo da torcere a molti CTO e aziende.
Grazie di nuovo e alla prossima puntata, ciao da Alex.
]]>