Dall’archivio di MokaByte: questo articolo è stato pubblicato sul numero 226, marzo 2017
Partire da un… adesivo
In questo articolo voglio riproporre una riflessione già apparsa su LinkedIn [0] che prende le mosse da un fatto legato alla grafica e alla comunicazione. Da quando abbiamo stampato “Trust me, I’m a developer”, lo sticker è andato a ruba non solo tra gli sviluppatori di Intré [1] e Mia [2] ma anche tra i clienti; questo mi ha fatto riflettere su un tema: che cosa vuol dire essere un Developer affidabile?
Il developer nerd-supereroe che sconfigge i bug è simpatico e comunica in modo semplice e comprensibile un’idea precisa. Questo è sicuramente dovuto alla bravura di Giuseppe Ferrario, illustratore professionista di effigie.it [3] che ha saputo dosare i vari elementi del puzzle.
Le caratteristiche del developer
Ma che cosa c’è dietro questa immagine che comunica un’idea? Quali sono gli elementi che contraddistinguono un developer? Ci ho pensato su un po’ e ho messo insieme un elenco di caratteristiche che considero importanti per chi fa la nostra professione.
Prima di passare in rassegna i cinque punti che ho individuato, vorrei però fare una doverosa premessa: da un lato ci possono essere anche altri elementi da aggiungere all’elenco, che non è certo una “tavola della legge” incisa nella pietra. Dall’altro, il fatto di riconoscere come validi i punti riportati di seguito non significa necessariamente essere immediatamente capaci di rispettarli tutti quanti. La lista va presa come un possibile quadro complessivo a cui tendere.
Punto 1. Semplicità delle soluzioni
Pensare in modo complicato è una caratteristica di molti sviluppatori. È abbastanza naturale perché è meno faticoso complicarsi la vita che renderla semplice… Partire con una soluzione complicata e man mano cercare di renderla sempre più semplice può essere un buon compromesso. Io la chiamo: “massaggiare il codice fino a quando non si vede l’essenza”…
È un po’ come mettere in ordine la propria cantina ogni tanto: si inizia a buttar dentro roba ma bisogna stare attenti che poi non ci si capisce più nulla… per cui regolarmente si cerca di mettere ordine e buttare via le cose che non servono più. Lo stesso succede con il codice: si inizia con una cosa che funziona ma un poco farraginosa e poi a mano a mano si affina e si rende più funzionale ed elegante; si fa, cioè, refactoring. Ma non è né semplice né immediato: la semplicità è un’arte, come del resto recita anche l’Agile Manifesto.
Raffinare design e architettura
Per questo sono benvenuti i concetti di architettura e di design emergenti che si raffinano a mano a mano che il progetto si evolve. Un consiglio è quello di scegliere il proprio stile architetturale e poi essere aperti a evoluzioni laddove queste rendano sempre più semplice quello che si sta facendo; e insomma inutile fare overdesign fin dal principio, con concetti che non servono subito ma che potranno emergere sono nel corso dello sviluppo.
Attenti inoltre ai framework: anche se sembrano la soluzione più veloce, non sempre lo sono a lungo termine. Meglio adottarli laddove i pattern tipici del framework emergono durante lo sviluppo; altrimenti ci si trova vincolati per cose che non sono neppure utilizzate dal nostro codice!
Punto 2. Bilanciamento tra debito tecnico e valore di business
Quante volte avete lottato contro questa situazione? “Già che rilasci in produzione, metti anche questo, è molto importante, anzi di più: è vitale per gli utenti! Senza questo il rilascio che facciamo non serve a nulla…”.
Evitare queste situazioni è diventato quasi istintivo per un developer. Fare una patch al volo mentre si rilascia altro aumenta quasi sicuramente il debito tecnico e i rischi in produzione perché non si ha tempo per fare nulla se non mettere la patch e via. È così che si creano attriti tra devel e business con dibattiti senza fine. E le cose man mano peggiorano…
Calcolare il debito tecnico
Un developer invece deve essere in grado di affrontare queste situazioni in modo sistematico e oggettivo. Proviamo a riassumere il concetto di “oggettivo” con una formula.
Se, aggiungendo una patch al volo si aumenta di ∆D il debito tecnico e si migliora di ∆V il valore per l’utente finale e se ripagare l’incremento di debito tecnico ci costerà ∆R, allora la condizione
∆V – ∆D > ∆R
deve essere valida perché abbia senso il rilascio della patch.
Altrimenti si tratta solo di uno spreco di denaro e non conviene aggiungerla. Nessuno in azienda vuole buttar via i soldi e con un confronto oggettivo è più facile dialogare… Affinché la formula sia precisa, il concetto del debito tecnico dovrebbe prendere in considerazione anche il costo del ritardo, e magari ne riparleremo prossimamente.
Punto 3. Sviluppo guidato dai test
Siamo tutti d’accordo che testare sia importante. Se i test sono automatici tanto meglio. Siamo un po’ meno d’accordo che scrivere prima i test sia fondamentale. O meglio sulla carta siamo tutti d’accordo ma poi nella vita di tutti i giorni i fatti dimostrano il contrario… non ne facciamo abbastanza!
I vantaggi del TDD
Il Test Driven Development (TDD) non è solo una buona pratica di test ma è soprattutto una pratica per creare codice migliore. E quando diciamo codice migliore intendiamo dire che sia:
- chiaro da leggere, perché scrivere i test spinge a pensare meglio ai nomi, alle responsabilità e ai pattern;
- mantenibile più facilmente, perché il test è una rete di salvezza per chi poi metterà le mani sul codice dopo di voi;
- documentato, perché i test esprimono in modo chiaro e oggettivo le intenzioni del codice, meglio di qualsiasi altro documento scritto;
- semplice, perché il TDD si fa a piccoli passi incrementali e a ogni passo corrisponde anche il refactoring.
Unico problema, bisogna essere molto disciplinati per fare TDD. Per cui: esercitarsi, esercitarsi, esercitarsi e mettere in piedi da subito i test! La prima linea di codice che si scrive deve essere un test! Direte: “OK. Bello, ma poi non lo si fa…” e avete ragione; anch’io ogni volta me lo devo ripetere e imporre. Ma, quando lo faccio, i risultati sono evidenti e mi pento di non farlo tutte le volte che scrivo codice.
Punto 4. Rendere tutto automatico, fin dal primo giorno
Penso che tutti noi abbiamo provato almeno una volta nella vita il “brivido” di rilasciare in produzione. Ma quando questo brivido è vissuto più e più volte al giorno diventa uno stress. Errori, dimenticanze, configurazioni incompatibili sono solo alcune delle insidie che ci aspettano dietro l’angolo del rilascio. La soluzione? Automatizzare tutto e meglio ancora “Sviluppo guidato dagli automatismi”.
Come nel TDD, in cui scrivo i test e poi il codice, consiglio di scrivere gli automatismi da subito altrimenti poi diventa difficile scriverli e verificare che funzionino con una base di codice importante.
Le caratteristiche dello sviluppo guidato dagli automatismi
È questa la ragione per cui allo sprint zero è importante evitare attività manuali e automatizzare la hello world application implementata sulla vostra architettura di riferimento che abbia le seguenti caratteristiche:
- build automatica con aggiornamento di tutte le librerie da repository dei sorgenti (npm, maven o altro); no alla copia di librerie a mano;
- tutta la catena dei test up and running e non solo gli unit ma fino ai test in produzione;
- verifica statica del codice con linters che consentano di uniformare lo stile di coding e riducano errori di svista;
- implementazione di un’adeguata politica di branch; più semplice è meglio è: potete usare il trunk based development o i feature branches con merge su branch temporanei per verifica in modo che i feature branch non divergano ma abbiano vita breve o brevissima;
- implementazione della catena di continuous: integration, delivery e deploy;
- aggancio delle storie Done del backlog alle build per capire cosa viene rilasciato e quando;
- definizione di un’adeguata politica di versionamento del codice;
- aggancio in modo corretto al codice di loggers e analytics in modo da catturare fin da subito crash logs e dati di utilizzo del vostro software da parte degli utenti o degli altri sistemi (M2M).
La lista potrebbe essere più lunga. Potrei aggiungere per esempio la creazione automatica delle macchine con Ansible, Vagrant e Docker etc. Ma mi fermo… lo spirito è comunque chiaro: ogni volta che una cosa è automatizzabile, facciamolo!
Punto 5. Non “innamoriamoci” della tecnologia ma degli utenti!
Ultimo punto a me molto caro è la tecnologia; per quanto affascinante non lasciamoci affascinare dalle continue novità oppure non rimaniamo ancorati a quello che sappiamo, ma esploriamo sempre! Quando sia meglio osare e quando sia meglio non farlo è una sensibilità che contraddistingue un buon developer.
Un developer appassionato è curioso e tende a cercare sempre soluzioni innovative, eleganti e tecnologicamente avanzate. Questo approccio è molto positivo, da sostenere e incentivare ma con una sola attenzione… bisogna stare attenti a ben bilanciare l’innovazione con il beneficio per l’utente finale. Infatti è sempre bene ricordarsi che il software è uno strumento per risolvere i problemi degli utenti, non il fine.
Per questo una buona scelta tecnologica è tale quando questa non è percepita dall’utente. Con questa semplice regola diventa facile capire quando osare e quando rimanere conservatori. La tecnologia può semplificare, velocizzare e rendere maggiormente robusto un servizio digitale. Maggiore è l’innovazione tecnologica, maggiormente questi fattori sono esaltati.
Quindi un developer scrive ogni riga di codice soppesando se quella riga aiuta e semplifica la vita all’utente, server o client che sia. Se non lo fosse, allora, potrebbe essere una riga inutile.
Conclusioni
Abbiamo cercato di stilare un elenco di caratteristiche e pratiche utili a definire la figura di uno sviluppatore di qualità.
- Semplicità delle soluzioni
- Bilanciamento tra debito tecnico e valore di business
- Sviluppo guidato dai test
- Rendere tutto automatico, fin dal primo giorno
- Non “innamoriamoci” della tecnologia ma degli utenti!
Chiaramente si tratta di una lista migliorabile e ampliabile, ma che ci auguriamo abbia fornito qualche spunto per la riflessione e la discussione.
Buon codice a tutti!