…meie igapäevast IT’d anna meile igapäev…

2008-04-30

Veel raskeid asju programmeerimisel: kommentaarid

Filed under: Programmeerimine — Sander @ 12:03:10

commentedCode2 Kui eelmine post oli muutujate nimetamisest, siis seekord tuleb veidi juttu kommentaaridest.

Kommentaaride kohta on niisama palju arvamusi kui programmeerijaid. Alates “hea kood ei vaja kommentaare” kuni “iga rida tuleb religioosselt kommenteerida”… oh, vabandust, unustasin ära kõige levinuma ja lollima seisukoha, “kommentaarid on nõrkadele”.

Kommentaarid on raske teema. Kui muutujate korralikult nimetamise kasulikkusest saavad enamasti kõik aru, siis korralike kommentaaride vajalikkust on raskem selgitada. Algajad programmeerijad ei saa aru, miks nende koodile peaks olema kommentaare vaja (“noh, funktsiooni nimi on ju GetItemData(), sellest saab kõik aru”), kohalik Extreme Programming guru on kusagilt lugenud et kommentaarid on mittevajalikud (teadmata täpselt mispärast), projektijuht leiab et need on ajaraiskamine, “tehke selle asemel tööd, kirjutage koodi” – ja siis on veel olemas alati Vana Programmeerija, kes leiab et kommentaarid on kurjast, need panevad kompilaatori tulist kurja vanduma ja keskööl mõlemast otsast verist vahtu välja ajama.

Miks on kommentaarid vajalikud?

Õigemini, miks on kommentaarid olulisemad kui kood?

Esimese asjana, “Stonehenge’i efekt” – algsed programmeerijad, arhitektid, analüütikud on firmast lahkunud või on rakenduse üle võtnud teine firma, teine tiim või teine programmeerija – ja keegi lihtsalt ei saa aru mida see kood teeb. Kui kunagi on vaja teha muudatus või bugfix, siis peab üks õnnetu programmeerija võtma ette koodi – lootes, et dokumentatsioon on ka alles, mitte ainult help – ja hakkama seda lahti harutama. Ilmaasjata pole öeldud, “Code as if whoever maintains your program is a violent psychopath who knows where you live.“. Olen ise päris mitmel korral see “õnnetu programmeerija” olnud, kes peab tegema muudatuse aastaid tagasi kirjutatud, halvas stiilis ja ilma kommentaarideta koodis. Ning siis projektijuht imestab “Selle pisikese muudatuse tegemiseks läks neli tundi?!”. Jah, läks. Kolm tundi ja 55 minutit selleks, et läbi närida ja aru saada, minut muudatuse tegemiseks ja neli minutit testimiseks.

IOCCC Teine põhjus, miks kommentaarid on vajalikud – selgitamine. Mitte ainult teiste jaoks, ka iseenda jaoks. Võta kätte aasta aega tagasi kirjutatud kood, kas sa saad peale vaadates aru mida mis teeb ja miks? Kui saad – tubli, oled hästi kirjutanud. Või vaatad liiga lihtsat koodi. Moodsad keeled on disainitud lihtsamini arusaadavad ja loetavad olema, aga Fortranit saab kirjutada igas keeles. Ega ilmaasjata ei toimu igal aastal International Obfuscated C Code Contest – ürita aru saada, mida teeb üks kunagistest võitjatest:

main(O){int I,Q,l=O;if(I=l*4){l=6;if(l>5)l+=Q-8?l-(Q=getchar()-2)%2:l;if(Q*=2)O+="has dirtiest IF"[(I/-Q&12)-l/Q%4];}printf("%d\n",8+O%4);}

Huvitava faktina, üks vanadest võitjatest ei suutnud oma võistlustööst aasta hiljem enam aru saada, pärast seda peavad võistlejad lisama selgituse eraldi failis…

Need on tähtsaimad põhjused, miks koodi on kasulik kommenteerida. Põhjuseid on veel, näiteks saab kommentaare lihtsamini otsida, märkida kohtasid, mis vajavad tähelepanu (“//HACK”, “//TODO”, “//XXX”, “//FIXME”), kasutada kommetaare automaatseks dokumentatsiooni genereerimiseks jne.

Kas kommenteerimine võib olla ka halb? Üllatav vastus on – jah, võib küll. Teatud keeltes/platvormidel teevad kommentaarid programmi aeglasemaks, näiteks klassikalises BASICus – aga ka ASP’is (mitte ASP.NET’is). Kui programmi ei kompileerita, siis lisab kommentaar koodile suurust ja aeglustab selle masinapoolset interpreteerimist. Tänapäeval on sarnaseks kohaks JavaScript – korralikult kommenteeritud ja vormindatud JS kood võib olla kaks korda suurem ja oluliselt aeglasem, kui kommenteerimata kood. Kuid lahenduseks ei ole kommenteerimisest loobumine – tuleb teha eraldi development ja release versioon, JS puhul on selleks olemas automaatsed rakendused.

Kommentaaride kvaliteet ja sisu on eraldi teema – aga nagu on öeldud, halb seks on ka parem kui üldse mitte midagi.

Mida ja kuidas kommenteerida?

Kindlasti pole vaja kommenteerida igat rida. Klassikaline näide mõttetust kommentaarist on “i++; //add one to i“. IBM’i poolt läbiviidud uurimuse kohaselt on optimaalne kommentaaride hulk üks kümne rea kohta.

Erandjuhud on kriitilised süsteemid – näiteks NASA kosmosesüstikuid juhtival koodil on iga rea kohta kommentaar. Kui koodireas tehakse muudatus, siis lisatakse rea kohale kommentaarina muudatuse sisu, tegemise põhjus, aeg ja tegija. Iga rea kohta. Ning tulemus – SATC‘i poolt läbi lastud koodis on vähem kui 0.1 viga iga tuhande rea kohta (isegi 0 viga 500 000’s reas koodis). Võrdluseks – tavalises koodis on enne testimist tuhande rea kohta 15..50 viga, Microsofti koodis on enne testimist 10..20 viga/KLOC ja 0.5 pärast väljalaset. Linuxi koodis on erinevatel hinnangutel 0.17…0.5 viga/KLOC, tavalistes projektides loetakse väga heaks tulemuseks 3 viga/KLOC.

Loomulikult ei saa NASA süsteemi igapäevaelus kasutada. See oleks ju suurepärane, aga tarkvara arenduse hinnad kümnekordistuksid – ja price/peformance suhe ei oleks aksepteeritav.

CommentExample Aga tagasi kommentaaride juurde. Mida kommenteerida?

Kõige olulisem – kommenteeri alati protseduurid. Selgita mida see protseduur, funktsioon või meetod teeb, mida see tagastab. Tänapäevastel arendusvahenditel on reeglina võimalus selle standardiseerimiseks ja lihtsustamiseks, näiteks Visual Studio genereerib kolme /// peale osaliselt täidetud XML-jupi, mille pealt on võimalik genereerida dokumentatsiooni (selleks on olemas automaatsed abivahendid), seda kasutab IntelliSense meetodi ja selle parameetrite info näitamiseks – ning loomulikult on see abiks koodist arusaamisel. Sarnane funktsionaalsus on kõigis moodsates programmeerimiskeskkondades, sageli küll eraldi plugina kujul.

Sarnaselt meetoditele saab nõnda, poolautomaatselt, kommenteerida ka klasse, klassimuutujaid jm. Kui see on ühendatud IntelliSense-laadse funktsionaalsusega, siis on see loomulikult veel lisaväärtuseks.

Failide päises olevad kommentaarid klasside, firma ja projekti nimedega, tegija, muudatused, koodis olev funktsionaalsus jne on pea reeglina vähemolulised. Lihtne on neid genereerida automaatsete vahendite abil, mis ise täidavad nimed jm ära. Reeglina sõltub päisekommentaari olemasolu firma oma sisemistest nõuetest. Mööda külgi maha ei jookse siiski ka need kommentaarid.

Koodi seletus on võibolla kõige levinum kommentaaritüüp. Selle sisuks on keeruka või loogikale vastu käiva koodi sisu seletamine. Väga raske, kui mitte võimatu, on anda konkreetseid juhiseid või õpetussõnu, millal selliseid kommentaare kirjutada. Ainuke konkreetne juhis – kui kahtled kas kirjutada, siis tee seda. Pigem rohkem kommentaare, kui vähe või üldse mitte. Samas – kui kood on nii keerukas, et vajab seletamist, siis võib olla on parem mõte kood selgemaks kirjutada.

Koodi sisu kommentaar on koodi vajalikkuse ja funktsionaalsuse selgitamine inimkeeles, paari lausega. Pea reeglina seda ei tehta, kuid nende kommentaaride olemasolu korral on koodist arusaamine kordades lihtsam. Sageli on sellised kommentaarid ka lihtsalt markerid koodis, mis võimaldavad kiirelt leida vajalikku kohta koodis (//peatsükli lõpp, //kui item==null, siis…)

Koodimarker on standardiseeritud/kokkulepitud formaadiga lühikommentaar, mis võimaldab anda juhiseid koodi hilisemaks muutmiseks. Näiteks üldlevinud //TODO: ja //FIXME:, mis on toetatavad ka enamike keskkondade poolt, so võimalik kiiresti neid listida ja vaadata.

Lõpetuseks

Integreeri kommenteerimine oma koodimisstiili, muuda see harjumuseks. “Kiire oli” ei ole vabanduseks, hiljem debugimisel teeb korralik kommentaar enda peale kulutatud aja kordades tasa. “Hiljem kommenteerin” on võibolla kõige hullem idee üldse, kommentaarid tuleb kirjutada samal ajal, kui sa koodi kirjutad. “Hiljem” enamasti ei saabu kunagi – ja kui see peaks ka tulema, siis ei mäleta sa enam, mida miski teeb.

8 kommentaari »

  1. Parem kui koodi *kirjutamise ajal* on kirjutada kommentaarid *enne koodi kirjutamist* – annab võimaluse kood läbi mõelda. Kui ma veel progesin, siis ma seda praktiseerisin. Samas kõiki kommentaare sel ajal ei saa, osad tulevad jooksvalt.

    Sa jätsid sellest jutust välja suure ohu, et kommentaarid ja kood ei lähe enam peale mingeid muudatusi kokku (millest meil just juttu oli). Ja üks halb kommentaar on ka see, mis on liiga pikk – kommentaar peab olema loetav paralleelselt täienduseks koodile, soovitatavalt lihtlausetega ja lühidalt. Muidu ta muutubki peagi kommentaariks, mis ei ole koodi sisuga kooskõlas (sest progeja ei viitsi seda muuta kui koodi muudab).

    kommentaar kirjutas liriel — 2008-04-30 @ 12:38:45 | Vasta

  2. “Enne koodi kirjutamist” kommenteerin ma reeglina meetodid ära, ülejäänud tulevad jooksvalt.

    Aga muudatuste kohta, kui kommentaar ei lähe enam kokku koodiga – see oli mul tegelikult plaanis. Aga eile õhtul unise peaga unus ära, nagu paar muudki asja, hommikul lugesin ainult üle ja avaldasin.

    kommentaar kirjutas dukelupus — 2008-04-30 @ 12:44:21 | Vasta

  3. Ilmselt kasutatakse väljendit “kommentaarid on nõrkadele” siiski iroonilises v. sarkastilises võtmes.

    kommentaar kirjutas Offf — 2008-04-30 @ 15:25:29 | Vasta

  4. Selle kommentaaride kohe kirjutamisega on see jama, et siis võtavad need aega, samas kui kood tuleb hetkel kiiresti. Endale istub kommentaare kirjutada peale mingi osa või loogika valmissaamist, kui vaatab veel koodi üle ja nii. Algsed kommentaarid tihti muutuvad või kaovad üldse ära

    kommentaar kirjutas marko — 2008-04-30 @ 16:30:54 | Vasta

  5. Oeh… XP guru luges ja tegi. XP ja muude agiilse maailma metoodikate juures on üks pisike ebamugav konks – koodi loetavus on äärmiselt oluline teema. Ja see teema on hulka mahukam, kui see ja eelmine blogi kanne. Võtame näiteks kontrollstruktuuride ja tsüklite struktuuri, indexeride nimetamise, koodi struktureerimise; seda nimekirja võiks jätkata veel pikalt. Selle kõige tulemuseks on kood, mis räägib suures osas iseenese eest. Eestis, muide, kohtab seda väääääga vähe, nimelisi näiteid oma lemmikute hulgast ei hakka tooma – ehk õpivad veel.

    Kommentaarid tuleb koodis lisada sinna, kus on koht, mis ei ole ilmne – tehtud on mingi otsus, mille sisu ei räägi iseenda eest. Selliseid otsuseid tuleb teha minimaalselt. Hea programmeerij akood on loetav, “elitaarsete häkkerite” kood on enamasti prügikasti kaup. Koodi dokumentatsioon on must-be. Ja kui kood on loetav, siis puudub igasugune vajadus pika ja lohiseva dokumentatsiooni järgi.

    Kui nüüd hea struktuur, väga hästi loetav kood ja kiiresti haaratavad kommentaarid kokku panna, saame tulemuseks mille? :)

    P.S. Arutelu koos selgitustega avaldan paari päeva jooksul DT blogis.

    kommentaar kirjutas Gunnar — 2008-05-02 @ 16:04:13 | Vasta

  6. Gunnar, ma pean tunnistama et su kommentaari mõte jäi üsna segaseks. Olen pidevalt rõhutanud, et koodi loetavus on oluline, kommentaarid ja muutujate nimetamine on üks selle aspekte – võibolla minu jaoks olulisemad, sest olen pidanud päris mitu korda halba koodi üle võtma.

    Käesoleva ja eelmise postituse eesmärgiks on kahe hea koodi aspekti kirjeldamine, mitte kogu hea koodi kirjutamiseks vajaliku info esitamine. Ma mõtlesin ka teha eraldi postituse koodi struktureerimisest, aga näeb kas selleni jõuan, niigi istub ports poolikuid drafte ootamas. Pealegi, tahan kogu seda teemat veidi rohkem enda jaoks lahti mõelda – näiteks millal on kasulik panna kaks partial klassi ühte faili jne.

    “Kommentaarid tuleb koodis lisada sinna, kus on koht, mis ei ole ilmne” – omaarust katsin selle ära lõiguga, mis algab “Koodi seletus on võibolla kõige levinum kommentaaritüüp.” ja lõpeb “Samas – kui kood on nii keerukas, et vajab seletamist, siis võib olla on parem mõte kood selgemaks kirjutada.”

    kommentaar kirjutas dukelupus — 2008-05-02 @ 18:08:30 | Vasta

  7. Ma seda pidasingi silmas, et teema on väga lai ja seda ühe kandega kokku kuidagi ei võta. Samas, too jõulisemalt esile head ja halvad näited. Umbes nii, et kui sinu (või miks mitte minu) nina ette satub mõni järjekordne programmiline “teos” otse ahjust, saaks autorile lingi pihku pista ja lasta tal asju korrastama hakata. :)

    See, millest ma kirjutada plaanin, on XP poolne ots, tehnilise ja inimkeelse teabe esitamise valguses. Kui suudan kompaktselt kirjutada, siis võtaks see mitmete heade tavade õldise kasu hästi kokku.

    Partial klassid – ma pole peale ASP.NET ja WIndows Forms’i vormide leidnud neile mingit asjalikku rakendust. Kihilise arhitektuuri kontekstis on nad mõttetud asjad, sest “teisel pool” kompilaatorit pole partial classi olemas. Kui IDE-s on näiteks andme- ja ärikiht lahendatud sama klassi osadena, siis on tegemist lauslollusega. Kihiline arhitektuur jääb kihiliseks arhitektuuriks ka kompileeerimise järel. ASP.NET ja Windows Forms seda reeglit ei riku, sest mõlemad on osad presentatsioonikihist ja pole vist kellelgi erilist vahet, millistest osadest see lõpptulemus seal kihi sees kokku lastakse. Tihti on isegi parem, kui klassi mingi kindla osaga tegelev automaatika ei tule oma tegemisi tegema sinna kohta, kus inimesed koodi kirjutavad. Kui aga leiad partial klassile mõne särava idee, siis olen loomulikult 1000% huviline.

    Kvaliteetse koodi osas – et selgeks mõtlemine sootuks uuele levelile hüppaks, on selline raju teos nagu Code Complete, mida ma julgen soovitada ka minust kordi kogenumatele progejatele. Kuigi ehk tugevamatele tegijatele on sealne kõik teada, on neilgi värskendav samu asju lugeda mõnes teises võtmes või esituses. Ma olen pea kindel, et kontorid, kus see raamat on olemas, on see pea kapsaks loetud ja kasutatud.

    kommentaar kirjutas Gunnar — 2008-05-02 @ 20:44:16 | Vasta

  8. Alustaks lõpust – Code Complete pole mul kapsaks loetud. Aga seda sel põhjusel, et ta on CHM’ina olemas. ;)

    CCv2 on hea raamat – soovitan samuti igale programmeerijale. Lugesin ta tegelikult sinu soovitusel läbi, olen plaaninud “lugemispäeviku” sissekannet teha selle kohta, aga… ehk kunagi jõuan. Esialgu vaja Peopleware lõpetada.

    Partial classes – olen neid ise kasutanud päris tihti Winformsi juures, näiteks suurema rakenduse juures hoides otsesed kasutajaliidese meetodid (so onclick handlerid jms) eraldi näiteks meetoditest, mis võrguga ühenduvad. Tehes partial class’i ja kasutades “this.” on pahatihti oluliselt lihtsam, eriti laisale inimesele nagu mina.

    Just täna pidin teiselt arendajalt ülevõetud Windows CF (Compact Framework, so Windows Mobile/CE) rakendusele lisama täiendava update-funktsionaalsuse. Kuivõrd antud rakenduses oli juba eraldi communication layer, siis kasutasin ära olemasolevaid klasse – aga kuivõrd kaks mind huvitavat klassi olid eraldi failides, mõlemad 400+ rida, siis tegin mõlemad klassid partial’iks ja täiendasin neid mõlemaid eraldi, omaette – aga ühes ja samas – failis. Ma pole kindel, kas see koodi selguse koha pealt oli hea või ei, seda ma pidasingi “mõtlema veel” juures silmas. Ühelt poolt on üks konkreetne funktsionaalsus koos ühes failis, teiselt poolt on klass jupitatud mitme faili vahele. Partial klassid võimaldavad koodi failide vahel paremini struktureerida, aga kui klass juba nii suureks ronib siis pigem tasuks juba arhitektuur uuesti läbi mõelda.

    Windows CF’ist – olen ammu igatsenud sellega tegeleda, nüüd viimased kaks-kolm nädalat olengi saanud. Peab ütlema et asi on kiire, meeldiv ja mugav. Debugimisel on VS 2005 surmaeglane, 2008 talutav. Kui aega on antud, siis teen ilmselt mõne aja pärast Compact Frameworkist eraldi kirjutise.

    Jään igatahes sinu postitust huviga ootama.

    kommentaar kirjutas dukelupus — 2008-05-02 @ 23:07:09 | Vasta


RSS feed for comments on this post. TrackBack URI

Lisa kommentaar

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Muuda )

Twitter picture

You are commenting using your Twitter account. Log Out / Muuda )

Facebook photo

You are commenting using your Facebook account. Log Out / Muuda )

Google+ photo

You are commenting using your Google+ account. Log Out / Muuda )

Connecting to %s

Create a free website or blog at WordPress.com.