Komentáře jsou nejdůležitější částí kódu

cs v kategorii code • 9 min. čtení
Mind the age! Most likely, its content is outdated. Especially if it’s technical.

Už je tomu šest let, co jsem psal o hezkém kódu na Zdrojáku. Sice bych to dnes po zkušenostech na několika velkých projektech napsal lehce jinak, ale stejně je skvělé, jak jsem se sám tenkrát k něčemu takovému dostal a dokázal sdílet s ostatními. Každopádně – popisoval jsem, že komentáře je lepší nepsat. Pokud je nutkání napsat komentář, mnohem lepší varianta je upravit kód, aby byl samopopisný.

S tím stále souhlasím. Dostal jsem se však do bodu, kdy i když je kód popisný a hezký, komentář napíšu. To hned z několika důvodů. Ukážu na příkladech. První příklad budiž snippet z Flasku:

@app.before_request
def require_login():
    if is_user_logged_in():
        return
     if flask.request.endpoint == 'static':
        return
     view = get_current_view()
    if not view:
        return
     if is_view_public():
        return
     flask.abort(403)

Když přečtu za sebou, jak je, hned je zřejmé, co se děje. Volně přeloženo do češtiny: ověř přihlášení před zpracováním jakéhokoliv požadavku. Ale proč se to netýká statických souborů? Statické soubory nejsou chráněné? A vlastně – proč statické soubory řeší Flask a ne něco rychlejšího? Komentáře hned objasní…

@app.before_request
def require_login():
    if is_user_logged_in():
        return
     # Static files are not protected. Only in development without nginx.
    if flask.request.endpoint == 'static':
        return
     # Not found page is not protected.
    view = get_current_view()
    if not view:
        return
     if is_view_public(view):
        return
     flask.abort(403)

Pojďme na další ukázku z jednoho malého scriptu, který jsem nedávno psal:

def load_config_variable(key):
    variable = connection.configserver.variable.getAttributes(key)
    utc = dateutil.tz.tzoffset(None, 0)
    local = dateutil.tz.tzlocal()
    variable['since'] = variable['since'].replace(tzinfo=utc).astimezone(local)
    return variable

Opět je jasné, co se děje. Načítám proměnnou z konfiguračního serveru. Jenže, proč se tu přepočítává datum do jiné časové zóny? A proč zrovna do lokální a ne do jiné? Co se stane, když se změní čas z letního na zimní a obráceně?

#FIXME: Konexe ma spanou implementaci casovych zon. Z aware RPC datetimu prevadi
#       na naive Pythoni datetime (se ztratou informace o zone se zapocitanim
#       offsetu). Takze tu mame naive datum v UTC. Musime ho obohatit tedy o
#       zonu, aby slo do configserveru zpet zapsat.
#       Smazat jakmile se opravi prace se zonou v RPC.

Nyní už není pochyb, proč to tu je. Dokonce i co je potřeba udělat, aby bylo zase v pořádku.

Další ukázka z Reactu:

let EntryActions = {
    (...)
    reportProblem: function(id) {
        AppDispatcher.handleAction({
            actionType: RSSConstants.ENTRY_REPORT_PROBLEM,
            id: id,
        });
        EntryService.reportProblem(id);
    }
    (...)
};

Z úryvku je patrné, že se při odpálení akce z UI vyšle, že je s nějakým záznamem problém. To se pomocí service odešle na server. Ale co když se komunikace se serverem nezdaří? Na to tu nikde není žádný kód, to vypadá na chybu. S komentářem opět dodá informaci o úmyslu:

// Dve moznosti:
//  1) Jen na par tydnu, nez se vyladi zaznamy. Jelikoz se brzy smaze,
//     nema tedy smysl resit rollback v UI.
//  2) Nebo se bude ladit donekonecna, pak ale bude potreba i vyzadovat komentar,
//     aby se dobre zpracovavalo, a tudiz udelat jinak, tedy nema smysl resit rollback v UI.

Další příklad mohou být Jasmínové testy. Kolega napsal vše v pořádku, ale u jednoho describe měl pouze jeden it s prázdným popisem. Zdálo se mi to jako chyba. Přitom to měl promyšlené – struktura testů byla dle logických celků, ale jedna malá drobnost do toho ne úplně zapadala. Ale zachoval to, což bych při návštěvě kódu pravděpodobně změnil. Poprosil jsem ho tedy o komentář, jak zamýšlel strukturu testů, aby další kolemjdoucí dodržel.

Jinými slovy se snažím říct, že vy možná právě teď komentáře u čitelného kódu nepotřebujete. Komentáře s úmyslem jsou ale pro ostatní, včetně vás za pár měsíců či týdnů. Záleží jak dobře paměť slouží. Protože s takovými komentáři se lze vyhnout zbytečným chybám. Líbil se mi na toto téma tweet s následujícím gifem a popiskem „Why is this code here? We don’t need this.“. :-)

Dokonce jsem zjistil, že mi pomáhá psát komentáře průběžně při vývoji všeho možného. Často sahám na spoustu míst a měním několik věcí najednou. Prototypuji. Rychle kód prasím. Až pak ho uhlazuji. Přijde mi to rychlejší než sáhodlouze přemýšlet, jak to udělat hezky na první dobrou. Proto si píšu komentáře, co se mi honí hlavou, a při uhlazování je postupně zpracovávám. Ve výsledku commitnu minimum napsaných komentářů, neb je proměnním v samopopisný kód a zůstanou jen ty komentáře vysvětlující úmysl.

A jelikož nejlepší komentář vysvětluje úmysl, přijde mi, že je častokrát důležitější, než kód samotný. Udělal jsem si takový malý průzkum a zjistil, že neexistuje žádný skin, kde by komentář nebyl téměř neviditelný. Proto jsem si sám ve všech používaných editorech nastavil komentáře tučně a křiklavě červené. Mám to tak přes měsíc a naprostá spokojenost.

Už jen škoda míst, kde nelze psát komentáře. Například v debianích souborech bych rád napsal, proč se například do deb balíku dávají i nějaké soubory a jiné naopak ne. Když to pak nejde, musí se napsat do dokumentace bokem. Jenže já mám tak rád, když se dokumentace generuje z kódu a nemusím na to myslet…

Na závěr taková perlička. Před dvěma lety jsem napsal takový ne zrovna hezký (asi tak jako samotný úkol), ale funkční, algoritmus na automatické generování práv v aplikaci. Napsal jsem k pár řádkům následující komentář (na který jsem úspěšně zapomněl) a kluci před pár dny našli:

# So you found a bug here. It's probably 2016. You know, it can't be
# fixed. You have to rewrite it completely. And what about your trip to
# Australia, was it good?

:-)






4 reakce

Naprostý souhlas. Proto nemám vůbec radost z toho, že se jako formát pro zápis konfigurace rozmohl JSON, kde se komentáře psát nedají.

@Vaclav: Relevantní čtení: https://plus.google.com/+DouglasCrockfordEsq/po... . Tomu pak odpovídá třeba popularita balíčku https://www.npmjs.com/package/strip-json-comments

Mnoho nástrojů podporuje i jiný formát konfigurace (JS, YAML, XML), případně provedou ořez komentářů, nebo dovolují zápis komentáře jiným způsobem (https://groups.google.com/forum/#!msg/nodejs/Nm...).

U open source pak máme často možnost poslat pull-request a nový formát konfigurace doprogramovat :-)

Líbí se mi, jak to řeší třeba ESLint - podporuje JSON, JS a YML soubory. Uživatel má na výběr, jestli primitivní konfiguraci, nebo vykonatelný kód nebo čistý YML zápis s komentáři.

Tak Amazon asi nepřesvědčím, aby v AWS umožnili konfiguraci v YAML :)

Přidat tam preprocessor by šlo, ale přijde mi to jako drbání se pravou rukou za levým uchem.

@Tomáš, @Václav: https://plus.google.com/+DouglasCrockfordEsq/po...

„I removed comments from JSON because I saw people were using them to hold parsing directives, a practice which would have destroyed interoperability. I know that the lack of comments makes some people sad, but it shouldn't.

Suppose you are using JSON to keep configuration files, which you would like to annotate. Go ahead and insert all the comments you like. Then pipe it through JSMin before handing it to your JSON parser.“





Může se vám také líbit

en Makefile with Python, November 6, 2017
en Fast JSON Schema for Python, October 1, 2018
en Deployment of Python Apps, August 15, 2018
cs Jasně, umím Git…, August 6, 2014
cs Checklist na zabezpečení webových aplikací, March 1, 2016

Další články z kategorie code.
Nenechte si ujít nové články díky Atom/RSS kanálu.



Poslední příspěvky

cs Mami, tati, přejde to, December 9, 2023 in family
cs Co vše bychom měli dělat s dětmi?, November 24, 2023 in family
cs O trávicí trubici, November 7, 2023 in family
cs Na šestinedělí se nevyspíš, October 28, 2023 in family
cs Copak to bude?, October 20, 2023 in family