Majasisese teegi loomise ja kasutamise parimad praktikad

Tehnoloogiad

6 minutit

In-house library

Tänapäeval tugineb tarkvaraarendus suuresti teekidele.

In-house library Software library Code quality Autoconfiguration Code duplication

Selles postituses arutleme, millal on mõistlik luua majasisene teek, kuidas seda ettevõttes juurutada, missugust kasu see toob ning mida me õppisime sellise teegi loomisel.

Selleks, et teek oleks rakendatav mitmetes meeskondades ja projektides, peab olema seda mugav kasutada ning see peab aitama lahendama püstitatud probleeme.

Kui meeskonnal on tekkinud vajadus luua teek, mida erinevates projektides kasutada, ei ole alati otstarbekas luua avalikuks tarbimiseks mõeldud teeki.

Olemus

Alustame teegi definitsioonist. Teek on hulk andmestruktuure ja nendega kokku käivat funktsionaalsust, mille kasutusele võtt mingis skripti või koodibaasis loob mingit väärtust. Teegi kasutusevõtt võimaldab arendusmeeskonnal vältida pakutavad funktsionaalsuse taaskirjutamist, mis säästab arenduse aega.

Sellest edasikanduvalt säästab see omakorda projekti ressursse. Teegi pakutav funktsionaalsus on ka läbi kasutatavuse testitud. Eeskujulikud teegi arendajad on ka teeke ise testinud või pakuvad automaatteste, mis võimaldavad teeki testida. See suurendab kasutatava funktsionaalsuse suhtes usaldatavust.

Majasisene teek on mõeldud ennekõige ettevõtte-, meeskonna- või projektisiseste vajaduste rahuldamiseks.

Teegi kirjutamisel on ootused pakutava funktsionaalsuse osas mõneti teised (rangemad) kui konkreetse rakenduse lähtekoodi kirjutamisel. Sellest tulenevalt on teegi kirjutamine ka ressursikulukam kui rakenduse lähtekoodi kirjutamine.

Kui meeskond tahab mingit hulka funktsionaalsust jagada mitme koodibaasi vahel, ei pruugi olla otstarbekas järgida kõiki teegikirjutamisega kaasnevaid parimaid tavasid, mida oodatakse avalikust teegist.

Põhjuseks võib olla suurem arenduskulu, lähenev tähtaeg või meeskonnasisesed kokkulepped, konventsioonid ja standardid, mis võivad olla subjektiivsed. See ei tähenda, et meeskond peaks mõttest loobuma – lihtsalt teek ei peaks olema avalik.

Sellistele teekidele oleme andnud nimetuse: majasisesed teegid. Majasisene teek on mõeldud ennekõige ettevõtte-, meeskonna- või projektisiseste vajaduste rahuldamiseks.

Majasisene teek kui mugandatud lahendus

Kui teek on mõeldud majasiseks kasutamiseks, ei rakendu sellele enam üldtunnustatud nõuded. Autorid võivad mugandada funktsionaaluse kasutamist nii, nagu ettevõtte normatiivid seda ette näevad. See vabadus avab uksed uutele viisidele, kuidas optimeerida kasutamist.

See võib välja kujuneda sellest, milline on vaikeseadistus, millist versioneerimiskonventsiooni kasutada, kuidas lahendada sõltuvused jne. Teades, kuidas konkreetses ettevõttes lähtekoodi kirjutatakse, on võimalik teha eeldusi, mille najal saab teha mugandatud lahendusi.

Majasiseseid teegid ja projektisiseseid teegid on üksteisest eristatavad. Peamine erinevus on see, et majasisene teek ei tohi sisaldada ühegi konkreetse projekti spetsiifikat. Paljudel juhtudel on majasisene ja projektisisene teek sisuliselt sünonüümsed.

Majasisese teegi juurutamine

Teegi kirjutamisel on meil kaks peamist eesmärki – pakkuda nii head lahendust, kui on meie võimuses, ja teha selle lahenduse kasutusele võtmine nii lihtsaks, kui vähegi võimalik. Seejuures peame arvestama erinevate väljakutsete erisusi, mis on spetsiifilised kas konkreetses projektis või rakenduses.

Seetõttu peab olema lahendus paindlik ja seadistatav nii, et arendaja ei peaks sellepärast palju pead murdma. Vastasel juhul loobub arendaja pakutavast lahendusest ja otsib alternatiivi.

Lahenduse kirjutamise ajal mõtleme hoolikalt läbi, mis osad peaksid olema seadistatavad. Mingeid omadusi võimaldame seadistada läbi konfiguratsiooni. Mõningad komponendid võimaldame laiendada.

Selleks kasutame printsiipi composition over inheritance, kus komponendi funktsionaalsust pakutakse mitte läbi päriluse, vaid läbi pistik-komponentide, mille saab väikese vaevaga ise kirjutada täpselt selliseks, nagu tarvis on, ning seejärel asendada see kobmponendis välja.

Et arendajal oleks teegi kasutuselevõtt võimalikult mugav, ei saa üle ega ümber dokumentatsioonist. Dokumentatsioonis tuleb kirja panna, mida iga komponent teeb. Püüda kirjeldada, kuidas funktsionabalsust saab mugandada vastavalt olukorrale. Kirjeldada kõiki seadistusi. Samuti pakkuda näidiseid sellest, kuidas komponente üle kirjutada selleks, et muuta või laiendada funktsionaalsust.

Pidevalt kogudes tagasisidet ja vaadeldes, kuidas teeki kasutatakse, saab teha järeldusi, kas pakutavate lahenduste juurutamine on tehtav või mitte. Sellest tulenevalt on võimalik teeki täiendada ning luua sellest aina paremaid versioone.

Teegi juurutamise protsess

1

Konfiguratsioon

2

Dokumentatsioon

3

Täiendused

Koodikirjutamise parimad tavad

Mistahes koodi kirjutamisel tuleb lähtuda parimatest tavadest. Vähemaga leppimine on lugupidamatu tooteomaniku ja kolleegide suhtes. Teegi kirjutamisel on see äärmiselt oluline, sest teegis kirjutatu saab olema osaks suurest osast koodibaasidest.

Iga komponent koosneb sisuliselt kahest kihist – liides ning sisemine loogika. Tänaseks oleme õppinud neid kihte üksteisest eristama ja sisemist loogikat kasutajate eest peitma. Kui arendajad saavad kasutada funktsioone, mis on mõeldud rangelt komponendi sisemiseks kasutamiseks, võivad nad komponenti väärkasutada ja seeläbi tahtmatult tekitada rakenduse toimimises veaolukordi.

Selleks, et vähendada probleeme, defineerime komponentides konkreetse avaliku liidese, mille kaudu saab komponendiga interakteeruda. Sisemised andmestruktuurid ja funktsioonid peidame ära, et neid ei saaks rakenduse lähtekoodis otse välja kutsuda. Ainult nii saame tagada, et iga toimingu kohustuslikud eel- ja järeltoimingud saavad korrektselt väljakutsutud. Seni kuni avalikku liidest ei muudeta, ei nõua uute teekide versioonide kasutuselevõtt arendajalt suurt pingutust.

Selleks et pakutav funktsionaalsus oleks lihtsasti kasutatav erinevates olukordades, on tähtis jälgida single responsibility printsiipi, millest lähtuvalt omab iga komponent täpselt ühte vastutust.

Kui komponent ei tee täpselt seda, mida kasutaja ootab, võib arendaja komponendi sisemise loogika üle kirjutada nii, et see vastaks tema vajadustele. Tulemusel võidakse kirjutada komponent selliseks, mis ei toimi igas kasutusloos korrektselt ning võib rakenduste töövoos tekitada veaolukordi.

Composition over inheritance printsiip koos adapter mustriga võimaldavad luua komponente, mis on hõlpsalt kohandatavad vastavalt olukorrale. Selleks et pakutav funktsionaalsus oleks lihtsasti kasutatav erinevates olukordades, on tähtis jälgida single responsibility printsiipi, millest lähtuvalt omab iga komponent täpselt ühte vastutust. Komponendi nimest peaks olema kerge aru saada, mida selle komponendiga teha saab. Kui komponent teeb täpselt seda, mida ta nimetus ütleb, on kergem üllatusi vältida.

Automaatkonfiguratsioon ja paindlikkus

Mõned teegid toimivad pistikprogrammidena, mis integreeruvad rakenduse aluseks olevaks raamistikuks. Need teegid kasutavad automaatkonfiguratsiooni, et seadistada end võimalikult vähese vaevaga. See tähendab, et funktsionaalsus aktiveerub automaatselt, kui see lisatakse rakendusse sõltuvusena. See on arendaja vaatepunktist väga mugav lahendus.

Kui teek pakub ühte funktsionaalsust, mida saab autokonfigureerida, siis hallatavusega probleemi ei ole. Kui teek pakub paljusid funktsionaalsusi, siis autokonfiguratsioon peab olema mugavalt kontrollitav. Kui sõltuvus lisatakse ühe komponendi pärast, siis ei tohiks ülejäänud komponendid automaatselt aktiveeruda ega rakendusega liidestuda.

Selleks, et arendajal oleks parem kontroll selle üle, kuidas komponendid autokonfigureeruvad, kasutame funktsioonilippe (feature flag). Niimoodi saab arendaja valida teegi ning Rootsi laua põhimõttel otsustada, mis funktsionaalsusi ta tahab rakendusele lisada. See on arendajate vaatepunktist kasulik omadus, sest paari reaga seadistuses on võimaldatud rakendusele lisada funktsionaalsus, mille nullist välja arendamine võib võtta nädalaid.

Sõltuvuskonfliktid ja nende lahendamine

Teegid sõltuvad sageli teistest teekidest, et uusi funktsioone pakkuda. Need sõltuvused moodustavad sõltuvuspuu – tsüklita graaf, mis kujutab komponentide vahelisi suhteid. Sõltuvus ei ole ainult seotud teegiga, vaid ka selle versiooniga, mis võib tekitada konflikte.

Mõnikord osutuvad konfliktid lahendamatuks või erinevate tööriistade konfliktide lahendamise strateegiad ei suuda probleemi lahendada, kuigi lahendus on olemas. Selliste probleemide vältimiseks oleme jätnud sõltuvused lõpliku teegi binaarsüsteemi materjaliloendist välja, et mitte segadusse ajada juba kasutusesolevaid tööriistu.

Dokumentatsioonis võiks kirjeldada, milliseid sõltuvusi tuleb teegiga koos lisada, kui tahetakse kasutada ühte või teist funktsionaalsust. See on väga ebatavaline lahendus, mida mujal me täheldanud ei ole. Samas on see võimaldanud meil võtta teek kasutusele ka olukordades, kus seda teha ei saa.

Teegi sisu kokkupanemine meie ettevõtte näitel

Kui me kirjutasime esimest teeki, siis soovisime selle teha nii universaalseks, kui vähegi võimalik. Selleks panime sinna sisse kõik, mis panna sai. Lõpuks ületas teegi suurus mõistlikkuse piire ning ühel hetkel ei olnud sedasi jätkamine enam efektiivne. Liiga suur teek sunnib kulutama rohkem ressursse, et selle peale rakendus ehitada, hiljem seda taristus hoida ning seda käitada.

Täna oleme pigem ettevaatlikud ja lisame teeki ainult neid funktsionaalsusi, mis on enamikes rakendustes päriselt vajalikud. Osasid funktsionaalsusi hoiame projektipõhistes teekides. Vaatleme arendajate tööd ja kui leiame midagi, mis võib olla kasulik teistes projektides, siis aretame funktsionaalsuse majasiseses teegis välja hoolsalt analüüsides, kuidas funtsionaalsust saaks kasutada kõiksugustes stsenaariumites.

Tutvu ühe meie majasisese teegiga näiteks siin.

Kvaliteedi tagamine

Nii nagu teegi kirjutamisel, tuleb lähtuda headest koodi kirjutamise tavadest. Äärmiselt tähtis on ka tagada kvaliteetne, läbimõeldud funktsionaalsus. Iga viga, mis esineb teegi funktsionaalsuses, levib kõikide selle teegi tarbijateni. Iga viga võib tähendada korduvat tõrkeraportit erinevates projektides ning vigu hallata on ilmselgelt kulukam.

Juba teegi kirjutamise juures tuleks hilisemat vigade parandust ennetada. Seetõttu võiks kirjutada oma teekidele põhjalikud automaattestid ja meeskondadelt pidevalt teegi kasutamsie kohta infot koguda. Iga uus versioon teegist tõstab selle vastu usaldust, sest funktsionaalsus on läbinud kadalipu.

Lõpetuseks, üks teegi kasutamise võlu rakenduse koodibaasis on see, et kirjutamata koodirida on rida, mida ei pea testima. Tõstes üldise rakenduse funktsionaalsuse teekidesse, saavad arendajad keskenduda rohkem äriloogiliste testide kirjutamisele. See on järjekordne koht, kus projekti meeskond saab ressursse kokkuhoida.

Soovitused tõhusa majasisese teegiarenduse jaoks:

  • Mõtle, kuidas funktsiooni saaks kasutada erinevates stsenaariumides. Tee oma komponendid paindlikuks ja kohandatavaks.
  • Hoia oma API selge. Peida majasisene loogika.
  • Koosta põhjalik dokumentatsioon ja kasutusnäited.
  • Funktsioonid peaksid tegema täpselt seda, mida nende nimi ütleb, mitte midagi rohkemat.
  • Arendajal peab olema täielik kontroll, mida teek tema koodibaasiga teeb.
  • Analüüsi transitiivsete sõltuvuste mõju.
  • Testi oma funktsioone automatiseeritud testidega.
  • Suhtle oma meeskonnaga, et tuvastada funktsionaalsus, mida enim vajatakse.

Tule kuula esitlust majasiseste teekide loomisest Digit 2024 konverentsil!

4. oktoobril 2024 toimuval Digit konverentsil teeb ettekande meie Tech Lead Erich, kes räägib meie majasiseste teekide loomisest, selle väljakutsetest ning printsiipidest, millest juhindume tänaseni. Üritus toimub Tartus Kammivabrikus (Teguri 28A).

Lisaks toimub 2. oktoobril 2024 meie Tartu kontoris (Vallikraavi 2) Digit konverentsi kõrvalüritus. Tule kuni viieliikmelise tiimiga ning pane enda häkkimisoskused proovile Hackminutes ülesandes! Lisainfot vaata siit.

Jälgi meid Instagramis!

Sellel lehel kasutame küpsiseid. Veebilehe kasutamist jätkates nõustud küpsiste kasutamisega.