”Miten se noin paljon voi maksaa? Sehän on vain yksi pieni lisätieto siinä lomakkeella!”
Näin asiakas saattaa kommentoida, kun keskustellaan muutostöistä ohjelmistoihin. Käyttäjän näkökulmasta analogia ohjelmiston ja paperilomakkeen välillä on usein vahva, jolloin voi olla vaikea ymmärtää, mitä kaikkea yksittäisen tiedon lisääminen järjestelmän toimintoon vaatii. Tiedon lisääminen vaikuttaa yleensä myös järjestelmän muuhun toiminnallisuuteen ja tätä voi olla hankala hahmottaa yksittäisen muutostoiveen näkökulmasta. Kerron omakohtaisen esimerkin vapaa-ajan projektistani.
Olen jo yli kymmenen vuoden ajan pitänyt kirjaa kaikista auton tankkauksista. Olen kirjannut Exceliin tankatun polttoaineen määrän ja hinnan, ajetut kilometrit ja matkamittarilukeman. Näistä olen saanut kerättyä tilastoa ajoneuvon keskikulutuksesta ja autoilun kustannuksista. Jossain vaiheessa Exceliin kirjaaminen alkoi kuitenkin muuttua työlääksi ja tankkauskuitteja kertyä pinoittain auton keskikonsoliin. Alan miehiä kun olen, päätin toteuttaa yksinkertaisen mobiilisovelluksen kirjauksien tallentamista varten. Mukaan otin perheen molemmat autot, jotka kulkevat 95E-polttoaineella.
Jossain vaiheessa ajattelin, että olisi mukava saada myös moottoripyörä mukaan tilastoihin, mutta siihen tankataan 98E:tä. Pitäisi siis saada käyttöliittymään lisättyä yksinkertainen polttoainetyypin valinta. No, eihän se nyt iso homma ole… eihän?
Toteuttamani sovellus on perinteinen client–server-arkkitehtuurin mukainen ratkaisu. Tietovarastona toimii Linux-palvelimella pyörivä MariaDB-tietokanta. Samalle palvelimelle toteutin myös Java-pohjaisen, RESTful Web Service -rajapinnan tarjoavan Spring Boot -sovelluksen mobiilisovelluksen tietojen hakua ja tallentamista varten. Käyttöliittymän tarjoavan mobiilisovelluksen toteutin älypuhelimelle tarkoitettuna Java-pohjaisena native Android-sovelluksena. Lopuksi, tallennettujen tietojen analysointiin ja selailuun tein valmista, selainpohjaista tiedon visualisointiin tarkoitettua Grafana-työkalua hyödyntäen visuaalisen mittariston ja raportointinäkymän.
Ja sitten hommiin…
Pitsaa? Check! Kolaa? Löytyy! Olosuhteet on kunnossa, joten ei kun koodaamaan, jotta saan 98E:n mukaan tilastoihin! Lisään Android-sovelluskehittimen graafisella käyttöliittymätyökalulla valintalistan kirjausnäkymään polttoainetyypin valintaa varten. Jotta valintalistaan saadaan valittavat arvot, ne täytyy löytyä jostakin. Luon tietokantaan erillisen taulun polttoainetyypeille, syötän sinne manuaalisesti tietokannanhallintatyökalulla arvot polttoaineille: 98E, 95E ja varmuuden vuoksi tulevia tarpeita ennakoiden myös Dieselille. Päivitän vielä vanhoille kirjauksille valmiiksi linkin 95E-polttoaineeseen, jotta kannan data säilyisi eheänä kannan rakenteen muutoksesta huolimatta. Jotta arvot siirtyvät tietokannasta sovelluksen valintalistaan, täytyy palvelinohjelmistoon luoda erikseen REST-rajapintaan palvelu, jota kutsumalla mobiilisovellus saa arvot haettua siirryttäessä kirjausnäkymään ja alustettua valintalistan. Hyvä. Käynnistän päivitetyn palvelinsovelluksen ja päivitän myös Android-sovelluksen puhelimeeni. Nyt kirjausnäytön valintalistaan ilmestyy polttoainevalinnat, mutta itse kirjaukseen valintalistan arvo ei vielä vaikuta.
Takaisin koodin ääreen. Tietokannan taulussa, jonne polttoainekirjaukset tallentuvat, on ainoastaan polttoaineen hintatieto. Jotta kirjausrivin hintatieto saadaan sidottua haluttuun polttoainetyyppiin, tulee linkki polttoainetyyppiin lisätä kirjausriville. Käytännössä tämä vaatii uuden sarakkeen tekemisen tietokantatauluun ja vierasavaimella linkkauksen polttoainetyyppejä kuvaavaan tietokantatauluun ja sinne tallennettuun polttoainetyyppiin. Jotta tieto saadaan välittymään käyttöliittymään, muokataan palvelinohjelmiston REST-palvelua siten, että siihen lisätään tuki polttoainetyypin käsittelylle ja tallennus tietokantaan muun datan mukana. Vastaavasti Android-sovelluksen toimintaa muokataan siten, että käyttäjän käyttöliittymässä tekemä valinta haetaan kirjauksen tallennuksen yhteydessä käyttöliittymäkontrollilta ja liitetään mukaan tallennuspalvelukutsuun.
Päivitän sovellukset ja testaan jälleen tuotoksia. Hyvältä näyttää. Arvot tulevat valintalistaan ja valinta tallentuu tietokantaan kirjauksen mukana oikein. Esittelen ylpeänä tuotostani vaimolleni, joka samalla on perheen toinen sovelluksen loppukäyttäjä. Kokeiltuaan sovellusta itse hän ihmettelee tyrmistyneenä, miksi sovellus ehdottaa 98E-polttoainetta nyt automaattisesti myös hänen autolleen käyttöliittymän oletusvalintana ja ehdottaa, eikö olisi luonnollista, että ajoneuvon oletuspolttoaine on tallennettu ajoneuvon tietojen taakse. Huokaisen… kyllä kyllä, mutta… Selitykseni siitä, että 98E on oletuksena, koska valintalistaan haetaan arvot lisäämisjärjestyksessä ja satuin epähuomiossa lisäämään sen tietokantaan ensimmäisenä, kaikuvat tyhjille seinille. Yksinkertaisen kentän lisäämisen työmäärä lisääntyi juuri merkittävästi.
Avaan jälleen ohjelmakoodit. Tällä kertaa lisään tietokannan ajoneuvotauluun linkin polttoainetyyppiin ja tallennan ajoneuvokohtaisen oletuksen tietokantaan. Mobiilisovelluksen puolelle lisään ajoneuvojen ylläpitotoimintoon samanlaisen polttoainetyypin valintaruudun kuin polttoainekirjausnäkymäänkin ja teen vastaavat muutokset toiminnon aukaisuun sekä ajoneuvotietojen tallennukseen mobiilisovellukseen ja palvelinsovellukseen. Kiroan mielessäni, että lähdin ylipäätään muokkaamaan sovellusta, mutta jospa muutos olisi nyt viimein saatu maaliin. Vaimoni kokeilee sovellusta tällä kertaa tyytyväisen oloisena. Oikea polttoainetyyppi on nyt kirjausnäkymässä automaattisesti valittuna ajoneuvon perusteella.
Olen jo sulkemassa tietokonetta, kun hän kääntyy ja kysyy viattomasti: ”Mitäs sitten, jos meille tulee vaikka kaasuauto? Mites mä saan sen lisättyä tänne polttoainevalintoihin?”
Summa summarum
Oman elämän esimerkin tarkoituksena oli konkreettisesti osoittaa, että aluksi erittäin pieneltä tuntuva muutos yksittäisessä toiminnossa saattaakin vaatia laajempia muutoksia järjestelmään. Tämänkin muutoksen parissa ilta venähti lopulta aamun pikkutunneille. Tämän sovelluksen järjestelmä on äärimmäisen yksinkertainen. Sen sijaan muutosten hahmottaminen esimerkiksi toiminnanohjausjärjestelmän kontekstissa on huomattavasti haasteellisempaa, sillä yksittäisiä käsitteitä on paljon (esim. myyntitilaus, nimike…) ja niitä käsitellään monipuolisesti useissa eri toiminnoissa. Lisäksi parametrien avulla yksittäisen toiminnon käyttäytymistä voidaan mukauttaa lukuisten eri toimialojen ja yritysten tarpeisiin. Yleensä asiakas näkee oman toimintamallinsa kautta vain muutaman näistä monista eri toiminnoista ja niiden variaatioista, mutta kun lähdetään tekemään kehitystä tuotteistettuun järjestelmään, tulee toimittajan kyetä huomioimaan vaikutukset niissä kaikissa.
Yksi tärkeä ero vertailtaessa harrasteprojektiani kaupallisen tuotteen kehittämiseen ja pohdittaessa niihin liittyviä työmääriä on huomioida, että oman sovelluksen kehityksessä ei sovellettu käytännössä juurikaan kaupallisen tuotteen kehitykseen liittyviä, ohjelmistotuotannon prosesseihin liittyviä käytäntöjä. Esimerkiksi laadun varmistukseen liittyvät asiat, kuten ohjelmiston automatisoitujen yksikkö- ja integraatiotestien toteutus ohitettiin, kuten myös toiminnon toiminnallinen määrittely ja muutoksen dokumentointi. Sama pätee myös julkaisu- ja versiointikäytäntöihin.
Yksi ohjelmointityön luonteeseen liittyvistä haasteista on, että vaikka alkuperäinen toteutus olisi omaa käsialaa, vaatii koodin haltuunotto myöhemmässä vaiheessa yllättävän paljon aikaa, ennen kuin varsinaisiin muutostöihin asti päästään. Muiden toteutusta, laajempaa kokonaisuutta tai ennalta tuntematonta järjestelmänosaa muokattaessa tämän perehtymistyön osuus muodostaa jo merkittävän osan pienen muutostyön kokonaistyömäärästä. Tätä työtä voidaan verrata esimerkiksi konepajateollisuudessa tuotantoprosessissa koneille vaadittuun asetusaikaan, jonka aiheuttamat kustannukset pienissä tuotantosarjoissa muodostavat suhteettoman suuren osan tilauksen kokonaiskustannuksista. Ohjelmistokehityksen työstä iso osa onkin toimialaan vihkiytymättömälle näkymätöntä, mutta siitä lisää myöhemmin omassa kirjoituksessaan.
Itse sovelluksesta
Entä, mitä polttoaineseurantaa tekemällä olen vuosien varrella oppinut? Yksi mielenkiintoinen näkökulma on tankkaustapahtumiin perustuva polttoaineen hintakehityksen seuranta ja hinnan vaihtelu vuosien varrella.
Esimerkiksi COVID-19-epidemian seurauksena E95-polttoaineen hinta putosi alimmilleen sitten vuoden 2009! Tilastojen kautta päästään kiinni myös ajoneuvojen todelliseen keskikulutukseen ja karkeaan käytön jakautumiseen eri ajanjaksoilla. Lisäksi tankkausten kautta polttoaineisiin valuneet autoilun suorat kustannukset ja ympäristövaikutukset nousevat konkreettisesti esiin. Esimerkiksi omalta kohdaltani viimeisen kymmenen vuoden aikana polttoainetta on eri ajoneuvoihin kulunut yhteensä kokonaisen säiliörekan verran!