Indice
Questo capitolo parla di come i progetti di software libero confezionano e rilasciano i loro software e di come si organizzano le procedure generali di sviluppo su questi obiettivi.
Una differenza principale fra i progetti open source e quelli proprietari è il difetto di un controllo centralizzato sul team di sviluppo. Quando sta venendo preparata una nuova release, questa differenza è specialmente forte: una compagnia può richiedere al suo team di sviluppo di focalizzarsi sula prossima release, mettendo da parte lo sviluppo di nuove funzionalità e la correzione di bugs non critici fino a che il rilascio non è avvenuto. I gruppi di volontari no sono così monolitici. La gente lavora al progetto per tutti i tipi di motivazioni, e quelli non interessati a favorire una data release vogliono continuare il lavoro di sviluppo mentre la release sta andando avanti. Poiché lo sviluppo non si ferma, i processi di rilascio tendono a impiegare più tempo, ma sono meno distruttivi, dei processi di rilascio commerciali. Questo è in po' come ritrovare la strada maestra. Ci sono due modi di riparare una strada: potete chiuderla completamente, così che il gruppo che sta riparando la strada maestra può sciamare su di essa alla piena capacità finché il problema è risolto, o potete lavorare su una coppia di corsie alla volta, lasciando le altre aperte al traffico. Il primo modo è molto efficace per il gruppo di riparazione, but not for anyone else—ma non per gli altri la strada è chiusa completamente fino a che il lavoro non è completato. Il secondo modo richiede molto più tempo comporta più problemi per il gruppo di riparazione (ora essi devono lavorare con meno gente e meno equipaggiamento, in condizioni più ristrette, con bandiere per rallentare e dirigere il traffico, ecc..), ma almeno la strada rimane utilizzabile, sebbene non con la sua piena capacità.
I progetti open source tendono a funzionare nel secondo modo. Infatti per un pezzo di software maturo con diverse linee di rilascio mantenute simultaneamente, il progetto è un genere di stato di permanente riparazione di una strada. C'è sempre una coppia di corsie chiuse ma un basso livello di inconveniente di fondo vien sempre tollerato dal gruppo di sviluppo nel complesso, cosicché le release vengono effettuate con una programmazione regolare.
Il modello che rende ciò possibile si estende a più che una sola release. E' il principio di mettere in parallelo operazioni che non sono mutualmente interdipendenti un principio che non è in nessun modo unico dello sviluppo open source, certamente, ma è un principio che i progetti open source implementano fra propri in particolar modo. Essi non possono permettersi di infastidire molto sia il gruppo di lavoro sulla strada sia il regolare traffico, ma non possono permettersi anche di avere gente dedita a fare affidamento sui coni arancione e a fare segnalazioni lungo il traffico. Così essi sono attratti da processi che hanno piatti, costanti livelli di spese generali amministrative, piuttosto che picchi e valli. I volontari vogliono generalmente lavorare con piccoli ma consistenti quantità di incomodo. La prevedibilità permette loro di venire e andare senza senza preoccuparsi se il loro programma contrasterà con ciò che sta avvenendo nel progetto. Ma se il progetto fosse soggetto a un importante programma in cui alcune attività escludessero altre attività, il risultato sarebbe un sacco di sviluppatori seduti a oziare per un sacco di tempo la qualcosa sarebbe non solo inefficiente ma tediosa, e quindi dannosa, in quanto uno sviluppatore annoiato è equivalente presto a un ex sviluppatore.
Il lavoro di release è usualmente la più notevole operazione che avviene in parallelo con lo sviluppo, così i metodi descritti nella prossima sezione sono per lo più attrezzati a rendere possibili le releases. Comunque notate che essi si applicano anche ad altre operazione eseguibili in parallelo, come la traduzione e l'internazionalizzazione, grandi cambiamenti alle API fatti generalmente lungo tutto il codice base, ecc..
Prima di parlare di come fare una release, vediamo come chiamare una release, che vuol dire sapere veramente cosa significa per un utilizzatore. Una release significa che:
I vecchi bugs sono stati corretti. Questa è probabilmente l'unica cosa sulla cui verità gli utilizzatori possono contare.
Nuovi bugs si sono aggiunti. Questa è anche una cosa su cui si può contare, tranne a volte nel caso di releases di sicurezza o di altre cose che avvengono una sola volta (vedere sezione chiamata «Le Releases di Sicurezza» più avanti in questo capitolo).
Nuove funzionalità possono essere state aggiunte.
Nuove opzioni di configurazione possono essere state aggiunte, o il fine delle vecchie opzioni può essere stato cambiato di poco. Le procedure di installazione anche possono essere cambiate sin dalla ultima release, sebbene uno speri di no.
Possono essere stati introdotti cambiamenti incompatibili, sicché alcuni formati di dati usati dalle versioni più vecchie non sono più utilizzabile senza sopportare qualche sorta di (possibilmente manuale) passo a senso unico.
Come potete vedere non tutte queste cose sono buone. Questo è il motivo per cui utilizzatori di esperienza si avvicinano alle nuove releases con qualche apprensione, specialmente quando il software è maturo e stavano già per la maggior parte facendo quello che volevano (o pensavano quello che volevano). Anche l'arrivo di nuove funzionalità è una benedizione di diversa specie, in quanto può significare che il software si comporterà ora in maniera imprevista.
Lo scopo della numerazione delle versioni, quindi, è duplice: ovviamente dovrebbero comunicare senza ambiguità l'orine delle releases (cioè, guardando a una di due releases, uno può sapere quella che viene dopo), ma anche dovrebbe indicare in modo quanto più compatto possibile il grado e la natura dei cambiamenti nella release.
Tutto questo in un numero? Si, più o meno, si. La strategia della numerazione delle releases è una delle più vecchie superflue discussioni qua e là (vedere sezione chiamata «Più semplice l'argomento, più lungo il dibattito» in Capitolo 6, Comunicazione), ed è improbabile che il mondo pattuisca un unico completo standard molto presto. Comunque poche buone strategie sono emerse, insieme a un principio su cui si è universalmente d'accordo: essere in armonia. Scegliete uno schema di numerazione, documentatelo, e seguitelo. I vostri utilizzatori vi ringrazieranno.
Questa sezione descrive le convenzioni formali della numerazione delle releases, e presuppone, una piccola precedente conoscenza. Se già avete familiarità con queste convenzioni, potete saltare questa sezione.
I numeri delle releases son gruppi di cifre separate da punti:
Scanley 2.3
Singer 5.11.4
...e così via. I punti non ono punti decimali, essi sono solamente separatori; "5.3.9" sarebbe seguito da "5.3.10". Pochi progetti hanno fatto intendere diversamente, il più famoso il kernel Linux con la sua sequenza "0.95", "0.96"... "0.99" leading up to Linux 1.0, ma la convenzione che i punti non sono decimali è fermamente stabilita e deve essere considerato uno standard. Non c'è un limite al numero dei componenti (parti di cifre non contenenti il punto), ma la maggior parte dei progetti non va oltre tre o quattro. La ragione diventerà chiara avanti.
In aggiunta a componenti numerici i progetti a volte aggiungono un'etichetta descrittiva tipo “Alpha” o “Beta” (vedere Alpha e Beta), per esempio:
Scanley 2.3.0 (Alpha)
Singer 5.11.4 (Beta)
Un qualificatore Alpha o Beta significa che quella release precedeuna futura release che avrà lo stesso numero senza il qualificatore Così, "2.3.0 (Alpha)" porta alla fine a "2.3.0". Per far entrare queste release candidate in una riga, gli stessi qualificatori posso avere dei meta-qualificatori. Per esempio qui c'è una serie di releases che sarebbero rese disponibili al pubblico:
Scanley 2.3.0 (Alpha 1)
Scanley 2.3.0 (Alpha 2)
Scanley 2.3.0 (Beta 1)
Scanley 2.3.0 (Beta 2)
Scanley 2.3.0 (Beta 3)
Scanley 2.3.0
Notate che quando essa ha il qualificatore “Alpha” Scanley "2.3" si scrive "2.3.0". I due numeri sono equivalenti—tutti i componenti 0 seguenti possono sempre essere eliminati per brevità ma quando un qualificatore è presente, la brevità smette di esistere comunque, come pure uno potrebbe scegliere la completezza invece.
Altri qualificatori semi regolari usano includere “Stabile”, “Instabile”, “Sviluppo” e “RC” (per “Release Candidate”). Le più largamente usate sono comunque "Alpha" e "Beta", con “RC” che concorre da vicino per il terzo posto, ma notate che “RC” include sempre un meta-qualificatore numerico. Cioè non rilasciate "Scanley 2.3.0 (RC)", voi rilasciate "Scanley 2.3.0 (RC 1)", seguita dalla RC2, etc.
Queste tre etichette “Alpha”, “Beta” e “RC” sono piuttosto largamente conosciute ora, e raccomando di non usare le altre, anche se a prima vista sembrano scelte migliori perché sono parole normali, non gergo. Ma la gente che installa software da release ha già familiarità con quelle tre, è non c'è motivo per fare cose gratuitamente in modo differente dal modo in cui chiunque altro le fa.
Sebbene i punti nei numeri delle realases non siano punti decimali, indicano un significato del valore della posizione. Tutte le realeases "0.X.Y" precedono la "1.0" (che è equivalente alla “1.0.0”, certo). La"3.14.158" precede immediatamente la "3.14.159" e non immediatamente precede la "3.14.160" come la "3.15.qualcosa", e così via.
Una politica di numerazione delle releases rende capace l'utilizzatore di di guardare ai numeri di rilascio per lo stesso pezzo di software e dire, proprio dai numeri, le importanti differenze fra queste due relaeases. In un tripico sistema a tre componenti il primo componente è il numero maggiore, il secondo è il il secondo è il numero minore, il terzo è il micro numero. FPer esempio, la release "2.10.17" è la diciassettesima micro-relaese nella decima linea di release minore entro la seconda serie di release maggiore. Le parole “linea” e “serie” sono usate informalmente qui, ma significano ciò che uno si aspetterebbe. Una serie maggiore sono semplicemente tutte le releases che hanno in comune lo stesso numero maggiore, e una serie minore (o linea minore) sono semplicemente tutte le releases che hanno in comune lo stesso numero maggiore e lo stesso numero minore. Cioè la "2.4.0" e la "3.4.1" non si trovano nella stessa serie minore anche se ambedue hanno “4” come numero minore; d'altra parte la "2.4.0" e la "2.4.2" si trovano nella stessa linea minore, sebbene non siano adiacenti se la “2.4.1” è stata rilasciata fra di esse.
Il significato di questi numeri è esattamente ciò che vi aspettereste: un aumento del numero maggiore indica che il cambiamento maggiore è avvenuto; un cambiamento del numero minore indica che sono avvenuti cambiamenti minori, e un cambiamento del micro numero indica cambiamenti trascurabili. Alcuni progetti aggiungono un quarto componente, usualmente chiamato numero di patch, specialmente per un un controllo più fine sulle differenze fra le loro releases (in maniera disorientante, altri progetti usano “patch” come sinonimo di “micro” in un sistema. Ci sono anche progetti che usano un sistema a tre componenti). Ci sono anche progetti che usano l'ultimo componente come numero di fabbricazione, incrementato ogni volta che il software è costruito, e non rappresenta nessun cambiamento al di fuori dell'allestimento. Ciò aiuta il progetto a mettere in relazione ogni rapporto di bugs con uno specifico allestimento, ed è forse molto utile quando i pacchetti binari sono il metodo di distribuzione di default.
Sebbene ci siano molte differenti convenzioni su quanti componenti usare, e cosa significhino i componenti, le differenze tendono a diventare piccole, voi tenete una piccola tolleranza, ma non troppo. Le prossime sue sezioni parlano delle due convenzioni più largamente usate.
La maggior parte dei progetti ha delle regole su che tipo di cambiamenti sono permessi nella release se uno sta incrementando solo il micro numero, differenti regole per il numero minore e ancora differenti regole per il numero maggiore. Non c'è uno standard stabilito per queste regole ancora, ma qui io descriverò una politica che è stata usata con successo da più di un progetto. Voi potete giusto adottare questa politica nei vostri porgetti, ma anche se non lo volete, questo è tuttavia un buon esempio del tipo di informazione che i numeri di release dovrebbero portare con sé. Questa politica è adattata dal sistema di numerazione usato dal progetto APR, vedere http://apr.apache.org/versioning.html.
I cambiamenti dei micro numeri (cioè i cambiamenti alla stessa linea minore) devono essere sia in avanti compatibili che indietro compatibili. Cioè, i cambiamenti dovrebbero essere solo le correzioni di bugs o accrescimenti molto piccoli delle funzionalità esistenti. Nuove funzionalità non dovrebbero essere introdotte in una micro release.
Cambiamenti del numero minore (cioè entro la linea maggiore) devono essere compatibili all'indietro, ma non necessariamente in avanti. E' normale aggiungere nuove funzionalità ad una release minore, ma non troppe in un sola volta.
I cambiamenti al numero maggiore segnano i limiti della compatibilità. Una nuova release maggiore può essere incompatibile sia in avanti che all'indietro. Ci si aspetta che una release maggiore abbia nuove funzionalità e può avere interi nuovi d set di funzionalità.
Che significhi compatibile in avanti e compatibile all'indietro , esattamente, dipende da ciò che il vostro software fa, ma nel contesto, non sono aperte a tante interpretazioni. Per esempio, se il vostro software è una applicazione client/server, allora “compatibile all'indietro” significa che l'aggiornamento del server alla 2.6.0 non dovrebbe causare per i clients la perdita di funzionalità o comportamenti differenti da quelli di prima (eccetto per i bugs che sono stati corretti, certo). D'altra parte, l'aggiornamento di uno di quei clients alla 2.6.0 , insieme al server, potrebbe rendere disponibili nuove funzionalità per quel client, funzionalità di cui i client 2.5.4 non sanno come avvantaggiarsi. Se ciò avviene, l'aggiornamento non è “compatibile in avanti”: chiaramente non potete ora tornare indietro con quel client alla 2.5.4 e mantenere tutte le funzionalità che aveva nella 2.6.0, perché alcune di quelle funzionalità erano nuove nella 2.6.0.
Questo è il motivo per cui le micro releases sono essenzialmente per le correzioni dei bugs. Esse devono rimanere compatibili in entrambe le direzioni: se voi aggiornate dalla 2.5.3 alla 2.5.4, poi cambiate idea e tornate indietro alla 2.5.3, nessuna funzionalità dovrebbe andar perduta. Certo i bugs corretti riapparirebbero dopo il ritorno alla precedente versione, ma voi non perdereste nessuna funzionalità, eccetto per il fatto che i bugs reintrodotti impediscono l'uso di alcune funzionalità esistenti.
I protocolli client/server sono giusto uno dei campi dalle molte possibili compatibilità. Un' altra è la formattazione dei dati: il software scrive i dati in uno spazio permanente? Se così, i formati che legge devono seguire le leggi di compatibilità promesse dalla politica dei numeri di rilascio. La versione 2.6.0 deve poter leggere files scritti nella 2.5.4, ma può in silenzio aggiornare il formato a qualcosa che la 2.5.4 non può leggere, perché la possibilità di ritornare indietro non è un requisito della 2.6.0 per via delle delimitazioni riguardanti un numero minore. Se il vostro progetto distribuisce librerie di codice per l'impiego in altri programmi, allora le API sono anche un dominio di compatibilità: dovete essere sicuri che le regole di compatibilità per il sorgente e il binario siano dette in maniera tale che l'utilizzatore informato non debba mai chiedersi se è sicuro e opportuno aggiornare o no. Egli deve essere capace di guardare i numeri è e saperlo istantaneamente.
In questo sistema voi non avete una chance per una fresca partenza finché non incrementate il numero maggiore. Questo può essere spesso un reale inconveniente: ci possono essere funzionalità che voi volete aggiungere, o protocolli che volete ridisegnare, cose che non possono essere semplicemente fatte mentre mantenete la compatibilità. Non c'è una soluzione magica a questo, eccetto che cercare di disegnare le cose in modo estensibile in primo luogo (una argomento che facilmente merita il proprio libro, ma certamente fuori tema in questo). Ma pubblicare una politica di compatibilità delle releases, e aderirvi, è una parte delle distribuzione del software a cui non si può sfuggire. Una sgradevole sorpresa può allontanare un sacco di utilizzatori. La politica appunto descritta è buona in parte perché è già abbastanza diffusa, ma anche perché è facile da spiegare e da ricordare, anche per coloro che non hanno ancora familiarità con essa.
E' generalmente convenuto che queste regole non si applicano alle release pre-1.0 (sebbene la vostra politica di release lo stabilisca esplicitamente, giusto per essere chiari). Un progetto che sia ancora allo sviluppo iniziale può rilasciare la 0.1, 0.2, 0.3 e così via in sequenza, finché non sia pronto per la 1.0, e le differenze fra queste releases possono essere arbitrariamente grandi. I micro numeri nelle releases pre-1.0 sono opzionali. A seconda della natura del vostro progetto e delle differenze fra le releases potreste trovare utile avere la 0.1.0, la 0.1.1. ecc.., oppure no. Le convenzioni per le releases pre-1.0 sono piuttosto permissive, principalmente perché la gente capisce che forti costrizioni di compatibilità intralcerebbero molto il primo sviluppo, e anche perché i primi che le adottano tendono ad essere indulgenti comunque.
Ricordate che tutte queste ingiunzioni si applicano a questo sistema a tre componenti. Il vostro progetto potrebbe venir su con un differente sistema a tre componenti, oppure potrebbe decidere di non avere bisogno di un così fine granulosità e usare invece un sistema a due componenti. La cosa importante è deciderlo per tempo, rendere pubblico ciò che i componenti significano, e aderire ad essi.
Alcuni progetti usano la parità del componente numero minore per indicare la stabilità del software. Pari significa stabile, dispari significa instabile. Ciò si applica solo al numero minore, non al numero maggiore a al micro numero. Incrementi nel micro numero ancora significano correzioni di bug (non nuove funzionalità), e incrementi nel numero maggiore ancora indicano grossi cambiamenti, nuovi set di funzionalità, ecc..
Il vantaggio del sistema pari/dispari, che è stato usato dal progetto kernel di Linux fra gli altri, è che offre una via per rilasciare nuove funzionalità per la fase di prova, senza costringere gli utilizzatori della produzione a un codice potenzialmente instabile. Le persone possono vedere dai numeri che la "2.4.21" va bene per l'installazione sul loro attivo web server, ma che la "2.5.1" dovrebbe essere usata solamente per esperimenti sulle work station. Il team di sviluppo gestisce i report di bugs che arrivano dalla serie minore (numerata dispari), e quando le cose incominciano a sistemarsi dopo un certo numero di micro releases in quella serie, incrementano il numero minore (così facendolo diventare pari), riportano il micro numero a “0”, e rilasciano il pacchetto presumibilmente stabile.
Questo sistema conserva, o almeno non va in conflitto con le linee guida date prima. Esso semplicemente carica ulteriormente il numero minore di qualche extra informazione. Questo costringe d'altronde il numero minore ad essere incrementato di circa due volte tanto spesso quanto sarebbe necessario, ma non c'è un gran male in ciò. Il sistema pari dispari è probabilmente il migliore per i progetti che hanno cicli di release molto lunghi, e che per loro natura hanno una grande fetta di utilizzatori conservatori che valutano la stabilità al di sopra delle nuove funzionalità. Questo comunque non è il solo modo di fare il test di nuove funzionalità allo stato selvaggio, comunque. sezione chiamata «Stabilizzare una Release» Più avanti in questo capitolo si descrive un altro, forse più comune, metodo di rilasciare al pubblico codice potenzialmente instabile, contrassegnato in modo che le persona abbiano un'idea del compromesso rischio/beneficio vedendo il nome della release.