Ohjelmiston versiohallinta

Johdanto

Kun ohjelmistoprojektien koko alkoi kasvaa räjähdysmäisesti 1960-luvun lopulla, huomattiin, että ohjelmistojen kehitys sisältää muutakin kuin vain ohjelmointiosuuden. Ongelmallisena koettiin ohjelmistoprojektin hallinta sekä suuret määrät lähdekoodia ja dokumentteja, joita tuli pystyä tarkoin hallitsemaan. Näinä aikoina versiohallinta tuli ajankohtaiseksi.
Versiohallinta on ohjelmistoprojektin tuotoksien hallintaa ja eräs sen tärkeimmistä
tavoitteista on mahdollistaa ohjelmistokomponenttien yhtäaikainen ja ristiriidaton
kehitys. Versiohallinta luo pohjan evolutionääriselle ohjelmistojen kehitykselle
takaamalla, että jokaista mielivaltaiseen ohjelmistokomponenttiin tehdyn muutoksen
piirteitä voidaan arvioida milloin tahansa.
Versiohallinta mahdollistaa ohjelmiston kehityskaaren seurannan ja turvallisen
kehityksen. Versiohallinta myös mahdollistaa kehityksen etenemisen eri suuntiin, joka
on usein välttämätöntä räätälöitäessä ohjelmistosta eri versiota eri alustoille ja asiakkaille.
Versiohallinta mahdollistaa myös aiempaan kehitysversioon palaamisen,
joka voi olla toivottavaa esimerkiksi silloin kun siinä on suorituskyvyn tai ominaisuuksien
kannalta joitakin haluttavia piirteitä, joita uusimmassa kehitysversiossa
ei enää ole.

Versiohallinnan teoriaa

Versiohallinta on yksinkertaisimmillaan joukko toimenpiteitä, joita noudattamalla
pyritään hallitsemaan dokumenttien kehittämistä ja versiointia. On varsin ilmeistä,
että manuaalisiin toimenpiteisiin nojaava versiohallintajärjestelmä on herkkä virheille,
skaalautumaton ja työläs ylläpitää. Ongelmien ratkaisuksi kehitettiin 70-luvulla
ensimmäiset palvelinkeskeiset versiohallintajärjestelmät, jotka automatisoivat
suuren osan työstä, jota aiemmin jouduttiin tekemään käsin. Nykyään versiohallintajärjestelmät
ovat jo varsin kehittyneitä ja läheisesti integroituja jokaiseen vähänkin
vakavampaan ohjelmistonkehitysprojektiin.
Tässä luvussa on tarkoitus esitellä katsausluontoisesti teoriaa, jonka varaan versiohallinta
edelleen suurelta osin perustuu. Ensin käsitellään konfiguraationhallintaa,
joka on versiohallinnan yläkäsite. Tämän jälkeen käsitellään versiohallintaa
ja sen osa-alueita.

Konfiguraationhallinta

Zellerin mukaan konfiguraationhallinta (engl. Configuration management, CM) on
oppi kehittyvien järjestelmien organisoinnista ja hallinnasta. 
Konfiguraationhallinta
pyrkii määräämään menettelytavat komponenttien ja niiden yhdistelmien tunnistamiseksi,
julkistusten ja muutosten hallitsemiseksi, tuotteen tilan kirjaamiseksi, sekä
tuotteen täydellisyyden ja yhtenäisyyden varmistamiseksi. Tässä komponenteilla
tarkoitetaan ohjelmistoalkioita, joita ovat muun muassa ohjelmatiedostot
ja dokumentit.
Zeller erottaa ohjelmiston konfiguraationhallinnan (Software Configuration Management,
SCM) perinteisestä konfiguraationhallinnasta ohjelmistojen mukautuvuuden,
helpon kopioitavuuden ja monimutkaisuuden kautta. Lisäksi ohjelmistojen
konfiguraationhallintaa voidaan automatisoida laajalti, koska komponentit ovat
tietokoneen hallinnassa. Pressman jakaa ohjelmiston konfiguraationhallinnan
tehtäväalueisiin, jotka ovat muutosten identifiointi, versiohallinta, muutoksenhallinta,
konfiguraation laadunarviointi ja muutoksista tiedottaminen.

Ohjelmiston versiohallinta ja versiointi

Pressmanin mukaan versiohallinta yhdistää menetelmät ja työkalut ohjelmistoprosessin
aikana luotavien konfiguraatio-objektien eri versioiden hallitsemiseksi.
Konfiguraatio-objektin voidaan ymmärtää tarkoittavan esimerkiksi asiakirjaa,
ohjelmistokomponenttia tai näiden muodostamia yhdistelmiä. Versiohallinta
on yhdistelmä konfiguraationhallinnan menetetelmiä, joiden avulla käsitellään
konfiguraatio-objektien eri versioita. Versiot ovat eräänlaisia koonteja tai kuvauksia
ohjelmistosta. Ne koostuvat joukosta ohjelmistoalkioita, joita joukko ihmisiä yhdessä
kehittää; versiot ovat ohjelmiston muunnelmia. Versiointi on joukko määrätyssä järjestyksessä
suoritettavia toimenpiteitä, jotka synnyttävät konfiguraatio-objektista uuden
version. Versioinnin toimenpiteitä ovat versioinnin ulottuvuuksien määrittely,
version merkitseminen, versioiden välisten erojen tunnistaminen ja version tallentaminen.

Versioinnin ulottuvuudet

Muutokset komponentteihin luovat komponenteista uusia versioita, joiden ulottuvuus
määräytyy muutoksen tekijän tarkoitusperän mukaan. Zellerin
mukaan versioinnin ulottuvuuksiksi luetaan yleisesti historiallinen, looginen ja
yhteistoiminnallinen versiointi.
Historiallinen versiointi on kehitystä, jossa uudempi versio syrjäyttää aiemman.
Tällaisia syrjäyttäviä versioita kutsutaan revisioiksi (revision).
Looginen versiointi on niin kutsuttujen haarojen (branch) luomista, jossa kukin
haara kuvastaa kehityksen vaihtoehtoista kulkua. Haarat etenevät omaa kehityskaartaan
muista haaroista riippumatta, toisin kuin historiallisessa versioinnissa, jossa
uudemmat revisiot syrjäyttävät vanhemmat. Vaikka haaroja voidaan integroida toisiinsa,
looginen versiointi korostaa rinnakkaista kehittämistä ja haarojen keskinäistä
autonomisuutta.
Yhteistoiminnallinen versiointi on väliaikaisuuden hallintaa siten, että tarkoituksena
on luoda hetkellisiä versioita komponenteista, jotka tullaan myöhemmin integroimaan
toisten versioiden kanssa. Loogisessa versioinnissa esiintyvän haarautumiseen
verraten kyseessä ei ole vaihtoehtoinen kehityssuunta, vaan pikemminkin
hetkellinen poikkeama, joka useimmiten on seurausta kehitystilanteessa esiin tulleesta
tarpeesta, mutta joka jo luonnin hetkellä tiedostetaan yhdistettäväksi toiseen
versioon myöhemmin.

Versioiden merkitseminen

Historiallisessa versioinnissa revisiot järjestetään ja ne identifioidaan järjestyksen
mukaan. Identifioiminen voidaan tehdä esimerkiksi numeerisesti siten, että suurin
luku viittaa viimeisimpään revisioon. Tällöin revisioita merkittäessä käytetään yleensä
kaksitasoista numerointia muodossa [V.R], missä V kuvastaa julkaisunumeroa ja R
tasonumeroa. Julkaisunumeroa kutsutaan myös versionumeroksi ja tasonumeroa revisioksi.
Julkaisunumeron muutos kuvastaa suurta muutosta ja revisionumeron muutos
pienempää muutosta.
Joskus versioninnissa käytetään lisäksi kolmatta tasoa, joka ilmaisee ohjelmaan tehdyn paikan (patch). Paikkausversioita käytetään ohjelmavirheiden korjauksissa.
Ohjelmankehityksessä kehitystason versiot ovat tyypillisesti alle 1.0. Siihen kuuluvat testausversiot alfa-, beta- ja gammatestauksineen. Kun ohjelma on valmis tuotantokäyttöön, se julkistetaan ja senhetkisen ohjelmankehityksen tilan versionumeroksi asetetaan 1.0. Julkistuksen jälkeen ohjelmasta julkaistaan tuotantoversion päivityksiä. Ne ovat numeroinniltaan yli 1.0. Tuotantoversioiden päivitykset ovat tyypillisesti virheenkorjausversioita tai uusia ominaisuuksia sisältäviä versioita. Versionumeroinnille ei ole olemassa täsmällistä ohjeistusta. Useiden tuotantokäytössä laajalti käytössä olevien ohjelmien versionumero on esimerkiksi 0.15. Ja toisaalta on olemassa ohjelmia, joiden tuotantoversiot eivät täytä käyttäjän näkökulmasta toimivan ohjelman kriteerejä.
Loogisen ja yhteistoiminnallisen versioinnin yhteydessä esiintyvien varianttien
merkitsemiseen käytetään useimmiten määrättyjä nimiä numeroinnin sijaan, koska
variantit eivät välttämättä esiinny toistensa suhteen järjestyksessä.

Versioiden välisten erojen tunnistaminen

Ohjelmistoon tehtyjen muutosten selvittämiseksi täytyy voida selvittää versioiden
väliset erot. Koska toisiaan seuraavat versiot, eritoten revisiot, saattavat
olla hyvin toistensa kaltaisia, eroavaisuuksien tarkan määrittelyn avulla voidaan
keskittyä muutokseen ja säästää resursseja. Perinteisesti versioiden välisten erojen
tunnistamisella on pyritty säästämään tallennustilaa.
Yleinen tapa erojen tunnistamiseen on suorittaa merkkivertailu tekstitiedostojen
välillä. Kyseisen tavan tavoitteena on löytää pienin joukko muutoksia, jotka täytyy
suorittaa komponentin version A muuttamiseksi versioksi B. Kyseinen metodologia
ei kuitenkaan päde kuin tekstitiedostoja käsitellessä, sillä esimerkiksi binääritiedostoissa
pieni paikallinen muutos saattaa tiedoston rakenteesta riippuen vaikuttaa
koko tiedoston sisältöön.

Versioiden tallentaminen

Ohjelmistojen kehityksen ja ohjelmiston aikaisempien versioiden uudelleenrakentamisen
mahdollistamiseksi on vanhat ja uudet versiot voitava tallentaa pysyvästi.
Hyvin yleinen tapa on käyttää varastoja (engl. repository), jonne konfiguraatio-objektien
versiot ja niitä koskevat konfiguraationhallinnan tiedot tallennetaan. Tallennuksessa
on pyritty hyödyntämään myös valmiita tietokantajärjestelmiä, mutta käyttöä rajoittaa
se, ettei niissä yleensä ole tukea versioinnille.
Usein varastoissa käytetään tallentamiseen puurakennetta, jossa puun juuri
kuvastaa konfiguraatio-objektin ensimmäistä versiota ja juuren jälkeläiset kuvastavat
konfiguraatio-objektin myöhempiä versioita. Historiallinen versionti on puun
syvyyden kasvattamista ja looginen versiointi puun haarautumista.
Tilansäästön vuoksi varastoihin tallennetaan eri versioista vain niiden väliset
erot. Tämä muutostieto on kohdassa 2.5 esitetty minimaalinen muutosjoukko, jonka
perusteella komponentin tietty versio A voidaan muuntaa versioksi B. Kyseistä
minimaalista muutosjoukkoa kutsutaan deltaksi. Varastot voivat laskea deltoja kumulatiivisesti
ensimmäisestä versiosta lähtien niin, että vain komponentin ensimmäisen
versio säilytetään kokonaisuudessaan. Varastot voivat laskea muutostietoja
myös toisin päin, jolloin varastoon tallennetaan komponentin uusin versio
kokonaisuudessaan ja sen mukana muutostiedot aikaisempien versioiden konstruoimiseksi.
Koska komponentin versioiden väliset erot ovat tavallisesti komponentin
kokoon nähden pieniä, on deltoja hyödyntämällä saavutettava tilansäästö merkittävä.

Yhteenveto

Versiohallinta on ohjelmistoprojektin tuotosten hallintaa ja se mahdollistaa ohjelmiston
kehityksen seurannan ja vakaan kehityksen. Ohjelmistoprojektin asiakirjoista ja
komponenteista muodostetaan konfiguraatio-objekteja ja edelleen konfiguraatioita.
Versiohallinta on eräs tärkeimmistä ohjelmiston konfiguraatiohallinnan tehtäväalueista.
Versiohallinta voidaan jakaa neljään päätoimenpiteeseen, jotka ovat versiointi,
versioiden merkitseminen, versioiden välisten erojen tunnistaminen ja versioiden
tallentaminen.
Versiointi voidaan jakaa historialliseen, loogiseen ja yhteistoiminnalliseen versiointiin.
Versioiden merkitseminen kuvaa niitä menetelmiä, joita sovelletaan tietyn
konfiguraatio-objektin yksikäsitteiseksi nimeämiseksi. Versioiden välisten erojen tunnistamisen
päätavoite on minimoida versioiden tallentamiseen käytettävä levytila.
Toisin kuin versiohallinnan muut toimenpiteet, versioiden välisten erojen tunnistaminen
ei ole välttämätöntä versiohallinnan onnistumisen kannalta. Versioiden
tallentamisen tarkoituksena on mahdollistaa versioiden pysyvä tallennus, josta mielivaltaisella
ajanhetkellä voidaan valita haluttu versio käsiteltäväksi.