Hvernig á ekki að drepa verkefni með slæmum forritunarvenjum?
Bartosz Slysz
Software Engineer
Margir forritarar sem eru að hefja feril sinn telja efnið um að nefna breytur, fall, skrár og aðra þætti ekki mjög mikilvægt. Afleiðingin er sú að hönnunarhugsunin þeirra er oft rétt – reikniritin keyra hratt og skila tilætluðum árangri, en kóðinn getur varla verið læsilegur. Í þessari grein mun ég stuttlega reyna að lýsa því hvað við ættum að hafa til leiðarvísis þegar við nefnum mismunandi kóðaeiningar og hvernig eigi ekki að fara frá einum öfga til annars.
Hér er tómt.
Hvers vegna mun vanræksla á nafngiftastiginu lengja (í sumum tilfellum – gífurlega) þróun verkefnisins þíns?
Segjum að þú og þinn lið eru að taka yfir kóði frá öðrum forriturum. The verkefni Það sem þú erfir var þróað án nokkurrar ástar – það virkaði alveg fínt, en hver einasti þáttur þess hefði getað verið skrifaður mun betur.
Þegar kemur að arkitektúrnum vekur kóðarfærsla nánast alltaf hatur og reiði hjá forriturunum sem fá hana. Stundum stafar þetta af notkun tækni sem er að deyja út (eða þegar útdauð er), stundum af röngu hugarfari gagnvart forritinu í upphafi þróunar, og stundum einfaldlega vegna skorts á þekkingu hjá þeim forritara sem ber ábyrgð.
Í öllum tilvikum, eftir því sem verkefnið líður, er mögulegt að ná þeim punkti að forritarar verði brjálaðir á arkitektúrum og tækni. Enda þarf að endurskrifa suma hluta hvers forrits eða gera breytingar á ákveðnum þáttum eftir einhvern tíma – það er eðlilegt. En vandamálið sem mun gera hárið á forriturunum grátt er hversu erfitt er að lesa og skilja kóðann sem þeir erfðu.
Sérstaklega í öfgafelldum tilfellum þegar breytur eru nefndar með einstökum, merkingarlausum stöfum og fall eru skyndileg uppspretta sköpunar sem á engan hátt samræmist restinni af forritinu, geta forritararnir þínir farið á geðveiki. Í slíku tilfelli krefst hvaða kóðagreining sem gæti keyrt hratt og skilvirkt með réttri nafngiftar aukagreiningar á þeim reikniritum sem bera ábyrgð á að framleiða niðurstöðu fallsins, til dæmis. Og slík greining, þó ósýnileg, eyðir gríðarlegum tíma.
Að innleiða nýja virkni í mismunandi hluta forritsins þýðir að ganga í gegnum martröð við greiningu þess. Eftir einhvern tíma þarftu að snúa aftur til kóðans og greina hann aftur því markmið hans eru ekki skýr, og tíminn sem þú varið í að reyna að skilja rekstur þess var sóun því þú manst ekki lengur hvað tilgangur þess var.
Og þannig sökkvum við í hvirfil óreiðu sem ríkir í forritinu og étur smám saman alla þá sem taka þátt í þróun þess. Forritarar hata verkefnið, verkefnastjórar hata að útskýra hvers vegna þróunartíminn eykst stöðugt, og viðskiptavinurinn missir traust og verður reiður því ekkert gengur eftir samkvæmt áætlun.
Hvernig forðast það?
Við verðum að viðurkenna – sumt er ekki hægt að sleppa. Ef við höfum valið ákveðnar tæknilausnir í upphafi verkefnisins verðum við að gera okkur grein fyrir því að með tímanum munu þær annaðhvort hætta að vera studdar eða sífellt færri forritarar verða kunnir tæknilausnum frá fyrir nokkrum árum sem smám saman eru að úreldast. Sumar bókasöfn krefjast, við uppfærslur, meira eða minna umfangsmikilla breytinga í kóðanum, sem oft leiða til völundarhúss háðra þátta þar sem auðvelt er að festast enn frekar.
Á hinn bóginn er þetta ekki svo svartarútlit; auðvitað eru tæknirnar að eldast, en það sem án efa hægir mest á þróunartíma verkefna sem tengjast þeim er að miklu leyti ljótur kóði. Og auðvitað verðum við að nefna bók Robert C. Martin – þetta er biblía forritara, þar sem höfundurinn kynnir margar góðar vinnubrögð og meginreglur sem ber að fylgja til að skapa kóða sem stefnir að fullkomnun.
Grunnatriðið við að nefna breytur er að miðla tilgangi þeirra á skýran og einfaldan hátt. Það hljómar nokkuð einfalt, en stundum er það vanrækt eða hunsað af mörgum. Gott nafn tilgreinir nákvæmlega hvað breytan á að geyma eða hvað fallið á að gera – það má ekki vera of almennt, en á hinn bóginn má það ekki verða svo langt að lestur þess einn og sér reynist heilanum ansi krefjandi. Eftir smá tíma með góðu gæðakóði, við upplifum sökkningaráhrifin, þar sem við getum ómeðvitað raðað nafngiftum og framvindu gögn að falla að virkninni á þann hátt að allt sé án nokkurs vafa um hvaða ásetningur hvetur hana áfram og hvaða niðurstaða er væntanleg við kallið.
Annað sem má finna í JavaScript, meðal annars, er tilraun til of-hagræðingar kóðans, sem í mörgum tilfellum gerir hann ólesanlegan. Það er eðlilegt að sum reiknirit krefjist sérstakrar athygli, sem oft endurspeglar að tilgangur kóðans getur verið nokkuð flóknari. Engu að síður eru tilfellin þar sem við þurfum of mikla hagræðingu afar sjaldgæf, eða að minnsta kosti þau þar sem kóðinn okkar verður óhreinn. Mikilvægt er að muna að margar málnotkunartengdar fínstillingar eiga sér stað á örlítið lægra stigi abstraktions; til dæmis getur V8-vélin, með nægum endurtekningum, aukið hraða lykkja verulega. Það sem ber að leggja áherslu á er sú staðreynd að við lifum á 21. öld og skrifum ekki forrit fyrir Apollo 13-ferðina. Við höfum mun meira svigrúm hvað varðar auðlindir – þær eru til þess að nota (helst á skynsamlegan hátt :>).
Stundum skilar það miklu að brjóta kóðann niður í hluta. Þegar aðgerðir mynda keðju sem á að framkvæma aðgerðir sem bera ábyrgð á tiltekinni breytingu á gögnum – er auðvelt að týnast. Þess vegna er einfaldlega hægt, í stað þess að gera allt í einni strengi, að sundurliðaða einstaka hluta kóðans sem sjá um ákveðna aðgerð í aðskilda einingar. Þetta gerir ekki aðeins ásetning einstakra aðgerða skýrari, heldur gerir það einnig kleift að prófa kóðabrot sem sjá um aðeins eina aðgerð og auðvelt er að endurnýta.
Nokkur hagnýt dæmi
Ég tel að nákvæmasta framsetning á sumum ofangreindum fullyrðingum sé að sýna hvernig þær virka í framkvæmd – í þessum málsgrein mun ég reyna að draga upp nokkrar slæmar kóðunarvenjur sem hægt er að breyta meira og minna í góðar. Ég mun benda á hvað rýrir læsileika kóðans á köflum og hvernig megi koma í veg fyrir það.
Plága einstafa breyta
Hrollvekjandi venja sem er því miður nokkuð algeng, jafnvel við háskóla, er að nefna breytur með einu einasta staf. Það er erfitt að vera ekki sammála því að stundum sé þetta nokkuð þægileg lausn – við sleppum óþarfa vangaveltum um hvernig á að ákvarða tilgang breytu og í stað þess að nota nokkur eða fleiri tákn til að nefna hana notum við bara einn staf – t.d. i, j, k.
Andstætt því eru sumar skilgreiningar þessara breyta með mun lengri athugasemd sem ákvarðar hvað höfundurinn hafði í huga.
Gott dæmi hér væri að sýna hringrásina yfir tvívítt fylki sem inniheldur samsvarandi gildi þar sem dálkur og röð skerast.
const array = [[0, 1, 2], [3, 4, 5], [6, 7, 8]];
// frekar slæmt
for (let i = 0; i < array[i]; i++) {
for (let j = 0; j < array[i][j]; j++) {
// hér er efnið, en í hvert skipti sem i og j eru notuð þarf ég að fara aftur og greina hvað þau eru notuð fyrir
}
}
// enn slæmt en fyndið
let i; // röð
let j; // dálkur
for (i = 0; i < array[i]; i++) {
for (j = 0; j < array[i][j]; j++) {
// hér er efnið, en í hvert sinn sem i og j eru notuð þarf ég að fara aftur og athuga athugasemdirnar til að sjá hvað þau eru notuð fyrir
}
}
// miklu betra
const rowCount = array.length;
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
const row = array[rowIndex];
const columnCount = row.length;
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
const column = row[columnIndex];
// Efast einhver um hvað er hvað?
}
}
Lúmsk ofbætir
Einn fallegur dagur rakst ég á afar háþróaðan kóða sem var skrifaður af a hugbúnaðarverkfræðingur. Þessi verkfræðingur hafði komist að því að senda notendaupplýsingar sem strengi sem tilgreina ákveðnar aðgerðir mætti verulega hagræða með nokkrum bitastigsbrellum.
Slík lausn væri líklega í lagi ef markmiðið væri Commodore 64, en tilgangur þessa kóða var einfaldur vefur umsókn, skrifuð í JS. Tíminn er kominn til að yfirstíga þessa sérvisku: Segjum að notandi hafi aðeins fjórar heimildir í öllu kerfinu til að breyta efni: búa til, lesa, uppfæra og eyða. Það er nokkuð eðlilegt að senda þessar heimildir annaðhvort sem JSON-lykla í hlut með stöðum eða sem fylki.
Hins vegar tók snjalli verkfræðingurinn okkar eftir því að talan fjögur er töfratala í tvíundarkerfinu og komst að því á eftirfarandi hátt:
Allur hæfileikataflan hefur 16 línur, ég hef skráð aðeins 4 til að miðla hugmyndinni um að búa til þessi leyfi. Lestrun leyfanna fer fram á eftirfarandi hátt:
const user = { permissions: 11 };
const canCreate = Boolean(user.permissions & 8); // satt
const canRead = Boolean(user.permissions & 4); // falskt
const canUpdate = Boolean(user.permissions & 2); // satt
const canDelete = Boolean(user.permissions & 1); // satt
Það sem þú sérð hér að ofan er ekki WebAssembly-kóði. Ég vil ekki að þetta verði misskilið – slíkar fínstillingar eru eðlilegt fyrirbæri í kerfum þar sem ákveðnar aðgerðir þurfa að taka mjög litla tíma eða nota mjög lítið minni (eða bæði). Vefumsóknir eru aftur á móti alls ekki staður þar sem slíkar offínstillingar hafa fulla þýðingu. Ég vil ekki alhæfa, en í vinnu framanvirkra forritara eru flóknari aðgerðir sem ná stigi bitastjórnunar sjaldan framkvæmdar.
Það er einfaldlega ólesanlegt, og forritari sem getur greint slíkan kóða mun vissulega velta því fyrir sér hvaða ósýnilegu kosti þessi lausn hefur og hvað getur skemmst þegar þróun team vill endurskrifa það í hentugri lausn.
Enn fremur – ég gruna að það að senda heimildarnar sem venjulegt hlut myndi gera forritara kleift að lesa tilganginn á 1–2 sekúndum, á meðan greining á öllu þessu frá upphafi myndi taka að minnsta kosti nokkrar mínútur. Í verkefninu verða nokkrir forritarar, og hver og einn mun þurfa að rekast á þennan kóðabút – þeir munu þurfa að greina hann nokkrum sinnum, því eftir einhvern tíma munu þeir gleyma hvaða galdur er þar í gangi. Er það þess virði að spara þessa fáu bita? Að mínu mati, nei.
Skiptu og sigraðu
Vefþróun Er að vaxa hratt og engin merki eru um að neitt muni breytast í þessu tilliti innan skamms. Við verðum að viðurkenna að ábyrgð framsíðuforritara hefur aukist verulega nýlega – þeir tóku yfir hluta af lógíkinni sem sér um framsetningu gagna í notendaviðmótinu.
Stundum er þessi rökfræði einföld, og hlutirnir sem veittir eru af forritaskil Þau hafa einfalda og læsilega uppbyggingu. Stundum krefjast þau hins vegar mismunandi kortlagninga, röðunar og annarra aðgerða til að aðlaga þau að mismunandi stöðum á síðunni. Og hér er auðvelt að falla í mýru.
Mörgum sinnum hef ég tekið eftir því að gögnin í þeim aðgerðum sem ég framkvæmdi urðu nánast ólesanleg. Þrátt fyrir réttan notkun fylkisaðferða og vandað nafngiftir breyta voru keðjur aðgerða á köflum næstum því að missa samhengi um hvað ég vildi ná fram. Einnig þurfti stundum að nota sumar þessara aðgerða annars staðar, og stundum voru þær svo alþjóðlegar eða flóknar að þær krafðust skrifunar prófa.
Ég veit, ég veit – þetta er ekki einhver smávæg kóðalína sem auðveldlega sýnir það sem ég vil koma á framfæri. Og ég veit líka að reikniveruleg flækjustig tveggja dæmanna eru örlítið mismunandi, en í 99% tilfellum þurfum við ekki að hafa áhyggjur af því. Munurinn á reikniritunum er einfaldur, þar sem bæði undirbúa kort af stöðum og eigendum tækja.
Sá fyrsti undirbýr þessa kort tvisvar sinnum, en sá annar undirbýr það aðeins einu sinni. Og einfaldasta dæmið sem sýnir okkur Að annar reikniritið sé flytjanlegra stafar af því að við þurfum að breyta rökfræði við gerð þessa korts fyrir hið fyrsta og t.d. útiloka ákveðna staði eða önnur undarleg atriði sem kallast viðskiptarök. Í tilviki hins seinna reikniritsins breytum við aðeins aðferðinni við að útbúa kortið, á meðan allar aðrar breytingar á gögnum sem eiga sér stað í næstu línum haldast óbreyttar. Í tilviki hins fyrsta reikniritsins þurfum við að fínstilla hverja tilraun til að útbúa kortið.
Og þetta er bara dæmi – í raun og veru eru mörg slík tilfelli þegar við þurfum að umbreyta eða endurskipuleggja ákveðið gagnalíkan í öllu forritinu.
Besti hátturinn til að forðast að þurfa að fylgjast með ýmsum viðskiptabreytingum er að þróa alþjóðleg verkfæri sem gera okkur kleift að draga fram upplýsingar sem okkur henta á frekar almennan hátt. Jafnvel þótt það kosti okkur 2–3 millisekúndur sem við gætum tapað vegna óhagræðingar.
Yfirlit
Að vera forritari er starf eins og hvert annað – á hverjum degi lærum við eitthvað nýtt og gerum oft mörg mistök. Það mikilvægasta er að læra af þessum mistökum, verða betri í starfi þínu og endurtaka ekki sömu villur í framtíðinni. Þú mátt ekki trúa goðsögninni um að vinnan sem við framkvæmum verði alltaf gallalaus. Þú getur hins vegar, með því að byggja á reynslu annarra, dregið úr göllunum í samræmi við það.
Ég vona að lestur þessa greinar muni hjálpa þér að forðast að minnsta kosti suma af Slæmar forritunarvenjur sem ég hef upplifað í starfi mínu. Ef þú hefur einhverjar spurningar um bestu kóðunarvenjur geturðu haft samband við The Codest áhöfn Út til að ráðfæra þig um vafa þína.