Ještě jednou a lépe: umělecké komentáře

Od Petr Zemek, 2013-12-07

Občas se v projektech setkávám s komentáři, které připomínají umělecké dílo. Většinou jsou nějakým pěkným způsobem ohraničeny a jejich obsah je zarovnán podle určitých pravidel. Taktéž mnohdy obsahují nadbytečné informace jen pro to, aby vše bylo konzistentní v rámci celého projektu. Dneska se zkusíme podívat na to, jak to udělat lépe.

Původní kód

Jako příklad dám vykonstruované komentáře na začátku souboru a před funkcí:

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//                            An Awsome Project                              //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  Author:  Name Surname <email@domain.net>                                 //
//  File:    some_file.h                                                     //
//  Info:    This file contains some stuff.                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//   Date/time    Author         Change                                      //
//                                                                           //
//   2003-07-20   Name Surname   Created the file.                           //
//   2003-08-01   Name Surname   Added a new function: isDone().             //
//   2003-08-02   Name Surname   Fixed the implementation of isDone().       //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
 
 
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//                               isDone                                      //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Parameters:                                                               //
//   * task       - a task                                                   //
//   * timeLimit  - a time limit                                             //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Returns: true if the given task is done within the given time limit,      //
//          false otherwise                                                  //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
bool isDone(const Task &task, int timeLimit);

Proč takto raději ne?

Důvodů je celá řada:

  • Udržovatelnost. Udržovat takové komentáře je peklo. S každou změnou je nutné upravit i odsazení či zarovnání znaků, které tvoří vatu kolem užitečného textu. Programátor se pak buď změnám v kódu vyhne, jen aby nemusel upravovat komentář, nebo změní pouze kód a komentář nechá původní. Mozková kapacita programátorů lze rozhodně využít lépe, než na "kreslení" komentářů.
  • Redundantnost. Všimněte si, že spoustu informací v komentářích je nadbytečných. Např. soupis změn v souboru. O ty by se měl starat váš verzovací systém (git, mercurial, svn atd.) a je zbytečné je nadbytečně uchovávat v komentářích k souboru. Dále, když se změní název funkce isDone, tak je potřeba provést tuto změnu na více místech. Jedna z těchto změn bude navíc zahrnovat hraní si s komentářem. Další ukázkou nadbytečnosti je popis parametrů této funkce, protože konzistence vám diktuje, abyste u každé funkce měli uvedeny všechny tyto bloky (název funkce, popis parametrů, popis návratové hodnoty atd.). Např. zde je z názvu parametrů jasné, o co se jedná, takže není potřeba používat podobné, nic neříkající popisy, jako že timeLimit je opravdu časový limit.
  • Nepoužitelné pro existující generátory API dokumentace. Generátory (např. doxygen) potřebují, aby komentáře byly v určitém tvaru. Pokud si vymyslíte vlastní umělecký styl, tak si budete muset napsat generátor vlastní. To je v drtivé většině případů ztráta času.
  • Nevhodnost pro automatizované zpracování. Napsání skriptu, který vám bude aktualizovat některé informace bude stížené faktem, že je při každé změně potřeba "sesynchronizovat" zarovnání a uspořádání vyplňujících znak. Taktéž syntaktická analýza (parsing) údajů bude komplikovanější.

Jak to udělat lépe?

Vyřešíme všechny problémy najednou, a to psaním komentářů v jednoduchém stylu, uchovávající pouze užitečné informace a umožňující použít generátor pro API dokumentaci. Jelikož se jedná o projekt v C++, tak zvolíme doxygen:

///
/// @author Name Surname <email@domain.net>
/// @file path/to/some_file.h
/// @brief This file contains some stuff.
/// @date 2003-07-20
///
 
///
/// @brief Returns true if @a task is done within @a timeLimit, false
/// otherwise.
///
bool isDone(const Task &task, int timeLimit);

Jak vidíme, kód se zjednodušil, neobsahuje redundantní informace a jeho údržba už nevyžaduje pevné nervy. U funkce isDone není třeba extra popisovat její parametry, protože z jejich názvu je jasné, o co jde. Taktéž není třeba zmiňovat její název, protože ten je hned pod komentářem. Název projektu si můžete specifikovat v konfiguračním souboru pro doxygen. Seznam změn by nám měl uchovávat náš verzovací systém. To je pak radost s takovým kódem pracovat a udržovat jej.

Na závěr si dovolím tři poznámky ke kódu výše:

  • Styl doxygen komentářů si můžete samozřejmě zvolit, pokud se vám tento nelíbí. Je však dobré v rámci projektu používat jednotný styl. Váš editor vám může být nápomocen při jejich vytváření a úpravě (např. gq ve Vimu, které vám vezme označený text a zarovná jej tak, aby nepřesahoval daný počet znaků na řádku s tím, že se automaticky postará o komentáře).
  • Datum u souboru (@date 2003-07-20) uvádím i přesto, že je to dohledatelné z verzovacího systému. Je pak na první pohled jasné, jak moc starý ten soubor je (v jaké době vznikl). Pokud tuto informaci nepotřebujete, tak lze toto vyhodit.
  • Cestu k souboru v doxygen komentáři (@file path/to/some_file.h) většinou uvádím z toho důvodu, že pokud se v projektu vyskytnou dva soubory se stejným názvem, tak doxygen je má na základě čeho odlišit. Pokud se vás toto netýká, tak jej tam nemusíte uvádět. Pokud vás trápí, že při změně názvu souboru či jeho přemístění je potřeba změnit tento komentář, tak máte pravdu. Jelikož je ale komentář velmi jednoduchý, lze si napsat skript, který toto přejmenování bude řešit za vás, a to v celém projektu. To je ale už na jiný příspěvek.
Obsah tohoto pole je soukromý a nebude veřejně zobrazen.

Filtrované HTML (využíváno)

  • Povolené HTML značky: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <table>
  • Zvýraznění syntaxe kódu lze povolit přes následující značky: <code>, <blockcode>, <bash>, <c>, <cpp>, <haskell>, <html>, <java>, <javascript>, <latex>, <perl>, <php>, <python>, <ruby>, <rust>, <sql>, <text>, <vim>, <xml>, <yaml>.
  • Řádky a odstavce se zalomí automaticky.
  • Webové a e-mailové adresy jsou automaticky převedeny na odkazy.
CAPTCHA
3 + 5 =
Vyřešte tento jednoduchý matematický příklad a vložte výsledek. Např. pro 1+3 vložte 4.
Nějak se mi tady rozmohl spam, takže poprosím o ověření.