Kuidas mitte tappa projekti halbade kodeerimistavadega?
Bartosz Slysz
Software Engineer
Paljud karjääri alustavad programmeerijad ei pea muutujate, funktsioonide, failide ja muude komponentide nimetamise teemat väga oluliseks. Selle tulemusena on nende disainiloogika sageli õige - algoritmid töötavad kiiresti ja annavad soovitud efekti, samas võivad olla vaevu loetavad. Selles artiklis püüan lühidalt kirjeldada, millest peaksime erinevate koodielementide nimetamisel juhinduma ja kuidas mitte minna ühest äärmusest teise.
Miks nimede määramise etapi unarusse jätmine pikendab (mõnel juhul tohutult) teie projekti arengut?
Oletame, et teie ja teie meeskond võtavad üle kood teistelt programmeerijatelt. Veebileht projekt mida te pärite, töötati välja ilma igasuguse armastuseta - see töötas suurepäraselt, kuid selle iga üksik element oleks võinud olla palju paremini kirjutatud.
Kui tegemist on arhitektuuriga, siis koodi pärimise puhul tekitab see peaaegu alati viha ja viha programmeerijate seas, kes selle said. Mõnikord on selle põhjuseks surevate (või hääbuvate) tehnoloogiate kasutamine, mõnikord vale mõtteviis rakendusest arenduse alguses ja mõnikord lihtsalt vastutava programmeerija teadmatus.
Igal juhul on võimalik, et projekti aja möödudes jõutakse punkti, kus programmeerijad on arhitektuuride ja tehnoloogiate suhtes vihased. Lõppude lõpuks vajab iga rakendus mõne aja möödudes mõne osa ümberkirjutamist või lihtsalt muutusi teatud osades - see on loomulik. Kuid probleem, mis muudab programmeerijate juuksed halliks, on raskused päritud koodi lugemisel ja mõistmisel.
Eriti äärmuslikel juhtudel, kui muutujad on nimetatud üksikute, mõttetute tähtedega ja funktsioonid on ootamatu loovuse tõus, mis ei ole kuidagi kooskõlas ülejäänud rakendusega, võivad teie programmeerijad hulluks minna. Sellisel juhul nõuab igasugune koodianalüüs, mis saaks korrektse nimetamise korral kiiresti ja tõhusalt toimida, näiteks funktsiooni tulemuse tekitamise eest vastutavate algoritmide täiendavat analüüsi. Ja selline analüüs, kuigi märkamatu - raiskab tohutult aega.
Uute funktsionaalsuste rakendamine piki rakenduse erinevaid osi tähendab, et tuleb läbida õudusunenägu selle analüüsimisega, mõne aja pärast tuleb minna koodi juurde tagasi ja analüüsida seda uuesti, sest selle kavatsused ei ole selged ja eelmine aeg, mis kulus selle toimimise mõistmiseks, läks raisku, sest te ei mäleta enam, mis oli selle eesmärk.
Ja nii satume me rakenduses valitsevasse korratuse tornaadosse, mis aeglaselt tarbib iga selle arengus osalejat. Programmeerijad vihkavad projekti, projektijuhid vihkavad seletada, miks selle arendusaeg hakkab pidevalt pikenema, ning klient kaotab usalduse ja vihastub, sest miski ei lähe plaanipäraselt.
Kuidas seda vältida?
Olgem ausad - mõningaid asju ei saa vahele jätta. Kui me oleme projekti alguses valinud teatud tehnoloogiad, peame olema teadlikud, et aja jooksul kas lõpetatakse nende toetamine või on üha vähem programmeerijaid, kes valdavad mõne aasta taguseid tehnoloogiaid, mis aeglaselt vananevad. Mõned raamatukogud nõuavad oma uuendustes rohkem või vähem keerulisi muudatusi koodis, mis sageli toovad kaasa sõltuvuste keerise, milles võib veelgi rohkem kinni jääda.
Teisest küljest ei ole see nii must stsenaarium; muidugi - tehnoloogiad vananevad, kuid tegur, mis kindlasti aeglustab nendega seotud projektide arendusaega, on suuresti kole kood. Ja muidugi tuleb siinkohal mainida Robert C. Martini raamatut - see on programmeerijate piibel, kus autor esitab palju häid tavasid ja põhimõtteid, mida tuleks järgida, et luua täiuslikkuse poole püüdlevat koodi.
Muutujate nimetamisel on põhiline, et nende eesmärk oleks selgelt ja lihtsalt edasi antud. See kõlab üsna lihtsalt, kuid mõnikord jätavad paljud inimesed selle tähelepanuta või ignoreerivad seda. Hea nimi täpsustab, mida täpselt muutuja peaks salvestama või mida funktsioon peaks tegema - see ei saa olla liiga üldine nimi, kuid teisest küljest ei tohi see muutuja muutuda ka pikaks lörtsiks, mille pelgalt lugemine tekitab ajule üsna suure väljakutse. Mõne aja möödudes kvaliteetse koodiga kogeme immersiooni efekti, kus suudame alateadlikult korraldada nimetamise ja andmete edastamise funktsioonile nii, et kogu asi ei jäta illusioone, milline kavatsus seda juhib ja milline on selle kutsumise oodatav tulemus.
Teine asi, mida võib leida JavaScripton muu hulgas katse koodi üle optimeerida, mis muudab selle paljudel juhtudel loetamatuks. On normaalne, et mõned algoritmid nõuavad erilist hoolt, mis sageli peegeldab asjaolu, et koodi kavatsus võib olla veidi keerulisem. Sellegipoolest on äärmiselt haruldased juhtumid, kus me vajame liigset optimeerimist, või vähemalt need, kus meie kood on räpane. Oluline on meeles pidada, et paljud keelega seotud optimeerimised toimuvad veidi madalamal abstraktsioonitasemel; näiteks võib V8 mootor piisava hulga iteratsioonide korral silmuseid märkimisväärselt kiirendada. Tuleb rõhutada, et me elame 21. sajandil ja me ei kirjuta programme Apollo 13 missiooni jaoks. Meil on ressursside teemal palju rohkem manööverdamisruumi - need on selleks, et neid kasutada (soovitavalt mõistlikul viisil :>).
Mõnikord annab koodi osadeks jaotamine tõesti palju. Kui operatsioonid moodustavad ahela, mille eesmärk on sooritada toiminguid, mis vastutavad konkreetse andmete muutmise eest - on lihtne eksida. Seetõttu saab lihtsal viisil, selle asemel, et teha kõik ühes ahelas, jaotada koodi üksikud osad, mis vastutavad mingi konkreetse asja eest, üksikuteks elementideks. See ei tee mitte ainult selgeks üksikute toimingute kavatsust, vaid võimaldab teil ka testida koodifragmente, mis vastutavad ainult ühe asja eest ja mida saab hõlpsasti uuesti kasutada.
Mõned praktilised näited
Ma arvan, et kõige täpsem on näidata, kuidas mõned ülaltoodud väited praktikas toimivad - selles lõigus püüan kirjeldada mõningaid halbu koodipraktikaid, mida saab enam-vähem muuta headeks. Toon välja, mis häirib mõnel hetkel koodi loetavust ja kuidas seda vältida.
Ühe tähega muutujate häda
Kohutav tava, mis on kahjuks üsna levinud isegi ülikoolides, on muutujate nimetamine ühe tähega. On raske mitte nõustuda, et mõnikord on see üsna mugav lahendus - me väldime asjatut mõtlemist, kuidas määrata muutuja otstarvet, ja selle asemel, et kasutada selle nimetamiseks mitut või enamat märki, kasutame lihtsalt ühte tähte - nt i, j, k.
Paradoksaalsel kombel on mõnele nende muutujate definitsioonile omistatud palju pikem kommentaar, mis määrab, mida autor silmas pidas.
Hea näide oleks siinkohal kujutada iteratsiooni üle kahemõõtmelise massiivi, mis sisaldab vastavaid väärtusi veeru ja rea ristumiskohas.
const array = [[0, 1, 2], [3, 4, 5], [6, 7, 8]];
// päris halb
for (let i = 0; i < array[i]; i++) {
for (let j = 0; j < array[i][j]; j++) {
// siin on sisu, aga iga kord, kui i ja j kasutatakse, pean ma tagasi minema ja analüüsima, milleks neid kasutatakse.
}
}
// ikka halb, aga naljakas
lase i; // rida
let j; // veerg
for (i = 0; i < array[i]; i++) {
for (j = 0; j < array[i][j]; j++) {
// siin on sisu, kuid iga kord, kui i ja j kasutatakse, pean ma tagasi minema ja kontrollima kommentaare, milleks neid kasutatakse.
}
}
// palju parem
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];
// kas kellelgi on kahtlusi, mis on mis?
}
}
Salakaval üle-optimeerimine
Ühel toredal päeval sattusin ma väga keerulise koodi peale, mille oli kirjutanud üks tarkvarainsener. See insener oli aru saanud, et kasutaja õiguste saatmist stringidena, mis määravad kindlaks konkreetsed tegevused, saab oluliselt optimeerida, kasutades mõningaid bititasandi trikke.
Tõenäoliselt oleks selline lahendus OK, kui sihtmärgiks oleks Commodore 64, kuid selle koodi eesmärk oli lihtne veebirakendus, mis on kirjutatud JS keeles. Aeg on tulnud selle veidruse ületamiseks: Oletame, et kasutajal on kogu süsteemis ainult neli võimalust sisu muutmiseks: luua, lugeda, uuendada, kustutada. On üsna loomulik, et me saadame need õigused kas JSON-vormingus olekuga objekti võtmetena või massiivi kujul.
Meie nutikas insener märkas aga, et number neli on maagiline väärtus binaarses esituses ja arvas selle välja järgmiselt:
Kogu võimete tabelis on 16 rida, ma olen loetlenud ainult 4, et anda edasi nende õiguste loomise idee. Õiguste lugemine käib järgmiselt:
See, mida te eespool näete, ei ole WebAssembly kood. Ma ei taha, et mind siinkohal valesti mõistetaks - sellised optimeerimised on normaalne asi süsteemide puhul, kus teatud asjad peavad võtma väga vähe aega või mälu (või mõlemat). Veebirakendused seevastu ei ole kindlasti koht, kus sellised üleoptimeerimised on täiesti mõistlikud. Ma ei taha üldistada, aga front-end arendajate töös tehakse harva keerulisemaid operatsioone, mis ulatuvad bitide abstraktsiooni tasemele.
See ei ole lihtsalt loetav ja programmeerija, kes oskab sellist koodi analüüsida, mõtleb kindlasti, millised on selle lahenduse nähtamatud eelised ja mida võib kahjustada, kui arendusmeeskond tahab seda ümber kirjutada mõistlikumale lahendusele.
Veelgi enam - ma kahtlustan, et õiguste saatmine tavalise objektina võimaldaks programmeerijal lugeda kavatsust 1-2 sekundiga, samas kui kogu selle asja analüüsimine algusest peale võtab vähemalt paar minutit. Projektis on mitu programmeerijat, igaüks neist peab selle kooditükiga kokku puutuma - nad peavad seda mitu korda analüüsima, sest mõne aja pärast unustavad nad, mis maagia seal toimub. Kas tasub neid paari baiti säästa? Minu arvates mitte.
Jaga ja valitse
Veebiarendus kasvab kiiresti ja miski ei näita, et selles osas peagi midagi muutuks. Peame tunnistama, et front-end arendajate vastutus on viimasel ajal oluliselt suurenenud - nad võtsid üle loogika osa, mis vastutab andmete esitlemise eest kasutajaliideses.
Mõnikord on see loogika lihtne ja API pakutavad objektid on lihtsa ja loetava struktuuriga. Mõnikord aga vajavad nad erinevat tüüpi kaardistamist, sorteerimist ja muid operatsioone, et kohandada neid erinevatesse kohtadesse lehel. Ja see on koht, kus me võime kergesti sootuks alla sattuda.
Mitu korda olen end tabanud sellel, et tegin oma toimingute andmed praktiliselt loetamatuks. Vaatamata massiivi meetodite õigele kasutamisele ja muutujate õigele nimetamisele, kaotasid operatsioonide ahelad mõnes kohas peaaegu konteksti, mida ma tahtsin saavutada. Samuti oli mõnda neist operatsioonidest mõnikord vaja kasutada mujal ja mõnikord olid need piisavalt globaalsed või keerulised, et nõuda testide kirjutamist.
Ma tean, ma tean - see ei ole mingi triviaalne kooditükk, mis illustreerib lihtsalt seda, mida ma tahan edasi anda. Ja ma tean ka, et kahe näite arvutuslik keerukus on veidi erinev, samas kui 99% juhtudel ei pea me selle pärast muretsema. Erinevus algoritmide vahel on lihtne, sest mõlemad valmistavad ette asukoha ja seadme omanike kaardi.
Esimene valmistab seda kaarti ette kaks korda, teine aga ainult üks kord. Ja lihtsaim näide, mis näitab meile, et teine algoritm on kaasaskantavam, seisneb selles, et me peame muutma selle kaardi loomise loogikat esimese jaoks ja näiteks tegema teatud asukohtade välistamise või muud imelikud asjad, mida nimetatakse äriloogikaks. Teise algoritmi puhul muudame ainult kaardi saamise viisi, samas kui kõik ülejäänud järgnevates ridades toimuvad andmemuudatused jäävad muutumatuks. Esimese algoritmi puhul tuleb meil iga katse kaardivalmistamisel muuta.
Ja see on vaid näide - praktikas on palju selliseid juhtumeid, kui meil on vaja teatud andmemudelit ümber kujundada või ümber kujundada kogu rakendus.
Parim viis vältida erinevate ärimuutustega kursis olemist on valmistada ette globaalsed tööriistad, mis võimaldavad meil huvipakkuvat teavet üsna üldisel viisil välja võtta. Isegi nende 2-3 millisekundi hinnaga, mida me võime kaotada de-optimeerimise hinnaga.
Kokkuvõte
Programmeerija on elukutse nagu iga teine - iga päev õpime uusi asju, tehes sageli palju vigu. Kõige tähtsam on õppida neist vigadest, saada oma ametis paremaks ja mitte korrata neid vigu tulevikus. Ei saa uskuda müüti, et meie töö on alati veatu. Te võite aga teiste kogemustele tuginedes vigasid vastavalt vähendada.
Ma loodan, et selle artikli lugemine aitab teil vältida vähemalt mõningaid halvad kodeerimistavad mida olen oma töös kogenud. Kui teil on küsimusi seoses parimate kooditavadega, võite pöörduda The Codest meeskond välja, et konsulteerida oma kahtlustega.