neljapäev, 25. aprill 2019

Minu JustOn



Tere kõigile!

Minu esimene sissekanna siia blogisse. Ei hakka lubama, et ka viimane.

Kirjutan siin eelkõige oma praktikakogemusest firmas JustOn ning mitte olmest ja vabal ajal läbitud seiklustest. Viimastest on teised juba raporteerinud. Kui mõni lugeja veidral põhjusel veel Kristjani postitust bratwurstimuuseumi kohta pole lugenud, siis tee endale teene ja hakka kohe lugema. Loe mitu korda.

Kuna täna on minu praktikaperioodi eelviimane päev ja kuigi palju sisulist tööd enam ei toimu, siis võin sellise veidi tagasivaatava postituse kirjutada. Mida tegema pidin, mida teha kavatsesin ja mida tegelikult tegin. Ja mida minuga tehti.

Image result for juston

Esiteks põgusalt ettevõttest. JustOn on 2010. aastal alguse saanud SalesForce platvormil töötav pilvepõhine B2B SaaS ettevõte, mis hõlbustab ja automatiseerib arvete koostamist ning haldamist. Nende kliendid on SalesForce'i kasutavad suuremad ja väiksemad erinäolised firmad üle kogu maailma. Neid firmasid ühendab see, et kõik nad soovivad arvetega tegelemisele võimalikult vähe aega kulutada ja selle asemel millegi sisulisemaga tegeleda.

JustOnis töötab kokku ca 20 inimest. Arendajaid nendest oli praktikaperioodi alguses neli, lõpus kolm. Üks otsustas vahepeal, et tahab midagi muud teha. Ehk siis pigem selline väike ettevõte. Selle vastu mul ei ole küll midagi - näeb protsesse ehk pisut lähemalt kui mõnes korporatsioonis oleks näinud. Niipalju kui olen aru saanud, siis enamik IT-ettevõtteid Jenas ongi pigem väiksed või keskmise suurusega. Aga neid on selle-eest palju ja tundub, et selle olukorraga ollakse rahul. Vähemalt JustOnis ei tekkinud tunnet, et tahetakse hullult kiiresti hambad ristis unicorniks saada. Pigem tundus olevat rõhk rahulikul aga stabiilsel kasvul.

Nagu juba mainitud, siis JustOni arendajad ise loovad tarkvara SalesForce platvormile ja see on selline võrdlemisi eraldiseisev süsteem, millel programmeerimiseks kasutatakse APEX keelt. APEX meenutab natuke Javat - strongly typed OOP keel. Mina seda siiski õppima ei asunud. Kuna JustOn põrgatab mõtteid veidi kaugemas tulevikus SalesForce'st sõltumatuks saada, siis kompavad nad selleks tasahilju maad - uurivad, mis on võimalik ja millise ajakuluga.
Mind rakendatigi just sellel eesmärgil. Minu praktikaülesanne oli luua prototüüp eraldiseisvast teenusest, mis looks HTML koodi põhjal PDF faili.

Firmas oli mõnda aega tagasi juba olnud üks teine praktikant, kes oli selle ülesandega tegelenud ja jõudnud järeldusele, et kõige mõistlikum vahend PDF-genereerimiseks on Puppeteer - Node'i teek, mille abil saab progremmaatiliselt kontrollida Google Chrome'i veebilehitsejat. Kõik lugejad on ilmselt Chrome'i kasutanud. Selles on võimalus printida veebilehti või neid ka PDF-na salvestada. Seda võimalust mina ära kasutama pidingi, JavaScripti abil.

Esialgne nõu oli kirjutada Node's selline REST API, millele saab saata HTML koodi ja mis vastab selle HTML'i põhjal koostatud PDF dokumendiga. See tähendas API serveri loomist ja vastava endpointi defineerimist. Kuna Puppeteer jookseb Node'i runtime's, siis tundus igati loogiline ka ülejäänud rakendus selles kirjutada. Kuigi mul Node'ga varasemalt kokkupuudet suures osas ei olnud, siis JavaScript, programmeerimiskeel, mida Node's kasutatakse, oli juba kohati koduseks muutumas. Tänu sellele sain suhteliselt kiiresti ka Node's maast lahti ja tiivad laiali.

Image result for asynchronous meme
Node's on mõnus kirjutatada asünkroonset JavaScripti

Selleks, et kiiresti vajaminev server üles seada, kasutasin Node'i veebiraamistikku Express. Et serveripoolse JavaScripti põhitõdedest aru saada kulus küll mõni päev, aga peale seda mõistsin, kui kergeks Express kogu protsessi teeb. Vaesed veebiarendajad, kes pidid kunagi ennemuistsel aal ilma kõigi nende moodsate tööriistadeta serveritarkvara kirjutama. Olen õnnelik, et olen elus aastal 2019. PDF-teenuse prototüübi v0.1 oli selline, mis töötas ainult minu arvutis ja suutis kohaliku HTML faili tagasi kohalikku failisüsteemi PDF'na salvestada. Kusagilt peab ju alustama.

Praktika kolmandal päeval andis mu juhendaja Alex mulle kiire miniloengu teemal HTTP päringud ja vastused. See ei olnud tegelikult kuigi mahukas ja aus olles rääkis ta väga vähe sellist, millest ma üldse kuulnud ei oleks olnud, aga ta suutis kogu vajaliku info väga hästi kokku siduda ja lihtsasti hoomatavaks muuta. Tundsin selgelt, kuidas hea juhendaja suudab õppimisprotsessi oluliselt kiirendada - tänapäeval on kogu mõeldav info ju internetis olemas, aga selleks, et seda infot efektiivselt hallata ja leida, võib üksinda kuluda kasutult palju aega.

API ja HTTP päringute testimiseks õppisin kasutama Postmani, mis ongi just sellisteks toiminguteks mõeldud.
Edasiminek API arenduses: kui saata sellele POST request, mille sisu on HTML kood, tagastab API PDF faili, mille sisu ühtib päringu HTML-ga. Lahe, mõtlesin ma. Olen suure töö ära teinud, mõtlesin ma. Tegelikult aga suur töö alles algas.

Image result for asynchronous meme
Kui saad aru, et stream ja buffer on sõnad, millel on tähendus.

Kuna esialgsed nõuded olid sellega seoses täidetud ja aega ei olnud liiga palju kulunud, siis anti mulle uued vihjed, kuhu suunas võiksin arendusega liikuda.

Esiteks asusin oma koodi testima. JavaScripti testimisteeke on mitmeid. Peale võimaluste uurimist otsustasin kasutada Jesti, sest selle veebileht nägi lahe välja.

Kirjutasin mõned funktsionaalsed ja integratsioonitestid, et veenduda mu koodi töötamises ja eesmärgipärasuses. Lisaks õppisin ka teste kirjutama. Koolis sai küll sedagi tehtud, aga vähe. Ja lisaks, eks need testid olid pigem formaalsused, sest tegu on siiski prototüübiga ja koodi, mis peaks ja saaks testida, seal kuigi palju ei olnud.

Image result for javascript testing meme
Testing is important but working application is importanter

Peale seda esitleti mulle järgmist nõuet. Kui siiani genereeris Puppeteer PDF'i harilikust HTML dokumendist, siis tegelikult võiks see toimuda natuke teisel põhimõttel. Nimelt võiks HTML tekkida mõne template engine'i abil. Ehk siis minu teenus saaks sisendiks mõne malli ja andmed, mida mallile lisada. Nende kahe põhjal koostataks HTML ja sealt edasi siis juba tuntud rada pidi PDF. Mallidega töötamise keeli on palju ja erinevaid, aga kõigil neil on suhteliselt sarnased võimalused ja tööpõhimõtted. Mina pidin nendest ühe, mida oma prototüübi juures kasutama, valima. Testisin põgusalt kahte erinevat templatating engine't: Handlebars ja Liquid. Handlebarsi poole kallutas mind selle populaarsus ja sellest tulenevalt hea dokumentasioon. Liquidit mainis mulle mu juhendaja. See on algselt Shopify platvormi jaoks loodud Rubyl põhinev keel, millega on mugav Shopify keskkonnas poode ja muud haldamist vajavat hallata. Sellest on siiski loodud ka Node'ga ühilduv JavaScripti versioon Liquid.js. Lähemal uurimisel ja nende kahe võrdlemisel selgus, et Liquid toetas teatud vajalikke filtreid kuupäevade kuvamiseks, mille Handlebarsis oleks pidanud ise kirjutama. Ratast pole mõtet leiutada ning seega asusin tööle selle kallal, et Liquid sobivad andmed õiges kohas õigel moel esitaks.

Töötamine Liquidi ja mallidega oli üle ootuste lihtne ja sain toimiva lahenduse valmis üsna kiiresti. Kindlasti oli seal palju erijuhte, millega ei arvestanud ja mis päriselt toimiva teenuse puhul võiksid tekitada probleeme ja pudelikaelu. Samas rõhutas minu juhendaja korduvalt, et tegu on prototüübiga ja liigselt detailidele keskenduda pole mõtet. Nõustusin sellega ja lähtusin, nagu ka muidu oma elus, 80/20 reeglist.


Järgmine nõue oli see, et PDF arve peal oleks kuvatud leheküljenumbrid vormis "Lehekülg 1 / 5". Ehk siis igalt lehelt peaks saama lugeda nii seda, mitmes hetkel käesolev leht on ja lisaks seda, mitu lehte on kogu arves kokku. Ja seda kõike erinäoliste stiilidega - erinevad fondid, kirjasuurused, võimalikud asukohad leheküljel jms. See kujunes üheks suurimaks (aga ka põnevamaks väljakutseks) kogu praktika jooksul. Väike ja näiliselt lihtne probleem, kuid, nagu lõpuks selgus, väga raske elegantselt lahendamiseks. Selleks, et hakata aru saama, kust leheküljenumbrid lehtedele saavad, pidin lugema päris suure koguse materjale CSS paged media ja print CSS teemadel. Kui CSS-i kasutatakse tavaliselt veebilehtede kujundamiseks, siis selles on eraldi reeglid juhtudeks, kui mingit dokumenti välja prinditakse. Mina selliste atribuutidega varem kokku ei olnud puutunud ja uut ning huvitavat oli rohkelt. Paraku selgus, et kui varem oli võimalik üsna lihtsasti kuvada CSS abil ka kogu dokumendi lehtede arvu, siis enam see võimalik ei ole. Seega selle probleemi parimaks lahenduseks jäi Puppeteeri sisseehitatud võimalus leheküljed enne PDF-ks teisendamist nummerdada. See aga tähendas seda, et leheküljenumbrid saavad olla ainult dokumendi päises või jaluses, mitte aga sisu keskel, nagu teatud arvete puhul võib soovitud olla. Kõik probleemid ei saagi alati täiuslikku lahendust ja sellises olukorras on tähtis osata minna lasta.

Edasi minnes visati mu rajale järgmine tõke. Pidin uurima, kas HTML-i, millest saab PDF, on võimalik lisada nö manustatud pilte ja fonte. See tähendaks vähem võrgutaotlusi ja seega ehk kiiremat andmetöötlust. Harilikult on piltide ja fontide lähtekood kusagil kaugemas serveris, mida HTML dokument siis vajadusel tülitab ja palub andmed endale saata, et neid lehe kuvamisel kasutada. See kõik võtab aega. Manustatud ressursside korral on andmed teatud alust kasutades HTML-i juba sisse kodeeritud ja neid ei pea kusagilt väljaspoolt otsima või küsima. Peale veidikest katsetamist tundus see lahendus päris hästi toimivat, kuigi HTML-failid/mallid muutusid üsna pikaks ja tegid arvuti üsna kuumaks.

Allolevas videos on näha üks fondifail base-64 kodeeringus osana ühest HTML failist.



Järgmisena integreerisin Puppeteeri ja Liquidi mallid, niimoodi, et kogu arvutamine tehtaks ära nö ühekorraga, ühes jadas. Selle käigus kirjutasin koodi ka natuke ümber, et vigade jälgmist lihtsamaks ja täpsemaks muuta. Alex andis sealjuures häid vihjeid, kuidas seda parimal viisil teha.

Kuna selleks hetkeks olid suuresti kõik funktsionaalsed nõuded täidetud, siis jätkasin koodi paiskamisega (deployment) serverisse, kus seda saaksid ka teised testida ja/või kasutada. Mulle soovitati kasutada selleks Heroku platvormi. Enne veel kui oma koodi "üles sain lükata", pidin selle kapseldama Dockeri konteinerisse. Selline on tänapäevane viis koodi internetis jagada - garanteeritud on sõltumatus keskonnast, kuhu kood on majutatud. Kuna ma ei olnud varem Dockerit kasutanud, siis pidin enne kasutamist üsna suures mahus ennast harima, aga peale ennast põhiideedest läbi närimist läks kõik üsna sujuvalt. Ja enne kui isegi aru sain, elas minu loodud PDF-teenus Heroku pilves, valmis vastu võtma päringuid mallide ja andmetega ja tagasi saatma PDF dokumente.

Image result for docker meme
Sellised olukorrad peaks Docker välistama

Kuna mul oli veel pisut aega üle, siis palus Alex mul uurida võimalust genereeritavatele arvetele vajadusel QR kood lisada. See muutub Šveitsis järgmisest aastast kohustuslikuks, seega on mõistlik sellega arvestada. Arvel olev QR-kood peab endas sisaldama infot vajaliku makse kohta: saaja, kontonumber, kuupäev, metadata jms. Otsisin Node'i mooduleid, mis võimaldaksid QR-koodi loomist ja leidsin meeltpainutavalt loova nimega mooduli qrcode. Kui qrcode'i abil QR-kood loodud, tuli see lihtsalt mallis sobivasse kohta paigutada, kasutades jällegi manustatud pildiandmeid. Lihtne.



Sellega seoses jõuamegi nüüd käesolevasse hetke, mil kirjutan blogipostitust tehtust. Oli meeldiv. Nukid sellele, kes kogu ülalseisva tekstiseina läbi jõudis lugeda, kahekordsed nukid sellele, kes seda ühe jutiga tegi. Vabandust, kui kõik või osa tekstist segaseks jäi. Küsimuste ja kommentaaride jaoks on siin Bloggeris ka vist mingi koht, seda julgustan kasutama.

Kokkuvõtteks praktika kohta. Loomulikult õppisin palju tehnilisi oskusi ja uusi teadmisi, aga neid on võimalik ka omal käel omandada, lihtsalt aega kulub ilmselt rohkem, kui pole kelleltki targemalt küsida. Minu arvates hoopis tähtsam kogu protsessi juures oli võimalus näha ja teatud määral osaleda tarkvarafirma igapäevatöös, suhelda tarkade inimestega, küsida (tihti veidi sinisilmseid) küsimusi (tihti ebaoluliste) asjade kohta. Igal hommikul kell 9:30 kohtus kogu meeskond püstijalakoosolekul, kus kõik jagasid, mida nad eile saavutasid ja mida täna kavatsevad korda saata. Tänu sellele tekkis mul mingi hägune ettekujutus, kuidas ja mis põhjustel JustOni erinevad osakonnad omavahel infot vahetavad ja koos töötavad. Firma arendusmeeskond oli äärmiselt ühtehoidev ja kõik arendajad olid nutikad ning sõbralikud inimesed, kellelt oli palju õppida. Keerulisemaid probleeme lahendati alati koos ja üksteise tegemiste vastu tunti huvi. Usun, et see on ainus mõeldav viis head tööd teha ja tarkvara luua. Olen väga tänulik, et sattusin niivõrd lahedasse firmasse praktikale.

Aitäh veelkord ja hüvasti
Gabriel

Kommentaare ei ole:

Postita kommentaar