L‘argomento dell‘articolo puntualizza come gli attori componenti del team di sviluppo software devono interagire con il sistema di versionamento. L‘articolo si concentra sulle modalità operative che lo sviluppatore deve osservare per garantire che il prodotto su sistema di versionamento sia sempre in uno stato di consistenza operativa, a prescindere dal prodotto di versionamento che viene utilizzato nel progetto.
Introduzione
L‘argomento dell‘articolo tocca uno dei punti solitamente più sottovalutati nei passi per la costruzione di un progetto software di valore: come gli attori componenti del team di sviluppo software devono interagire con il sistema di versionamento. L‘articolo si concentra sulle modalità operative che lo sviluppatore deve osservare per garantire che il prodotto su sistema di versionamento sia sempre in uno stato di consistenza operativa, a prescindere dal prodotto di versionamento che viene utilizzato nel progetto.
Senza la dovuta attenzione, il sistema di versionamento rischia di essere utilizzato come un repository di file alla stregua di un file system condiviso, dimenticando che il sistema di versionamento è un mezzo per tracciare in ogni istante la storia del proprio software ricostruendone l‘evoluzione e lo stato.
Scenario: sviluppo software e sistema di versionamento
La definizione di un progetto software si articola in una serie di passi che si articolano fra scenari e attori diversi. In breve si passa dall‘acquisizione dei requisiti utente, alla comprensione e stesura degli stessi, alla definizione dei casi d‘uso, al disegno architetturale, allo sviluppo delle classi e delle componenti, allo sviluppo dei casi di test, al deploy, al passaggio del software nei vari ambienti di esercizio, alla manutenzione e… ho finito il fiato.
In sostanza scenari complessi che con le nuove pratiche agili di progettazione e realizzazione software si rincorrono in un percorso articolato e dagli equilibri delicati.
Il “repository” del software
In ultima analisi, la realizzazione di un progetto software prevede la creazione di un insieme di artefatti o “oggetti software” il cui ciclo evolutivo deve essere gestito. Gli elementi che compongono il software devono essere sottoposti al controllo di versione, e il ciclo di vita di questi oggetti dallo sviluppo all‘esercizio deve essere ben definito e regolamentato (prima con un processo chiaro, al limite supportato da tool specifici).
Operativamente tutto quello che concorre al funzionamento del prodotto (sorgenti, configurazioni, script vari, etc.) va sottoposto a controllo di versione e, in modo figurato, compone una linea evolutiva del progetto.
Figura 1 – Dal workspace al sistema di versioning
Normalmente su questa linea di sviluppo si concentra l‘interesse di più figure coinvolte nello sviluppo software: dagli sviluppatori che creano e modificano i sorgenti del progetto, a chi si occupa degli script di build e deploy, e di riflesso chi si occupa di definire le milestones di progetto.
Caratteristiche della linea di sviluppo
In generale, il modello di gestione del codice supportato da un dato sistema di versionamento offre ai vari elementi o una politica di accesso esclusivo, o una politica di accesso concorrente.
Per accesso esclusivo si intende che un solo sviluppatore ha la possibilità di modificare un elemento in un determinato momento. L‘accesso esclusivo viene ottenuto attraverso un‘operazione di check-out con lock sul elemento. Mentre un elemento è concesso esclusivamente a uno sviluppatore, gli altri possono accedere all‘ultima versione presente sul repository in modalità sola lettura. Al termine delle modifiche, il programmatore riporta sul repository la versione modificata attraverso un‘operazione di check-in. Il codice è ora disponibile nella nuova versione, gli altri sviluppatori lo includeranno al successivo aggiornamento.
Per accesso concorrente si intende un contesto in cui gli sviluppatori possono accedere in maniera concorrente agli elementi versionati, modificarli e aggiornarli, con l‘accortezza di lavorare su di una versione aggiornata. Al momento di rendere disponibili le proprie modifiche agli altri sviluppatori (operazione di commit che fa il paio con il check-in), il sistema evidenzia gli eventuali conflitti provocati da accessi concorrenti sulla stessa porzione di codice, impedendo l‘aggiornamento sul repository della classe in cui il conflitto si è verificato. Una volta risolti localmente i conflitti, si può riportare la versione sul repository.
Uno scenario di questo genere, tipico dei progetti open source, ha vantaggi nel caso di gruppi di sviluppo numerosi o molto distribuiti, in quanto sposta il coordinamento necessario per le modifiche agli stessi files più avanti nel tempo. Di contro, presuppone una maggiore conoscenza dello strumento di versioning e delle politiche di funzionamento perché risulta meno protettivo rispetto ad accessi indiscriminati.
Livelli di integrità del software in versionamento
Un sistema di controllo di versione non è un semplice strumento di backup, ma ha proprietà e modalità d‘uso strettamente legate alle caratteristiche degli elementi contenuti. Un prodotto software complesso è un‘entità con proprietà particolari di cui si deve tenere conto nelle modalità d‘uso del prodotto.
Un insieme di sorgenti presente sul repository può in generale appartenere ad uno di questi stati:
- INFORME: il repository è usato alla stregua di un disco condiviso, i sorgenti sono semplicemente accumulati.
- COMPILABILE: l‘insieme dei sorgenti presenti sul repository è compilabile (dove per compilabilità si intende che il codice si possa compilare rispetto agli script di compilazione o meccanismi di build implementati nella struttura di build management).
- FUNZIONANTE: i sorgenti nel loro complesso possono essere compilati e fornire un eseguibile in grado di svolgere un set di compiti verificabili (dove per verificabile si intende che il codice si possa verificare rispetto ad una suite di test appositamente creata, che rispettano un‘architettura di verifica ben determinata).
Ognuno di questi stati è in genere rappresentativo di diversi momenti della storia di un software. Durante la fase iniziale di un progetto si possono allentare i vincoli; per evitare fastidiosi contrattempi, ad esempio durante la fase di sviluppo, ci si attesta su una politica di mantenimento del sorgente nel repository almeno in condizioni di compilabilità .
È utile sottolineare che uno specifico livello di integrità del codice può essere mantenuto solo se tutti gli sviluppatori, facenti parte del team di progetto, si adeguano a una determinata politica. È sufficiente l‘uso indiscriminato della risorsa da parte di un solo componente del team per distruggere quanto costruito dagli altri.
Lo sviluppo software: dinamiche di sviluppo
Di seguito di illustrano i passi le corrette modalità di interazione dello sviluppatore con il sistema di versionamento; di contro non si farà alcun cenno sulla modalità con cui ogni singolo sviluppatore implementa un particolare caso d‘uso a lui assegnato.
Configurare il proprio workspace
A seconda che si tratti di uno sviluppo evolutivo o di uno sviluppo manutentivo si dovrà provvedere alla creazione, nel proprio workspace, della corretta condizione del software (sorgenti, configurazioni di ambiente, librerie, ecc.) su cui lavorare. Lo sviluppatore sincronizza la macchina di sviluppo con il sorgente su cui lavorare, caricando sul proprio workspace il software dal sistema di versionamento. Una volta caricati nel proprio workspace tutti i file di lavoro, e dopo aver configurato l‘ambiente per poter funzionare (configurazione dell‘application server, configurazione delle connessioni a DB, eventuali configurazioni dipendenti dall‘ambiente, etc.), si può procedere allo sviluppo.
Figura 5 – Creazione del workspace sulla macchina di sviluppo
Check-out esclusivo dei file su cui si prevede di lavorare
Lo sviluppatore prende in checkout i file su cui deve eseguire l‘intervento. Il checkout esclusivo eviterà che qualcun altro possa mettere mano agli stessi file. In questo senso è il caso che il checkout dei file avvenga su singole entità ben definite con una logica di “stretta necessità “; tale comportamento evita di creare eccessivi lock su sorgenti senza alcuna necessità . Per essere chiari, se si deve procedere alla modifica di una singola classe, non ha senso prendere in check-out tutto il progetto.
Figura 6 – Check-out puntuale delle realtà soggette a modifica
Check-in a lavoro finito
Una volta realizzate le modifiche sui sorgenti si può consolidare il software su repository. Il processo di consolidamento prevede il rilascio sul repository dei file in check-out ed eventualmente l‘aggiunta al processo di versioning di nuovi file sviluppati. Il processo deve essere affrontato con la dovuta accortezza in quanto si sta procedendo all‘allineamento di un qualcosa di condiviso.
A questo punto lo scenario si configura con un workspace locale che possiede una situazione dei sorgenti verosimilmente diversa rispetto alla baseline, perché è realistico pensare che altri sviluppatori abbiano apportato modifiche su codice non necessariamente dipendente da quello usato dal nostro sviluppatore protagonista. Se si procede con un check-in senza le dovute accortezze, è probabile che sul repository si abbia un codice NON compilabile, contravvenendo ai requisiti di minima.
Attenzione! Non si può lasciare al caso la modalità di allineamento del repository con il software nuovo o modificato, perché si possono provocare situazioni di non compilabilità del software provocando ritardi e contrattempi nel processo di sviluppo a tutto il gruppo di lavoro che si appoggia alla medesima linea di versionamento.
La modalità migliore per procedere all‘allineamento del codice prevede i seguenti passi:
- sincronizzare il sorgente su workspace locale con quanto sta sul repository;
- verificare che non esistano incompatibilità di sorta (problemi di compilazione in primis e test ko in secondo luogo) ed eventualmente sistemarle in locale;
- se la sistemazione ha richiesto un lungo periodo di intervento conviene ripetere il punto 1, altrimenti si procede verso il punto 4;
- realizzare il consolidamento del nuovo codice (check-in).
Passi per la politica del check-out concorrente: eseguo il commit
Nel caso il sistema di versionamento sia configurato per supportare la politica di check-out non esclusivo, le operazioni che si devono compiere all‘atto del commit del codice sono le medesime (1, 2, 3 e 4). Sarà il sistema di versionamento che effettuerà un controllo sul codice modificato e avviserà l‘utente se l‘operazione di modifica ha creato dei potenziali disallineamenti su codice modificato e che un altro attore ha precedentemente consolidato. A questo punto si dovrà procedere alla risoluzione locale dei conflitti con un lavoro di merge. L‘operazione di merge non è sempre semplice e scontata per cui, nel caso alcune situazioni non siano chiare, è bene rapportarsi all‘ultimo autore del sorgente su repository per capire come procedere nella fase di merge.
Una volta risolti in locale i contrasti si può procedere al commit del file, secondo i passi descritti nel paragrafo precedente che non produrranno a questo punto incompatibilità di sorta sui singoli file.
Conclusioni
I prodotti di versionamento sul mercato consentono il trattamento di un insieme di informazioni che garantiscono il soddisfacimento delle esigenze dei vari progetti. Qualsiasi prodotto però ha la necessità di essere correttamente utilizzato e configurato. Oltre a una corretta modalità di utilizzo, sono necessarie anche la definizione delle entità da porre sotto controllo di versionamento e le politiche secondo cui queste entità devono essere gestite. È chiaro che queste situazioni sono da affrontare in una fase iniziale del progetto e devono essere unite a un corretto processo di formazione degli utenti che partecipano al processo di sviluppo, nel caso che lo si ritenga utile.
Infatti uno scorretto utilizzo del sistema da parte degli sviluppatori, ad esempio, può creare ritardi nello sviluppo, problemi nel bug fixing, impossibilità di supportare processi agili di integrazione continua.
L‘articolo illustra qual è la corretta modalità di interazione fra lo sviluppatore e il sistema di versionamento, ponendo l‘attenzione su scenari differenti. Altre situazioni sono da affrontare ed approfondire; è solo un inizio, ma, come si dice, “chi ben comincia è a metà dell‘opera”.