D-Day: il giorno del rilascio
Ogni sviluppatore ha vissuto nella sua vita, almeno una volta, quella sensazione di palpabile tensione che si avverte nel Giorno del Rilascio. Tutti conosciamo le insidie dello sviluppo di un software e comprensibilmente temiamo il momento in cui questo comincerà a essere utilizzato, svelando i suoi difetti e, con essi, quelli del nostro lavoro.
Se siamo all’inizio della nostra carriera di sviluppatori, la paura del nostro primo rilascio potrebbe immobilizzarci, spingendoci a posporlo il più possibile. Se invece siamo sviluppatori esperti, sarà il fatalismo a farla da padrone: marceremo accigliati incontro al nostro destino e, se ci sarà da debuggare, si debuggerà!
In alcuni casi la preoccupazione per un rilascio è tale da toglierci il sonno la notte, o le notti, precedenti al fatidico Delivery Day. Siamo sicuri che debba essere veramente così?
La paura si vince con la conoscenza: si può forse dunque superare il timore del rilascio trasformando ogni giorno in un D–Day, e rendendo le procedure di rilascio una routine prevedibile ed eseguibile su richiesta. È qui che ci viene in aiuto la pratica del Continuous Delivery.
Are you a release candidate?
Il termine Continuous Delivery (CD) [3] acquisisce notorietà nel 2010 con la pubblicazione dell’omonimo libro [2] scritto da Jez Humble e David Farley. Facendo evolvere i concetti di Continuous Integration (CI) figli del pensiero dell’eXtreme Programming di fine anni Novanta, il Continuous Delivery si propone di portare cambiamenti di qualunque tipo — incluse nuove features, cambi di configurazione, fix di bugs ed esperimenti — in ambiente di produzione e, quindi, nelle mani degli utilizzatori finali, in modo sicuro, veloce e sostenibile.
In un processo di tipo tradizionale, infatti, dopo lo sviluppo del prodotto seguono una serie di attività volte a far sì che il software sviluppato diventi rilasciabile. L’idea alla base del Continuous Delivery invece è che il software sviluppato debba essere sempre rilasciabile. Ma come arrivarci?
Il punto di partenza è quello, tipico della metodologia Agile, di suddividere il lavoro in singoli requisiti rilasciabili autonomamente. Lo step successivo, concettualmente fondamentale, è l’integrazione continua di ogni singolo sviluppo: anziché posporre questa fase a un momento successivo, essa viene automaticamente eseguita con il commit. Si crea così un sistema di feedback che rileva se un cambiamento rompe il sistema o non rispetta i requisiti nel momento stesso in cui viene introdotto.
Il Continuous Delivery aggiunge un passo in più: dopo le fasi di build e test il software è automaticamente rilasciato in un ambiente di staging, analogo a quello di produzione, con gli stessi processi e strumenti. Il software prodotto secondo questa prassi, se supera tutti i passaggi e arriva all’ambiente di staging, è quindi di fatto già in condizione di poter essere rilasciato. Ogni cambiamento introdotto nel sistema in questo modo diventa dunque un release candidate, rilasciabile in produzione tramite una nuova versione del software.
È possibile portare questo processo al suo estremo, automatizzando anche quest’ultimo passaggio, senza l’intervento di una persona per l’approvazione della messa in produzione: è la pratica cosiddetta di Continuous Deployment [4].
I principi del Continuous Delivery
Tenendo ben presente questa concezione di release candidate, si possono identificare sei principi essenziali per garantire un processo di rilascio efficace e continuo:
- automatizzare quasi tutto;
- mantenere tutto in controllo versione;
- affrontare il “dolore” e costruire sulla qualità;
- “finito” vuol dire “rilasciato”;
- ognuno è responsabile;
- miglioramento continuo.
Vediamoli in dettaglio.
Automatizzare quasi tutto
Molti team di sviluppo non automatizzano il processo di sviluppo perché pare rischioso, complesso e time-demanding. La verità è che quasi tutto — processo di build, test di accettazione, upgrade e downgrade di database, configurazione di network e firewall, e molto altro ancora — può, con il giusto lavoro, essere automatizzato. L’automazione è il prerequisito per una pipeline di deployment che sia affidabile, ripetibile e semplice come premere un bottone.
Mantenere tutto in controllo versione
Ogni piccolo commit di codice, tutto ciò che usiamo per lo sviluppo, il test, il rilascio dei nostri applicativi deve essere conservato con un sistema di versionamento (Git, Subversion, Mercurial o qualsiasi altro VCS). Ogni change set dev’essere referenziato con un numero di versione, e dev’essere sempre possibile identificare quale build dei vari applicativi è rilasciata in un dato momento in ogni singolo ambiente, e da quale versione proviene.
Affrontare il “dolore” e costruire sulla qualità
Integration, test, release possono essere momenti dolorosi in un progetto. Per questo non vanno rimandati alla fine, ma anticipati il prima possibile ed eseguiti il più spesso possibile. Questo principio consente non solo di migliorare le competenze del team ma soprattutto di individuare subito i difetti del software e di poter intervenire prontamente per correggerli. Scrivendo codice coperto da test, quindi, si è automaticamente vincolati a scrivere buon codice: è così possibile arrivare al “Build Quality In”.
“Finito” vuol dire “rilasciato”
Uno dei più classici problemi nella definizione di un requisito, solitamente espresso sotto forma di user story, è la nozione di “finito”, anche chiamata Definition of Done: la lista di attività che devono essere portate a termine affinché il requisito possa dirsi completato e che deve soddisfare i criteri di accettazione. A ben guardare, però, una feature raggiunge il suo scopo solo nel momento in cui viene utilizzata dai suoi utenti: è uno dei motivi alla base del Continuous Delivery. Per eliminare ogni equivoco, dunque, in un processo di CD si considera finito solo ciò che è già stato rilasciato.
Ognuno è responsabile
Il rilascio di un software richiede tipicamente la collaborazione di più persone (developer, tester, operations team, PO…). Poiché non genera valore per il cliente finché non è rilasciato, il successo di un progetto è sempre un successo di team, mai individuale. Rendere le persone corresponsabili e incoraggiare la loro collaborazione è uno step fondamentale per ottenere rilasci più rapidi e più affidabili.
Miglioramento continuo
Proprio come il rilascio di un’applicazione è solo la prima fase della sua vita, che continuerà a evolvere, così anche il processo di rilascio deve essere continuamente e incrementalmente migliorato.
Un processo anche per le piccole realtà
A quasi dieci anni dall’uscita del libro di Humble, il Continuous Delivery è celebre per essere utilizzato in molte grandi aziende del mondo digitale come ad esempio Google o Yahoo. Il deployment engine di Amazon gestisce oltre 50 milioni di rilasci l’anno, mentre Facebook rilascia dai 500 ai 1000 cambiamenti al giorno.
Il CD non è tuttavia una questione di scala: è basato su un insieme di principi che possono essere trasformati in pratica in modo diverso ma con uguale successo a seconda del contesto in cui opera ogni team di sviluppo, anche in aziende di piccole dimensioni.
La nostra esperienza con Mia-Platform
Quel che raccontiamo di seguito non ha la pretesa di essere esaustivo; è il frutto dello studio e dell’esperienza maturate nella nostra realtà, Mia-Platform [7] un’azienda informatica che conta circa 40 sviluppatori. Questo articolo, infatti, nasce dalle riflessioni sul lavoro fatto dai nostri colleghi Tommaso Ballardini e Riccardo Porrini che hanno razionalizzato la loro esperienza diretta nel talk “It Starts With a Goal” [1]
Mia-Platform fornisce il proprio software a molte aziende differenti, che lo utilizzano per lo sviluppo di applicazioni che servono complessivamente milioni di utenti. Si pone dunque la necessità di conciliare i rilasci del proprio prodotto con gli sviluppi, gli aggiornamenti e la manutenzione degli applicativi dei clienti, ciascuno dei quali ha i propri tempi e le proprie esigenze.
Gestire una tale complessità non è banale: il processo di delivery tradizionale, che prevedeva build e test manuali, ci ha creato negli anni più di un grattacapo. Non era infrequente la situazione in cui, a seguito di un rilascio a fine giornata, ci si trovasse poi a dover riparare il software a orari improbabili, perché l’integrazione del software e il suo funzionamento non erano stati prima debitamente testati e verificati; talvolta addirittura si poteva incorrere in problemi perché non sempre l’immagine che era testata era poi la stessa che veniva rilasciata.
Le pratiche di CD adottate dal team
Uno dei nostri team, al lavoro su un progetto specifico, ha deciso in accordo con gli altri di sperimentare e portare all’interno del proprio percorso di rilascio alcuni principi di Continuous Delivery, trasformandoli in pratiche concrete adoperabili nel proprio contesto. Di seguito le vediamo una per una.
Obiettivi pianificati
La pianificazione stabilisce gli obiettivi di rilascio per ogni ciclo di lavoro, che ha una periodicità definita, tipicamente settimanale. Ogni mattina, poi, il team si aggiorna e condivide ciò che verrà sviluppato e rilasciato quel giorno. La board del team, fisica o digitale che sia, consente di tenere gli obiettivi sott’occhio, mantiene il team allineato e aiuta ad attuare il principio dell’“Everyone is Responsible”.
Pipeline di deployment automatica
Il codice sviluppato e versionato attiva una pipeline automatica di build, unit test e test di accettazione. Il Product Owner, interno al team, verifica subito i requisiti di accettazione del cliente e abilita il rilascio automatico in ambiente di staging, dove il software è sottoposto a un’ulteriore validazione. In modo continuo, nel corso di ogni sprint, durante le finestre di rilascio prestabilite, le feature pronte passano dall’ambiente di staging a quello di produzione, tramite un deployment automatico che viene azionato manualmente.
Finestre di rilascio
Non sempre il business servito — il cliente — rende possibile rilasciare in produzione in ogni momento. Analizzando il traffico e l’utilizzo da parte degli utenti è possibile individuare i momenti migliori per i rilasci a seconda delle esigenze specifiche. Le finestre temporali sono generalmente dipendenti dalle applicazioni e dal dominio applicativo — per esempio, macchine non disponibili in determinate fasce orarie — e comprendono sempre anche il tempo per eventuali rollback, come il re-deployment della versione precedente.
Small batches
Il batch work (accorpare insieme feature differenti, bug fixes, etc.) è nemico dei developer perché aumenta la possibilità di far fallire il rilascio. La complessità di merge infatti non aumenta linearmente rispetto alla quantità di codice rilasciato. Un’eventuale roll-back, inoltre, invalida tutto il lavoro fatto, incoraggiando il team a scomporre il lavoro in singole feature e procedere per cicli di sviluppo incrementali.
Versionamento rigoroso
Poiché si rilascia molto spesso in tutti gli ambienti, è fondamentale sapere sempre che cosa è rilasciato in ogni ambiente. Per questo ogni applicazione e servizio espone un proprio numero di versione.
I risultati ottenuti sono stati estremamente positivi: dopo un primo periodo di assestamento e di messa a punto del processo, il team ha incrementato in modo esponenziale il numero dei propri rilasci, che oggi sono anche varie decine al giorno.
Allo stesso tempo, i rilasci che causano rotture critiche sono pressoché scomparsi, perché i cambiamenti che rompono il sistema vengono automaticamente bloccati prima di arrivare in produzione.
Molti degli insegnamenti appresi da questo team sono diventati patrimonio comune e pratica condivisa anche per tutti gli altri team di Mia-Platform. Ogni singolo progetto software ha il proprio contesto e le proprie esigenze specifiche, e dunque non sempre è possibile estendere a tappeto i processi in modo uniforme; ma i principi alla base rimangono comunque validi per tutti e sono oggi un riferimento imprescindibile nel percorso di sviluppo dell’intera azienda.
In conclusione
I principi di Continuous Delivery, applicati nella pratica secondo il contesto in cui opera ogni team di sviluppo, consentono di sconfiggere la paura del rilascio e far evolvere il software in modo più rapido, semplice e affidabile. Anche grazie a questi principi oggi riusciamo a gestire l’intricata trama dello sviluppo di molteplici prodotti e applicativi, e vivere i rilasci come una normale routine.
Un buon processo di delivery, nella nostra esperienza, è automatico, è uguale per tutti gli ambienti, comprende anche le infrastrutture, prevede due step separati per build e deploy, è attivabile da chiunque all’interno di un team, segue un versionamento rigoroso e consente in modo continuo il rollback del software.
I costi principali risiedono nella scrittura dei test e nell’automazione dei processi, nella suddivisione dei progetti in singole feature da sviluppare, e nel tempo necessario alle persone per adattarsi al nuovo processo di sviluppo. Nessuno di questi costi dovrebbe essere un freno tale da scoraggiare questa strada, dati i numerosi benefici che essa comporta tanto per l’azienda come per i suoi clienti.