Kuntoon laitettu koodi on merkittävä kilpailuetu
Sovelluskoodin optimointi säästää aikaa ja resursseja tulevassa kehitystyössä, mutta parantaa myös itse sovelluksen käyttökokemusta. Toteutimme yhdessä Brellan kanssa heidän tapahtumaverkostoitumispalvelunsa datanhakukoodin refaktoroinnin, erinomaisin tuloksin.
Onko kiire? Lue tiivistelmä projektin tavoitteista ja hyödyistä.
Sovelluskehitys on yllättävän luovaa työtä. Esimerkiksi yleisesti verkkosivustoilla ja sovelluksissa käytettävä ohjelmointikieli JavaScript mahdollistaa saman asian tekemisen monella tavalla. Kun kehitystiimin pääluku kasvaa, on sovelluksen koodi jossain vaiheessa elinkaartaan päässyt rönsyilemään jo pahasti. Tämän seurauksena virheiden paikantaminen ja korjaaminen sekä uusien ominaisuuksien mukaan tuominen on yhä työläämpää, monimutkaisempaa ja kalliimpaa.
Onneksi tähän on olemassa lääke, koodin refaktorointi. Tämä tarkoittaa koodin muokkaamista ilman, että sovelluksen ominaisuudet muuttuvat mitenkään. Loppukäyttäjien vinkkelistä kaikki pysyy samanlaisena, lukuun ottamatta sovelluksen parantunutta nopeutta ja toimintavarmuutta. Koodin yksinkertaistaminen ja yhdenmukaistaminen palvelee sovelluksen kehittämistä, tehden siitä mielekkäämpää ja nopeampaa. Päätavoite on luoda luettavampaa koodia, jonka päälle on helpompi tuoda uusia ominaisuuksia.
Brellalla oltiin pohdittu jo pitkään sovelluksen datanhakukoodin refaktorointia, mutta projektiin oli vaikea irrottaa resursseja täystyöllistetyn tiimin sisältä. Sopivaksi ratkaisuksi osoittautui ostaa koodin uudelleen mietintä ulkoisena toimeksiantona meiltä.
Edut liiketoiminnan kannalta
Refaktorointi voi tuoda merkittäviä säästöjä nopeutuneen sovelluskehityksen myötä. Kun devaajilla menee vähemmän aikaa koodikannan tulkinnassa, bugit ovat nopeampia paikantaa ja ratkaista, ja uusien ominaisuuksien tuominen sovellukseen on helpompaa ja nopeampaa, on kehitystyö kaikkinensa kustannustehokkaampaa.
Refaktoroinnin myötä nopeammin ja luotettavammin toimiva sovellus tarjoaa paremman käyttökokemuksen. Vähemmän bugeja tarkoittaa myös vähemmän tyytymättömiä asiakkaita lähettämässä tikettiä ylläpitoosi.
Lisäksi, ymmärrettävä ja standardinmukainen koodi mahdollistaa sen, että uudet kehittäjät voivat ottaa nopeammin haltuun softan työstämisen. Aiemmin vain harvojen ja valittujen hanskaamaa ymmärrystä koodikannasta voi nyt odottaa junior-tason kehittäjiltä. Tämän seurauksena uudet ominaisuudet voidaan tuoda sovellukseen nopeasti ja tehokkaasti. Ja nopeus on avainasemassa oman kilpailuedun varmistamisessa tai muiden etumatkan kuromisessa kiinni markkinoilla.
Abstraktoinnilla vähemmän virheitä ja huonoa koodia
Refaktorointi toteutetaan osittain abstraktoinnilla. Abstraktointi tarkoittaa sitä, että usein toistuvat koodirakenteet siivotaan esimerkiksi kirjastoihin, eli uudelleen käytettäviksi komponenteiksi, pois varsinaisesta koodikannasta. Tällöin koodin pituus lyhenee huomattavasti ja ennen kaikkea se saadaan yhdenmukaistettua, jolloin sitä on helpompi lukea ja ymmärtää.
Aiemmin esimerkiksi jokaista sovelluksen backendiin lähettämää kutsua varten piti koodata, että miten ja missä järjestyksessä tämä tehdään. Datan haussa voi olla esimerkiksi jopa 10 vaihetta, joissa backendista haettava data muutetaan sovelluksen ymmärtämään muotoon. Devaaja sai päättää itse, minkä niminen funktio on ja minkä nimiseen paikkaan se kutsun datan tallettaa. Ajan mittaan, useiden kehittäjien työskennellessä koodin parissa, tämä johti sillisalaattiin, jota oli todella työlästä ymmärtää.
Abstraktoinnilla koko tämä kutsuprosessi siirretään erilliseen kirjastoon. Abstraktoinnin yhteydessä päätetään yhdenmukaisesta nimeämiskäytännöstä. Brellan tapauksessa esimerkiksi käyttäjätietoja haettaessa datatyyppi nimetään käyttäjäksi ja tallennetaan samalla nimellä sovelluksen välimuistiin. Itse koodissa luodaan kutsu ainoastaan kirjastoon, joka suorittaa datahaun sekä tallentamisen välimuistiin.
Datan tallentaminen välimuistiin on yksi yleisimmistä kohdista React-Redux -sovelluksissa, jossa syntyy koodatessa virheitä, joten sen abstraktointi on tehokas keino vähentää bugien määrää. Abstraktoidulle koodinpätkälle on helppo tehdä omia testejä, joilla varmistetaan sen toiminta. Aiemmin mahdolliset bugit oli jäljitettävä itse koodista ja korjattuasi yhden virheen, saattoi muualla koodissa olla edelleen jäljellä vastaavia bugeja. Kirjastoon tehdyt korjaukset fiksaavat ongelman koko sovelluksessa.
Abstraktointi tekee siis koodista siistimpää ja tiiviimpää, jolloin sen hallinta ja ymmärtäminen on helpompaa. Tiiviimpi koodi on vähemmän altis inhimillisille virheille ja monissa tapauksissa bugit on helppo eristää kirjastoon ja korjata siellä. Myös itse sovelluksen toiminta nopeutuu huonosti toimivan koodin vähentyessä, mutta suurin arvo on säästetyissä tekniikan työtunneissa sekä nopeutuneessa kehitystyössä.
Brellan sovelluksen koodista saatiin siivottua lähes 10 % pois ja tulevien ominaisuuksien datanhakuun ja välimuistiin liittyvästä koodista voidaan jatkossa leikata jopa 75 %, joka nopeuttaa ja yksinkertaistaa työtä merkittävästi.
Rajattu API tehostaa kehittäjien työtä
Brellan koodin abstraktointi lähti liikkeelle konseptitasolla. Kävimme läpi miten dataa haetaan backendista sovellukseen, mitä yhtäläisyyksiä kutsuissa on ja niin edelleen. Tärkeää oli löytää malli, joka toimii kaikissa käyttötapauksissa. Perusteellinen suunnittelu on välttämätöntä projektin onnistuneen toteutuksen kannalta. Brellan tapauksessa tämän pohdinta otti pari viikkoa, jotta olimme varmasti ymmärtäneet optimaalisen etenemistavan.
Oivalluksen myötä testasimme ratkaisutapaa ensin rajatulla, tyypillisellä käyttötapauksella. Vasta kun abstraktoinnin toimivuus oltiin saatu verifioitua, aloimme soveltaa sitä koko koodiin. Suurin haaste oli löytää abstraktio-malli, joka olisi niin yksinkertainen kuin mahdollista.
Tämän johtoajatuksen pohjalta toteutimme APIn, joka avaa frontend-kehittäjille vain heidän tarvitsemansa rajapinnan. Näin hahmotettavien asioiden määrä väheni ja oleelliseen on vastedes helpompi keskittyä. Brellankin käyttämällä Reactilla voi koodata niin monella tavalla ja jos ei ole työskennellyt juuri projektissa käytössä olevalla stackilla, nopeuttaa rajattu API huomattavasti uusien devaajien mukaan tuontia.
APIa ei myöskään ole naitettu tietyn HTTP client -kirjaston kanssa, vaan se on laajasti yhteensopiva, esimerkkeinä Frisbee, Axios ja Superagent. Näin vältetään turhat bugit ja tietoturva-aukot ympäristössä, missä yhden kirjaston tuki ja päivitykset saattavat loppua hyvinkin nopeasti.
JSON:APIn avulla nopeampaa datan hakua
Hyödynsimme myös JSON:APIa yksittäisten datapyyntöjen abstraktoinnissa. JSON:APIn määritysten mukaan backendin pitää palauttaa tietty datatyyppi sovitussa muodossa. Tämän avulla abstraktoimme yksittäisten pyyntöjen logiikan siten, että kun tiedetään minkä tyyppistä dataa saadaan tietystä backendin pisteestä, se voidaan tallentaa suoraan välimuistiin ilman, että sille pitää erikseen kertoa mistä datasta on kyse.
Saimme vähennettyä datapyynnöissä niiden tiedostojen määrää kuudesta kahteen, joihin muutoksia on tehtävä kutsun yhteydessä. Kun koodi on jaettu vain muutamaan paikkaan, on bugien paikantaminen helpompaa ja niiden korjaaminen nopeampaa. Tämä ei suoranaisesti nopeuta sovelluksen toimintaa, mutta vähentää mahdollisuutta tukkia softaa huonolla koodilla. Kehno koodi kun puolestaan saattaisi hidastaa tai epävakauttaa sovelluksen toimintaa.
Paransimme myös datan päivitystä sovelluksen sisäiseen välimuistiin. Brellan backend ja JSON:API toimivat siten, että käyttäjän data on tietyn avaimen takana. Jos pääresurssiin, esimerkiksi käyttäjätietoihin, on linkitetty käyttäjän sopimat tapaamiset, voi tämän lisätiedon palauttaa kutsun included-avaimena tai relaationa.
Automatisoimme tämän lisädatan päivittämisen sovelluksen sisäiseen välimuistiin, joka vähentää backendille tehtyjen hakujen määrää ja pitää sovelluksen frontendissä tiedot entistä paremmin ajan tasalla. Näin sovellus toimii loppukäyttäjällä nopeammin, kun data voi muuttua yhden kyselyn sisällä. Myös kehittäjien työ helpottuu, kun ei tarvitse koodata enää manuaalisesti, että mikä tieto liittyy mihinkin.
Brellan verkostoitumissovellusta käytetään isoissa yleisötapahtumissa, jossa pyyntöjä tulee paljon kerralla. Vaikka backend suoriutuukin kuormasta, voi hitaammalla tapahtumapaikan wifi-verkolla mennä tehtävässä turhan kauan. Tällöin loppukäyttäjälle pienikin parannus nopeudessa voi olla merkittävä.
Tiivistelmä tavoitteista ja tuloksista
Tavoite
- yksinkertaistaa ja yhdenmukaistaa datan hakua backendista
- vähentää tarvittavan koodin määrää
- helpottaa sovelluksen ylläpitoa sekä nopeuttaa uusien ominaisuuksien toteuttamista
Hyödyt
- vähemmän virheille altis koodikanta
- enemmän resursseja käyttöliittymän ja käyttökokemuksen kehittämiseen
- vähemmän epäjohdonmukaisuuksia ja poikkeamia
- nopeammin ja vakaammin toimiva sovellus
- nopeutunut tuotekehitys
Miten
- datapyyntöjen uudelleen ajattelu ja koodin refaktorointi, osin abstraktoinnin avulla ja osin JSON:APIn avulla,
- datahaun/välimuisti-kerroksen APIn rajaus kehittäjille oleellisiin osiin
Tulokset
- uudelleen käytettävien komponenttien kirjasto
- useiden apukirjastojen (Frisbee, Axios, Superagent) kanssa yhteensopiva API,
- koodin määrä väheni lähes 10 %
- datahaun/välimuisti-kerroksen koodi väheni noin 2531 rivillä
- uusien ominaisuuksien toteutuksessa tarvittavan koodin määrä väheni keskimäärin 74.5 %
- uusien ominaisuuksien toteutuksessa tarvittavien tiedostojen määrä väheni kuudesta kahteen
- kunnolla toimiva datan päivitys käyttäjä-välimuistiin