21.06.2018Blogi

Clojurea ja tietokantamagiaa – työssäoppimista Solitalla

Aloitin Oulun Solitalla ohjelmistokehittäjänä loppuvuodesta 2014. Olin siihen asti tehnyt pitkään mobiilijuttuja sekä jonkin verran Javaa ja melko uusia frontend-tekkejä.

Solitalle siirtyessäni toivoin pääseväni osaksi rentoa työyhteisöä, jossa on mahdollista saada omaan ammatilliseen kehitykseen vetoapua itseään kokeneemmilta tekijöiltä. Halusin nähdä konkreettisesti miten suuria digitaalisia palveluita kehitetään ja monitoroidaan ja miten ihmeessä ne saadaan pysymään lähes aina pystyssä ja kestämään kuormaa.

Kerron tässä joitakin kokemuksiani mitä ja miten olen työssäni oppinut.

Vuoden 2014 lopussa aloitimme Oulun toimiston ensimmäisen projektin, Liikenneviraston Harjan. Sain heti alussa muutaman mahtavan tiimikaverin ja Harjaa alettiinkin heti suunnittelemaan tiiviissä yhteistyössä asiakkaan projektiryhmän kanssa. Parin kuukauden ajan kävimme Oulusta Helsingin Pasilassa lähes viikoittain tapaamisissa, jossa keskustelimme asiakkaan kanssa järjestelmän keskeisistä vaatimuksista.

Roolini hankkeessa oli papereiden mukaan frontend-kehittäjä, eli suomeksi sanottuna ajattelin tekeväni enimmäkseen Javascriptiä ja CSS:ää selainkäyttöliittymän toteuttamiseksi. Kuitenkin aika pian huomasin onnekseni, että tällaiset lokeroinnit sain Solitalla heittää romukoppaan.

”Kaikki saa tehdä kaikkea mitä osaa ja haluaa” -ajatusmalli oli tiimissämme vahva ja kävikin selväksi että kukaan ei ylhäältä päin tullut painamaan jarrua siihen, mitä kukin saa tai ei saa tehdä.

Järjestelmän määrittelyn tarkennusvaiheessa huomasimme, että päästäksemme asiakkaan kanssa parempaan yhteisymmärrykseen vaatimuksista tarvitsimme hyvien keskustelutaitojen tueksi myös visuaalisia koevedoksia. Olin jo ennen Solitaa saanut työskennellä tiiviissä yhteistyössä taitavien käyttökokemussuunnittelijoiden kanssa, joten tartuin mahdollisuuteen ja aloin osaavien UX-suunnittelijoidemme tukemana itsekin piirtää vaatimusten ja keskustelujen pohjalta niin sanottuja rautalankamalleja Balsamiq-työkalulla. Näiden nopeiden ja karkeiden demojen avulla hahmoteltiin sovelluksen asioita ja yksityiskohtia, joita asiakas meille kuvaili haluavansa. Aika nopeasti opin Balsamiqin metkut ja uusia rautalankoja olikin sitten nopea tehdä.

Varsinaisten käyttöliittymäasiantuntijoidemme kanssa ratkaisuja sparraillessa kuulin muistakin vastaavista suunnittelutyökaluista, ja mitkä olivat kunkin työkalun hyviä ja huonoja puolia. Säästimme paljon asiakkaan aikaa, kun ominaisuudet pystyttiin käymään läpi ruudulla sen sijaan että olisimme yrittäneet aina keskustella abstraktilla tasolla. Malleja paranneltiin kunnes päästiin yhteisymmärrykseen eri osa-alueiden tarvittavista ydintoiminnallisuuksista. Rautalankamallit toimivat projektin ensikuukausina hyvänä pohjana myös itse kehitystyölle.

Suunnitteluvaiheen rautalankamalli Harjan Tilannekuvasta, jota käytettiin keskustelun tukena yksityiskohtaisempien vaatimusten selvittämiseksi.

Hankkeen alkuvaiheessa pääsin myös tekemään lukuisia käyttäjähaastatteluja ELY-keskuksissa ja urakoitsijoiden luona. Näiden haastatteluiden merkitys lopputulokseen oli varsin suuri, eikä käsittääkseni mikään korvaa sitä että järjestelmäkehittäjät menevät oikeasti tulevien loppukäyttäjien luokse kyselemään ja selvittämään mitä arkisia ongelmia oikeasti ollaan ratkaisemassa. Nämä kohtaamiset eri organisaatioiden asiantuntijoiden kanssa saivat minut usein myöhemminkin muistamaan kenelle ja miksi järjestelmää kehitimme. Tällainen esiselvitys paitsi antoi merkittävästi lisätietoa asioista, myös paransi tiimin motivaatiota ja omistajuuden tunnetta. Jälkikäteen ajateltuna näitä haastattelukäyntejä olisi varmasti kannattanut tehdä vieläkin enemmän.

No entä sitten itse koodaaminen?

Heti hankkeen alussa kävi ilmi että toinen tiimimme alkuvaiheen ohjelmistokehittäjistä ja projektin pääsuunnittelija Tatu olikin varsinainen Clojure-setä.

Olin toki aiemminkin kuullut jotain Clojuresta ja vilkuillut aiheen tiimoilta blogeja, mutta käytännössä en vielä ymmärtänyt mikä tässä oli niin ainutlaatuista. Aiemmin käyttämäni ohjelmointikielet olivat tuntuneet mukavilta ja tehokkailta, enkä osannut kuvitella että tekemällä koodia täysin eri paradigmalla voisin päästä vielä parempaan lopputulokseen ja tekemisen nautintoon. Onneksi Tatun Clojure-innostus oli vahvaa ja hän tiesi teknologian olevan jo kypsä tuotantokäyttöönkin, niin päätimme tehdä Harjan kokonaisuudessaan Clojurella. Tietokannaksi valitsimme avoimen lähdekoodin PostgreSQL:n ja selainpuolen karttakirjastoksi lopulta OpenLayersin.

Harjan Tilannekuva-toiminto käyttöliittymässä ja vastaavaa Clojure-toteutusta

Clojure alkoi avautua minullekin funktio funktiolta

Projektin alkuvaiheessa päivät kuluivat kuin siivillä, kun uutta opeteltavaa oli niin paljon ja samalla työstimme asiakkaan kanssa vaatimuksia eteenpäin. Kuitenkin kun into tekemiseen oli kova, Clojure alkoi avautua minullekin funktio funktiolta, ja jossain vaiheessa huomasin ettei Tatua tarvinnut enää vaivata peruskysymyksillä. Sitten kun vastaan tuli jokin syvempi ja haastavampi tietorakenne, murskattiin sitä usein parikoodauksena, mikä oli todella opettavaista ja mukavaa. Haastavissa datan käsittelyissä Clojuren vahvuudet pääsivätkin kunnolla esiin. Selainpuolelle toin pinoon jotain ennestään tuttuakin kun tyylit teimme käytännöllisellä LESS:llä ja layoutin responsiiviset rakenteet (scaffolding) Bootstrapillä. React-viitekehyksen ClojureScriptille tehdyn rajapinnan, Reagentin, käyttö frontissa tuntui niin ikään varsin nopeasti luontevalta: sama vanha DOM hyvine ja huonoine puolineen siellä oli lopulta vastassa, ihan kuten Javascriptillä tehdessä.

Projektin edetessä yksi Harjan perusvaatimuksista oli tehdä tien hoidon urakoiden laskutusraportti. Laskutusraporttiin haettiin tietokannasta käytännössä kaikki urakan kustannuksiin vaikuttava tieto tietyltä aikaväliltä. Päätimme kokeilla tiedon hakemista raportille kokonaisuudessaan yhden tietokantakyselyfunktion eli niin sanotun stored proceduren avulla. Sprocien avulla voidaan käytännössä ohjelmoida SQL-tiedostoon hallintarakenteita, tehdä silmukoita ja monimutkaisiakin laskentoja siirtymättä palvelimen kontekstiin.  Projektin mittaan tuo Laskutusyhteeveto-funktio on kasvanut jo yli 600 rivin mittaiseksi monsteriksi. Tiimiin myöhemmin liittyneet nuoremmat kehittäjät ovatkin joskus haastaneet oliko perusteltua kirjoittaa tuo kaikki logiikka kokonaisuudessaan yhteen funktioon. Luultavasti pilkkomalla se pieniin osiin olisi päästy parempaan luettavuuteen, ehkä tarkempaan testattavuuteenkin; toisaalta tekemällä kaikki laskenta samassa funktiossa tiettyihin tauluihin tarvittiin vähemmän kyselyitä tai liitoksia (join), koska funktion silmukka oli valmiiksi oikeassa kontekstissa (kustannuksen toimenpide ja urakka). Kyselyiden taulut tarkasti indeksoiden päästiin myös suureen tietomäärään nähden melko nopeaan suorittamiseen ja itse kyselyn helppoon testattavuuteen sekä automaattitestein että tarvittaessa käsin SQL-tulkista. Usein ohjelmistokehityksessä onkin monta eri tapaa päästä haluttuun lopputulokseen.

Aiemmin olin itse kirjoittanut tietokantapuolelle lähinnä yleisluontoisia kyselyitä Oracle-kantaa vasten. Harja-projektin myötä olen päässyt tekemään lukuisia SQL-funktioita, cachetauluja ja niiden invalidointeja ja triggereitä, custom-tyyppejä, monenlaisia indeksejä ja rajoitteita, PostGIS-geometrialaajennoksen käyttöä jne. Tulipa myös konvertoitua ja tuotua Harjaan aimo annos vanhojen urakoiden dataa Harjaa edeltäneestä järjestelmästä.

Koska olen ollut pitkään mukana Harja-hankkeessa, olen saanut nähdä valittujen ratkaisujen vaikutuksia suorituskykyyn ja skaalautuvuuteen kun järjestelmän tietomäärä on kasvanut. On eri asia testata toimintoja 10 rivillä testidataa kun myöhemmin tuotannossa taulusta löytyykin jo kymmenen miljoonaa riviä. Monitoroinnissa olemme käyttäneet apuna mm. New Reliciä ja Grafanaa. Vasta konkreettisten ongelmatilanteiden myötä olen alkanut hieman paremmin ymmärtää tietomallinnusta, ja ennakoimaan mikä taulu tulee mahdollisesti olemaan sovelluksessa pullonkaulana ja miten haut ja indeksoinnit olisi syytä rakentaa. Hankkeen aikana olemmekin joutuneet refaktoroimaan osaa suurimmista tietokantatauluista, jotta sovelluksen sujuva toiminta on pystytty turvaamaan. Ongelmatilanteessa taustatukea ja vinkkejä sain Solitan parhailta tietokantojen erikoisosaajilta: kyselyiden analysointi ja sieltä erilaisten tehottomuuksien bongaaminen olivat aluksi itselleni vierasta, mutta nämäkin asiat ovat tulleet hankkeen aikana rutiininomaiseksi osaksi kehitystyötä.

Oppimiseni Harjassa ei ole rajoittunut pelkästään ohjelmointiin 

Myös sovellustukea on tullut tehtyä yhtaikaa kehitystyön kanssa. Olemme tiimin kanssa parantaneet jatkuvasti kehitysmenetelmiämme sekä säätäneet hankkeen testi- ja tuotantoympäristöjen infraa. Testipalvelinten ja CI:n käytössä tutuksi ovat tulleet mm. Ansible, Docker, Vagrant, Upcloud, CircleCI, Travis ja nyt viimeisimpänä projektin Slack-kanavan kautta testattavan uuden ominaisuuden (git-haaran) vaivaton toimittaminen AWS:n EC2:een. Jo käytössä olevia ratkaisuja on siis paranneltu tiimin arjen tarpeiden mukaan.

Harjan kehitys on ollut viime vuosina suuri voimanponnistus, joka itsessään on tarjonnut valtavasti uutta opittavaa minulle. Olen kuitenkin arkisen asiakastyön ohella ehtinyt välillä osallistua myös Solitan sisäisiin tietoiskuihin ja koulutuksiin, pienempiin devaajatapahtumiin ja jopa konferenssimatkoille. Koska meillä asiantuntijat itse kouluttavat jatkuvasti toisiaan, pysyy koulutustarjonta ajantasaisena ja näin on mahdollista ystävystyä samoista asioista kiinnostuneiden työkavereiden kanssa.

Tässä pähkinänkuoressa tärkeimpiä oppejani ensimmäisestä Solita-projektistani:

  • Ennen koodaamista ja sen aikana kannattaa käydä tulevien loppukäyttäjien kanssa asioita läpi eli mitä ongelmia ohjelmistolla halutaan ratkaista tai mitä prosesseja parantaa
  • Clojure-ohjelmointikielen oppiminen sekä frontendin että backendin kontekstissa
  • OpenLayers-karttakirjaston käsittely selaimessa ja geometriatiedon hallinta tietokantatasolla (PostGIS)
  • Monipuoliset PostgreSQL-tietokannan käsittelytaidot
  • Balsamiqin ja muiden vastaavien suunnittelutyökalujen käyttö karkean tason rautalankamallinnuksessa
  • Kehitys- ja testiympäristöjen virtualisointi (Vagrant, Docker), palvelinten provisiointi ja testattavien ominaisuuksien ketterä toimittaminen git-haarasta pilvipalveluhiin (Ansible, Upcloud, AWS)
  • Tuotannossa olevan järjestelmän suorituskyvyn monitorointi (Grafana, New Relic)
  • Suuren tietomäärän aiheuttamien SQL-kyselyiden suoritusongelmien paikantaminen ja korjaaminen
Jarno Väyrynen työskentelee Solitalla ohjelmistokehittäjänä ja kehitystiimin esimiehenä.

Harja-projektin koodia pääset katsomaan GitHubista.