Juha
Satu
Taru
Kati

Perheen tarina
Lasten albumi
Sivuston historia

Etusivu

Valid HTML 4.01!
Valid CSS!

Käytännön vinkkejä ohjelmistotuotantoon

1. Johdanto

Sarjakuva

Kuva 1: Uusi auto ei sisältä vastaa odotuksia. Harvinaista autoteollisuudessa, mutta ohjelmistotuotannon arkipäivää.

Jos mietit aloittavasi tekemään tai teet ohjelmistoja, tässä muutamia käytännön vinkkejä, joista toivottavasti on hyötyä. Kappaleissa 2 - 7 käsitellään itse ohjelmistojen tekemisen prosessia. Kappaleessa 1 on muutamia yleisiä asioita, jotka koskevat kaikkia ohjelmistotuotannon vaiheita. Joissain kohdin tässä tekstissä on otettu esimerkiksi Java-maailmasta löytyviä asioita. Teksti ei ota kantaa onko itse prosessi vesiputousmalli, spiraalimalli, protomalli tai joku muu.

1.1. Termit

1.1.1. Ohjelmistotuotanto

Ohjelmistojen tekemiseen ei ole yhtä vakiintunut suomenkielistä termiä, vaan käytössä on samaa asiaa tarkoittavat termit ohjelmistotuotanto ja ohjelmistotekniikka. Tässä tekstissä käytetään termiä ohjelmistotuotanto.

1.1.2. Prosessi

Prosessi tarkoittaa hallittua toistettavaa työvaiheiden sarjaa, jonka lopputulos on ennakoitavissa. Ohjelmistoja voidaan tehdä ilman prosessia, mutta tästä aiheutuu mm. laatuongelmia, koska lopputulos riippuu täysin tekijöistä.

1.1.3. Malli

"1. Johdanto" -kappeleessa mainitut mallit prosessista kertovat miten työvaiheesta toiseen edetään:

  • Vesiputousmallissa edetään vaiheet järjestyksessä ensimmäisestä viimeiseen, jonka jälkeen prosessi loppuu.
  • Spiraalimalli eroaa siten, että viimeisen vaiheen jälkeen voidaan aloittaa uudestaan ensimmäisestä vaiheesta.
  • Protomallissa tehdään ensin valmiksi proto ohjelmistosta, jossa on keskitytty ohjelmiston yhden tärkeän ominaisuuden esittelyyn. Proton rakentamisen jälkeen aloitetaan tekemään ohjelmistoa nollasta.

1.1.4. Ohjelmistotuotannon työvaiheet

Ohjelmistotuotanto koostuu seuraavista työvaiheista: määrittely, suunnittelu, toteutus, testaus, käyttöönotto ja ylläpito. Näiden työvaiheiden sisältöön otetaan kantaa kappaleissa 2 - 7.

1.2. Dokumentointi

Dokumentointiin kannattaa käyttää pistää paukkuja. Matalan tason tekninen dokumentointi sujuu luontevasti englanniksi, mutta muun dokumentaation kielen valintaan kannattaa käyttää hetki aikaa. Kielen valintaan vaikuttaa se kenelle dokumentti on tarkoitettu nyt ja kuka sitä mahdollisesti tulevaisuudessa lukee. Kielen valinnan epäonnistuminen vaikeuttaa dokumentointia sekä heikentää dokumentoinnista saatavaa hyötyä. Dokumenttien kuvitukseen kannattaa käyttää aikaa, koska kuvat kertovat tunnetusti "enemmän kuin tuhat sanaa". Lisäksi usein lukijoiden on vaikea keskittyä pitkään vaativaan tekniseen tekstiin, joten kuvat tarjoavat katkoja lukemiseen.

Dokumentoi harkiten asioita kahteen kertaan, käytä mielummin viittauksia, jotta ylläpidosta selvitään kunnialla. Tietyissä tilanteissa esimerkiksi ohjelmiston yleiskuvaus on perusteltua kopioida sellaisenaan dokumentista toiseen. Toinen hyvä syy tupladokumentointiin on se, että kaikkia dokumentteja ei toimiteta kaikille tahoille. Hyvin tehty dokumentaatio on hyödyllinen dokumentin kirjoittajalle itselleen, koska siitä käy ilmi tarvittavat asiat - tekijän ei tarvitse muistaa kaikkia asiota. Kirjoittajan hyötynä voidaan pitää sitä, ettei toisten henkilöiden tarvitse henkilökohtaisesti kysellä kirjoittajalta tietoja, jos he löytävät etsimänsä tiedon dokumentista. Ennen varsinaisen dokumentoinnin aloittamista kannattaa miettiä minkälaisia dokumentteja kirjoitetaan ja mitä asioita niihin tulee otsikkotasolla. Näin helpotetaan tekemään dokumentaatiosta looginen, johdonmukainen, luettava ja ylläpidettävä.

1.3. Hukkaan heitetty työ

Mitä pidemmellä ohjelmiston tekemisessä edetään, ettei kaikki osapuolet tiedä tarkkaan mitä ollaan tekemässä, sitä enemmän hukataan työtä, jos jälkikäteen selviää että toinen puhui aidasta ja toinen aidan seipäästä. Sama pätee vikojen havaitsemiseen, koska mitä aikaisemmassa prosessin vaiheessa viat havaitaan ja korjataan, sitä pienemmällä työmäärällä selvitään. Jottei tehdä turhaa työtä, kannattaa prosessin alkupäähän kiinnittää erityistä huomiota.

Aina välillä kannattaa pysähtyä kriittisesti arvioimaan jo tehtyä työtä - puuttuuko jotain olennaista, onko jotain turhaa ja onko tuotettu tieto muutoksineen toimitettu kaikkien tietoa tarvitsevien ulottoville. Pitäen samalla mielessä, että prosessin heikoin lenkki kertoo koko prosessin tason. Valitettavan usein aikataulu sanelee käytännön ehtoja. Yllyttämättä venyttämään ohjelmistoprojekteja on silti hyvä pitää mielessä seuraavaa asia. Jos ohjelmistoprojekti myöhästyy vähän, sitä ei kukaan muista vuoden päästä, mutta jos ohjelmisto on susi, sitä joudutaan parantelemaan hamaan tulevaisuuteen.

1.4. Kirjasto esimerkki

Läpi tämän tekstin rakennetaan rinnalla yksinkertaistettu kirjasto järjestelmä, jotta ohjelmistotuotannon eri vaiheet tulisivat käytännönläheisesti käytyä läpi.

2. Määrittely

Aluksi määrittelyssä kannattaa muodostaa itselle kuva mitä ollaan tekemässä tutustamalla aiheeseen. Tämä voi tapahtua lukemalla kirjallisuutta tai keskustelemalla henkilöiden kanssa, joilla on selkeä käsitys siitä mitä halutaan, mutta eivät välttämättä ymmärrä tekniikan päälle. Kerää muistiinpanoja, jotka helpottavat varsinaisen määrittelydokumentaation kirjoittamista. Jos määrittelydokumentaation kirjoittamiseen osallistuu useita henkilöitä, sopikaa selvät roolit ja käykää määrittelyn etenemistä säännöllisesti läpi. Muussa tapauksessa asioita tehdään useaan kertaan ja lopputuloksesta tulee sekava jopa ristiriitainen.

Määrittelydokumentaatiossa tärkeitä asioita on mm. termien määrittely, vaatimuksien numerointi, vaatimuksien pitäminen lyhyinä ja selkeinä sekä vaatimuksien kategorisointi, jos vaatimuksia on paljon. Vaatimukset voidaan tarvittaessa priorisoida, jolloin on sovittava miten prioriteetit vaikuttavat käytännössä. Jos vaatimuksia joudutaan myöhemmin muuttamaan, vaatimusdokumenttien versiointi on tärkeää. Näin voidaan prosessin myöhemmissä vaiheissa viitata vaatimuksiin, joiden pohjalta työtä on tehty.

Määrittely dokumentaatiossa ei oteta kantaan tekniikkaan esim. millä ohjelmointikielellä toteutus tullaan tekemään, tullaanko toteutus ajamaan palvelimella vai asiakkaalla, käytetäänkö tietovarastona tietokantaa jne. Määrittelydokumentaation valmistumisen yhteydessä on hyvä pyytää kirjallinen hyväksyntä ohjelmiston tilaajalta. Näin vältetään tai ainakin minimoidaan mahdolliset epäselvyydet myöhemmin, joiden korjaaminen vie usein paljon aikaa. Määrittelydokumentaatioon pohjautuu kaikki määrittelyn jälkeiset työvaiheet. Testauksen suunnittelu on hyvä aloittaa samaan aikaan määrittelyn kanssa, jotta testaaminen keretään suunnitella riittävän kattavaksi.

Kirjasto esimerkin vaatimusten 0.1-versio:

Termit:
-Kirjasto on paikka, jossa teoksia säilytetään ja josta asiakas niitä lainaa.
-Asiakas on yksityishenkilö, joka voi lainata/palauttaa teoksen/teoksia kirjastosta.
-Teos on pienin mahdollinen lainauksen kohde esimerkiksi
   +lehti
   +kirja
   +CD-musiikkilevy
   +C-kasetti
   +DVD-video
   +VHS-video
   +musiikki satu (sis. CD-levyn ja kirjan)

Toiminnalliset vaatimukset:
1) Asiakas yksilöitävä
2) Asiakas voi lainata kirjastosta teoksen/teoksia
3) Asiakas palauttaa teoksen/teokset ennen laina-ajan umpetumista
4) Asiakas voi palauttaa teoksen tai teoksia riippumatta lainasiko hän ne kerralla
5) Asiakkaita voi lisätä tai poistaa
6) Asiakkaan poisto edellyttää teosten palauttamista
7) Asiakkaan tietoja voi muokata
8) Asiakkaan tietoja vähintään nimi, yhteystieto
9) Asiakkaan nykyiset lainat nähtävä
10) Asiakkaan nykyiset lainat voi nähdä asiakas tai kirjaston edustaja
11) Teoksen maksimi laina-aika määräytyy tyypin mukaan (kaikkia teoksia ei lainata)
12) Teoksien tyyppejä voi lisätä tai poistaa
13) Teoksen tyypin poisto edellyttää ettei kyseistä tyyppiä käytetä 
14) Teoksien laina-aikoja voi muuttaa 
15) Teokseien laina-aikojen muuttaminen ei vaikuta lainattujen laina-aikoihin
16) Teoksia voi lisätä tai poistaa
17) Teoksen tietoja voi muokata
18) Teoksen tietoja vähintään nimi, teoksen tekijä, tyyppi, lukumäärä

Ei toiminnalliset vaatimukset:
19) Asiakkaan mahdolista käyttää kodistaan
20) Jokaisella sivulla apua-osio
21) Ulkoasua voi muokata kirjastokohtaisesti (Vähintään kirjaston logo, fonttien koot ja värit)
22) Yhtäaikaisia asiakkaita jopa 50, joille vaste 3 sekunnin välein
23) Maksimi viive 0,5 sekunttia
24) Käytettävissä ruuhka-aikana (joka päivä kello 9-18) yli 99,5%
25) Käytettävissä yli 95% ruuhka-ajan ulkopuolella

Jos tiedetään muita vaatimuksia, jotka todennäköisesti myöhemmin halutaan toteuttaa, on ne syytä kirjata pienemmällä prioriteetilla jo vaatimusten ensimmäiseen versioon. Esimerkki määrittelystä puuttuu yksinkertaistamisen vuoksi mm. asiakaskohtainen käyttöliittymän kieli, alaikäisten henkilöiden lainojen vastuuhenkilö, montako teosta yksi asiakas voi lainata, mitä käy jos asiakas ei palauta teosta ajallaan, mahdollisuus tallentaa ylimääräistä tietoa esim. syy miksi käyttäjä/teos on poistettu, aika jolloin käyttäjä/teos on lisätty/poistettu, teoksien varaaminen, muistutukset määräajan lähestymisestä, kirjaston yhteystiedot ja aukioloajat tai ilmoitus varatun teoksen vapautumisesta yms.

3. Suunnittelu

Suunnittelu perustuu vaatimusten tiettyyn versioon, joka on syytä dokumentoida. Suunnittelu koostuu kolmesta osasta, joita voidaan tehdä rinnakkain ja missä tahansa järjestyksessä.

3.1. Käyttöliittymän suunnittelu

Käyttöliittymäsuunnittelu sisältää luonnokset käyttöliittymän tärkeimmistä toiminnoista. Käyttöliittymässä kannattaa miettiä käytettävyyttä, joka on yksi tärkeä osa sovellusta. Käytettävyys on asiana todella laaja, joten tässä tekstissä vain raapaistaan pintaa. Jos käyttäjän ei ole sallittua kaikkina aikoina käyttää kaikkia osia, kannattaa miettiä miten käyttäjää informoidaan ettei osa sovelluksesta ole käytössä. Pelkkä sovelluksen osan häviäminen käyttöliittymästä voi hämmentää käyttäjää, jos käyttäjällä joskus on kuitenkin mahdollisuus käyttää kyseistä osaa. Tai sama käyttäjä voi olla useassa eri roolissa sovelluksen käytössä. Käyttöliittymä suunnitelmassa voidaan myös kertoa kuka kyseistä osaa voi käyttää - esimerkiksi:

-etusivu (asiakas & kirjasto)
-asiakas
   +asiakkaan haku (asiakas & kirjasto)
   +asiakkaan tietojen katselu (asiakas & kirjasto)
   +asiakkaan muokkaus (kirjasto)
   +asiakkaan poisto (kirjasto)
   +asiakkaan luonti (kirjasto)
   +asiakkaan lainojen katselu (asiakas & kirjasto)
   +asiakkaan lainojen palautuksen (kirjasto)
-teokset
   +teoksen haku (asiakas & kirjasto)
   +teoksen tietojen katselu (asiakas & kirjasto)
   +teoksen muokkaus (kirjasto)
   +teoksen poisto (kirjasto)
   +teoksen luonti (kirjasto)
   +teoksen lainaus (kirjasto)

3.2. Tietovaraston suunnittelu

Jos sovelluksen varastoitava ja haettava tietoa, kannattaa suunnitella mihin tieto tallennetaan esim. tietokantaan tai tiedostojärjestelmään ja miten tieto sinne tallennetaan esim. tietokannan kuvaus tai tiedostojen sijainnin ja sisällön kuvaus. Ristiriitojen välttämiseksi tietovaraston sisällössä vältettävä tiedon säilyttämistä kahdessa paikassa. Tietovaraston suunnittelussa yksinkertaisuus on kaunista ja helpottaa ylläpitoa. Esimerkki tietokannan rakenteesta - huomaa että tämä kannattaa jo tehdä englanniksi, jotta ohjelmistossa voidaan käyttää samoja termejä:

-user
   +name
   +login (primary key)
   +password
   +contact address
   +role

-item
   +name (primary key)
   +creator
   +type
   +units

-type
   +name (primary key)
   +loan period

-unit
   +item (foreign key)
   +user (foreign key)
   +start date
   +end date

3.3. Sovelluksen suunnittelu

Suunnitelmassa kannattaa tuottaa vähintään ylemmän tason suunnitelma miten sovellus aiotaan toteuttaa mm. millä ohjelmointikielellä. Suunnittelussa kannattaa pilkkoa kokonaisuus osiin, joista kannattaa ensin suunnitella yleiskäyttöisiä osia ja lopuksi ohjelmistokohtaiset osat. Jos sovellus pilkotaan kerroksiin, kannattaa tämä kuvata suunnittelu dokumentaatioon. Kerroksia voi olla esim. tietokanta kerros, logiikka kerros ja käyttöliittymä kerros. Suunnittelussa voidaan ottaa kantaa, että nimeämiseen esim. toteutus kerrokset, asennuspaketit, asennuspolut, versiointi yms. Suunnittelussa voidaan mahdollisesti ottaa kantaa lähdekoodin ulkoasuun, sovelluskehittimeen jolla lähdekoodi tehdään, lähdekoodin versiohallintaan, lähdekoodiin kääntämiseen ajattavaksi ohjelmaksi. Esimerkki suunnittelun tuloksesta:

-Toteutus tehdään J2EE (=Javan Enterprise Edition) 1.5 versiolla
-Sovellusta ajetaan JBoss-sovelluspalvelimen 3.2 versiolla
-Tietokantana käytetään Derbyn versiota 10.1
-Käyttöliittymä toteutetaan XHTML 1.0 standardin mukaan
-Käyttöliittymä toimii Mozilla 1.0 selaimella
-Sovelluskehittimenä käytetään Eclipsen versiota 1.3
-Versiohallintaan käytetään CVS:ssää
-Versiohallinnan päähaarassa pitää olla testattu ja toimiva ohjelma
-Versiohallintaan luodaan sivuhaara library-example, johon kehitystyötehdään
-Sovelluksen nimi on library-example
-Sovellus paketoidaan example.library-pakettiin
   +example.library.db-paketti sisältää tietokanta toteutuksen
   +example.library.logic-paketti sisältää sovellus logiikan
   +example.library.ui-paketti sisältää käyttöliittymän
-Sovellus kirjoittaa logia java.util.logging.Logger-luokalla
   +Virheet logittaa käyttöliittymä taso, alemmat tasot heittävät MyException
   +Severe-tasoa käytetään virheestä, jolloin ei voida jatkaa esim. tietokanta rikki
   +Warning-tasoa käytetään virheestä, joka johtuu esim. käyttäjän syötteestä
   +Info-tasoa käytetään käyttäjän kirjautuessa sisään ja ulos
   +Fine-tasoa käytetään käyttäjän vaihtessa sivua
   +Finer-tasolla kirjoitetaan logiikan pääkohdat ja tietokanta haut
   +Finest-tasolla kirjoitetaan muut mahdolliset tiedot

4. Toteutus

Toteutus sisältää lähdekoodin, lähdekoodin dokumentoinnin ja sovelluksen yksikkötestit. Lähdekoodin keskeisiä asiota on mm. nimeäminen, selkeys, luettavuus, yksikkötestattavuus. Yksikkötestit sisältävät metodien testaamisen ilman käyttöliittymää tai IO-rajapintoja esim. tietokanta yhteyttä. Yksikkötestit kannattaa automatisoida, jotta jokaisen muutoksen jälkeen voi varmistua ohjelmiston toimivuudesta. Yksikkötesteistä on myös tärkeää saada dokumentti, jotta testaus vaiheessa tiedetään mitä kaikkea on testattu. Kätevin tapa dokumentoida yksikkötestit Javassa on käyttää standardeja Javadoc merkintöjä. Yksikkötestien tekeminen edesauttaa koodin selkeyttä, koska se pakottaa jakamaan koodin pieniin osiin.

Selkeyttä lisää se, ettei samaa koodia kopioida useisiin paikkoihin vain keskitetään yhteen. Tämä helpottaa ohjelmiston ylläpidettävyyttä ja vikojen korjaamista. Hyvä nimeäminen ja luettavuus helpottaa koodin sisäistämistä jälkikäteen. Se auttaa tekijää itseään palamaan astialla pitkän ajan jälkeen. Tärkeässä roolissa on virheiden käsittely, joka kannattaa erottaa varsinaisesti sovelluskoodista. Kätevimmin Javassa tämä tapahtuu tekemällä omia poikkeusluokkia. Jos tälläisiä poikkeuksia esiintyy ohjelmaa ajattaessa, voidaan vika paikantaa suoraan oikeaan paikkaan eikä tarvitse epäillä esim. sovelluspalvelvinta. Poikkeuksien perusperiaate on heittää ne mahdollisimman aikaisin ja ottaa kiinni mahdollisimman. Poikkeuksesta kannattaa tehdä ajonaikainen, jos ylemmällä tasolla ei voida tehdä poikkeukselle mitään esim. tietokanta yhteys on poikki.

5. Testaus

Testaus on vaativa ja laaja kokonaisuus, jota helposti väheksytään. Karkeasti testaaminen voidaan jakaa suorituskyky ja toiminnalliseen testaamiseen. Testauksen perustana toimii vaatimukset ja niitä täydentävät yksikkötestit. Testaamisen automatisointia kannattaa harkita, mutta monesti manuaalisesti testaaminen on nopeampaa lyhyessä juoksussa. Automaattitestauksen hyödyt tulevat esille vasta, kun sovelluksesta tehdään useita versioita ja samoja testitapauksia joudutaan ajamaan useita kertoja läpi eli rekressiotestaamaan. Testausta voidaan tehdä hyvin monella tasolla: yksikkötestauksesta, integraationtestauksen, järjestelmätestatuksen kautta aina hyväksyntätestatukseen.

Testauksen yhteydessä sovitaan miten virheiden korjaukset aikataulutetaan. Jos virheitä on paljon, joudutaan kategorioiden sisällä sopimaan erikseen korjausjärjestys. Virheet voidaan esimerkiksi jakaa seuraaviin kategorioihin helpottamaan korjausjärjestystä:

Korjaus-
järjestys
KategoriaKuvausKirjasto esimerkkiVaikutus hyväksyntätestaukseen
1.puutemäärittelyssä ja puuttuu sovelluksestaA) asiakkaan lisäys puuttuuestää testauksen aloittamisen
2.estävä virheei voida kiertää ohjeistamallaB) teoksen lainaus ei toimi
C) teoksen tietojen katselu ei toimi.
korjataan testauksen aikana ja lisää testausaikaa
3.muu virhekäyttöä vaikeuttava tai muu virheD) teokset listatataan luomisjärjestyksessä (eikä aakkosjärjestyksessä)
E) asiakashaun kautta onnistuu vain tietojen muokkaus ilman poisto mahdollisuutta
korjataan myöhemmin (esim. viivyttelemättä, viimeistään 6kk aikana)
4.muutospuuttuu määrittelystä kokonaanF) teosten ryhmittely (esim. tiede, viihde)määritellään ja suunnitellaan myöhemmin

6. Käyttöönotto

Käyttöönotto vaatii erityistä suunnittelua, jos kyse on toiminnassa olevan sovelluksen korvaamisesta uudella. Tällöin on syytä ottaa huomioon nykyiset käyttäjät varsin tarkkaan mietittäessä ohjelmiston korvaamisen ohjeistusta ja ajankohtaa. Jos korvataan vanha sovellus, pitää ottaa huomioon kuinka vanhaa sovellusta tuetaan ylimenokauden ajan, kun molemmat sovellukset ovat rinnakkain käytössä. Ideaalitilanne olisi, jos ylimenokautta ei olisi ollenkaan.

7. Ylläpito

Yksikään sovellus ei ole ikinä täysin valmis, koska elämme muuttuvassa maailmassa. Monikohan erehtyi aikanaan luulemaan, ettei vuotta 2000 tulisi ikinä =) Tai että Suomessa olisi markka valuuttana ikuisesti =) Reaalimaailman muutoksista johtuen ylläpito kannattaa ottaa huomioon jo ohjelmiston määrittelyvaiheessa - muista vaiheista puhumattakaan. Kuinka paljon ylläpitoa helpottaa, jos ohjelmisto on laadukkaasti tehty alusta loppuun.