A programozók alapjában véve lusták, és nem az önkifejezés nagy mesterei. Emiatt nem is igazán rajonganak a dokumentációkészítésért. Mindemellett még az is igaz, hogy a dokumentáció írásakor nem a jól bevált fejlesztő környezetükben kell dolgozniuk, hanem egy olyan helyen, ahol például nincsen az eszköztáron Build gomb (szövegszerkesztő). Emiatt mindig az utolsó utáni pillanatra halasztják a szoftver dokumentációjának elkészítését.
Nos, a dokumentációs kommentek ezen a helyzeten próbálnak meg javítani. Minden programozó használ többé-kevésbé kommenteket, hogy az általa előállított kódrészlet a későbbiekben is dekódolható legyen, vagy mások számára (itt fejlesztőre kell gondolni, nem átlag halandóra) is olvasható, érhető legyen. Miért ne lehetne ezeket felhasználni a dokumentációkészítéshez? A válasz nagyon egyszerű, mivel mindenki másképp csinálna. Ezért a Microsoft ezen úgy próbál meg segíteni, hogy ad egy ajánlást arra, hogy szerinte minkét kéne kinéznie a kommenteknek ahhoz, hogy utána lehessen belőlük dokumentációt generáltatni. Ehhez egy speciális formátumra van szükség, amelyet a szakirodalomban dokumentációs kommenteknek neveznek.
A dokumentációs komment feladata egyfelől az egységes kinézet/felület biztosítása a kommentekhez, másfelől pedig a hierarchiába szervezhetőség. Utóbbit nézzük meg részletesebben.
Általában amikor egy osztályt felkommentezzünk, akkor megadunk az osztályról egy általános leírást, amely röviden összefoglalja az általa megvalósított funkcionalitást. Másrészről az egyes függvényekhez, illetve metódusokhoz is meg szokás adni egy-egy részletesebb meghatározást. Vagyis az objektumok és a tagjaik közötti kapcsolatot célszerű a kommentek szintjén is eltárolni.
Egy másik fontos kapcsolat, amely szintén megjelenik a kommentek szintjén is, az az objektumok közötti hierarchia. Például hivatkozunk egy másik osztályra, amely használja ezt (akár példakód megadásával is), vagy fordítva, egy olyanra hivatkozunk, amelyet ebben szeretnénk felhasználni. Tehát ezeket a kapcsolatokat is célszerű eltárolni, az egymásra történő hivatkozhatóság miatt.
A Microsoft ahhoz, hogy a fentebb említett két fontos tulajdonságot (vagyis az egységes felületet, és a hierarchiába szerverhetőséget) be tudja vezetni a kommentek szintjére, úgy gondolta, hogy az XML nyelv használatára van itt is szükség. Ugyanis az XML-nél az egységes felületet könnyen lehet garantálni séma vagy definíciós fájlok segítségével, illetve az XML fájlok alapból hierarchikus felépítésűek.
Az XML nem csak a kommentek tárolásánál jelenik meg, hanem már forráskódban is (vagyis magunkban a kommentekben is). Ugyanis így könnyen lehet garantálni az egységes kinézetet már kód szinten is, másrészt pedig a forráskód elemező is így egyszerűbben elő tudja állítani a kommentekből a megfelelő XML fájlt. A Microsoft részéről itt véget is ér a sztori. Vagyis a kezünk be ad egy reprezentációs modellt (hogyan kommentáljunk), illetve egy a modellnek megfelelő leírást (a generált XML fájlt). Az, hogy ezzel mi ezek után mit kezdünk, az már a mi dolgunk – állítja az MS.
Formálisabban megfogalmazva az előző bekezdés végét: a rendszer biztosítja számunkra a dokumentációs kommenteket, illetve a dokumentáció generátort, de a dokumentáció megjelentő már a fejlesztő feladata. Erre az álláspontra (érhetetlen okból) a .NET 2.0 és a Visual Studio 2005 megjelenésekor tértek át. Ugyanis azelőtt az 1.X-es verzióknál az IDE-ben még volt támogatás dokumentáció megjelenítésre, úgynevezett web report formátumban. Sajnos ezt a 2005-ös változatból már kihagyták.
De hogy még se maradjunk megjelenítő eszköz nélkül a Microsoft nem sokkal a 2005-ös fejlesztő környezet megjelenés után nyilvánossá tette az általuk belsőleg is használt dokumentáció megjelenítőt, amely a SandCastle névre hallgat. Ezzel az eszközzel részletesebben is fogunk még foglalkozni a későbbiekben, ezért előjáróban csak annyit, hogy nem egyszerű használni. Ezért megjelentek a piacon olyan eszközök, amelyek teljes körű dokumentációkezelési támogatást nyújtottak, ilyen volt például a DoxyGen. (Ez így nem teljesen igaz, ugyanis a DoxyGen már előbb jelen volt, csak azelőtt a C# nyelvet nem támogatta).
Ennyi bevezető után, lássuk hogyan is néznek ki ezek a dokumentációs kommentek. Az egysoros dokumentációs komment három darab jobbra dőlő perjellel kezdődik, míg a többsoros változata ennek egy jobbra dőlő perjellel és két csillaggal kezdődik és egy csillag + egy perjel párossal záródik. Nézzünk ezekre egy egyszerű példát:
Utóbbit ritkán szokás használni, inkább az egysoros változat kezdő szimbólumait szokták ismételgetni. Amit ezekről még fontos megjegyezni itt az elején az az, hogy úgy kell őket használni, mint az attribútumokat, vagyis mindig az adott osztály, metódus, stb. fölé kell elhelyezni. Íme, egy konkrét példa:
Mint, ahogyan azt már fentebb is említettem, illetve, ahogyan azt a kódrészlet is mutatja, XML elemek segítségével történik a dokumentációs kommentek megadása. A summary az egyik legegyszerűbb, amely egy általános szöveges összefoglalás megfogalmazását teszi lehetővé.
Két dolgot jegyeznék még meg, mielőtt belekezdenék az ajánlott dokumentációs kommentek felsorolásába. Az egyik, hogy mivel XML alapú a rendszer, ezért szabadon bővíthető. A másik dolog szintén az XML alapúságból fakad: a generikus típusoknál különös elővigyázatossággal kell eljárni, ugyanis az xml elemek leírásához használt forma megegyezik a generikus paraméterek megadásának módjával. Ennek kivédésével a megfelelő dokumentációs kommentek résznél fogunk foglalkozni.
A dokumentációs kommenteket általában két nagy csoportba szokás osztani. Az egyiket magyar fordításban elsődleges, a másikat pedig másodlagos csoportnak lehetne nevezni. Az elsődleges csoportba olyan XML tag-ek tartoznak bele, amelyek a komment szintjén használhatóak. A másodlagos csoportba pedig azok kaptak helyet, akiket nem lehet önmagunkban használni, hanem be kell őket csomagolni, ágyazni egy elődleges kommentbe. Eme csoportosítás alapján a 22 alap dokumentációs komment:
- Elsődleges csoport: <example>, <exception>, <include>, <param>, <permission>, <remarks>, <returns>, <seealso>, <summary>, <typeparam>
- Másodlagos csoport: <c>, <code>, <description>, <item>, <list>, <listheader>, <term>, <typeparamref>, <para>, <paramref>, <see>, <value>
Egy másfajta szemléletmód szerint történő kategorizálása a kommenteknek a funkció szerinti csoportosítás (természetesen egy komment akár több funkcionális csoportba is beletartozhat). Ezek alapján az alábbi kategóriákat lehet megkülönböztetni: szövegformázó tag-ek, lista/táblázat készítő tag-ek, hivatkozás leíró tag-ek, általános leíró tag-ek, paraméter leíró tag-ek, és függvény leíró tag-ek. Íme, ezek alapján a 22 alap dokumentációs komment csoportosítása:
- Szövegformázó tag-ek: <c>, <code>, <param>
- Lista/Táblázat készítő tag-ek: <list>, <listheader>, <item>, <term>, <description>
- Hivatkozás leíró tag-ek: <see>, <seealso>, (<include>)
- Általános leíró tag-ek: <summary>, <remarks>, <value>, <example>
- Paraméter leíró tag-ek: <param>, <paramref>, <typeparam>, <typeparamref>
- Függvény leíró tag-ek: <returns>, <exception>, <permission>
A dokumentációs kommenteket a funkcionális csoportosítás szerint haladva fogom bemutatni.
Ez egy olyan formázó tag, amely segítségével inline vagy egysoros (tehát viszonylag rövid) kódrészlet stílusú szöveget lehet elhelyezni a kommentben. Vagyis a nyitó és záró tag-ek közé elhelyezett szöveg olyan betűtípust (Courier New-t) fog használni, mint amilyen a forráskód betűtípusa. Ezt általában osztály vagy metódus nevek formázására, illetve egysoros utasítások beszúrására szokták használni a kommenteken belül. Íme, egy egyszerű példa:
(A remarks tag osztályok általános leírására szolgáló tag, lásd lentebb bővebben.)
Ez a formázó tag nagyon hasonlít a c tag-re, a kettő között az a különbség, hogy a code-t többsoros forráskódok idézésére is használhatjuk. Általában az example (példaadásra használt leíró) tag-gel együtt szokott előfordulni a kommentekben. Íme, egy egyszerű példa a használatára:
(Természetesen az example tag-ek köré is kell tenni egy-egy remark tag-et.)
Ez egy olyan formázó tag, amely hosszú leírások esetén használatos, ugyanis ennek segítségével lehet paragrafusokat létrehozni. A html-es p tag-re hasonlít leginkább. Általában a remark és a summary tag-eken belül szokás használni. Íme, egy egyszerű példa:
Ezen lista/táblázat készítő tag segítségével számozást (számozott listát) vagy felsorolást (pontozott listát) lehet létrehozni, illetve akár táblázatot is. Azt, hogy éppen melyikre van szükségünk azt a type attribútumon keresztül tudjuk beállítani, amely az alábbi értékek valamelyikét veheti fel: bullet, number, table. Az egyes elemeket az item tag-ek segítségével lehet leírni, amelyek általában egy term és egy description tag-ből állnak. Van lehetőség címke (listákhoz) vagy fejlécsor (táblázathoz) megadására is a listheader tag segítségével, melynek felépítése megegyezik az item-éval. A list tag segítségével tehát úgy nevezett definíciós listát/táblázatot lehet létrehozni, vagyis megmondhatjuk, hogy mi (term), mit jelent (description). Íme, egy egyszerű példa (az előző példa táblázatos változata):
Ezen tag segítségével a táblázatokhoz fejlécsort, vagy listákhoz címkét/fejlécet lehet megadni. A html table objektumának th tag-jével hozható analógiába. Fontos: csak a list-tel együtt használható. Példa: lásd list példa.
Ez a tag arra szolgál, hogy egy lista egy elemét vagy egy táblázat egy sorát leírjuk vele. Alapból két alkotó elemből tevődik össze egy term-ből (mi) és egy description-ből (mit jelent). De van arra is lehetőség, hogy csak a description használjuk! A html table objektumának tr tag-jével hozható párhuzamba. Példa: lásd list példa.
Ezen tag megadása nem kötelező, de ha megadjuk, akkor azt mondja meg, hogy mihez találunk leírást a description tag-ben. Példa: lásd list példa.
Ezen tag egy táblázat- vagy egy listabeli elem leírását tartalmazza. Használható a term-mel együtt, illetve nélküle is. Mindig egy item tag-en belül kell lennie. Példa: lásd list példa.
Ez a tag a hivatkozások leírására szolgál. Egy másik osztályra, vagy egy metódusra történő hivatkozáskor, a cref attribútumon keresztül kell megadnunk annak a nevét. A tag manifesztációja a dokumentációban egy hiperlink lesz. Íme, egy egyszerű példa:
Ezzel a tag-gel a dokumentáció „See also” (~„Lásd bővebben”) részébe tudunk elhelyezni linkeket. A felépítése teljesen megegyezik a see tag-ével.
Ez a tag is a hivatkozás leíró tag-ek csoportjába sorolandó, de itt a hivatkozás alatt kicsit mást értünk, mint a see, vagy a seealso esetében. Ezzel egy XML dokumentumra (vagy annak részlétére) tudunk hivatkozni, amelyet a dokumentáció generálásakor a fordító behelyettesít a megfelelő xml tartalommal. A hivatkozás szintaktikája a következő: a file attribútum szolgál az xml dokumentum relatív elérési útjának megadására, a path opcionális attribútum pedig egy XPATH lekérdezést tartalmazhat. Íme, egy egyszerű példa:
Ez az egyik legáltalánosabb célú dokumentációs tag. Használható önmagában is, illetve konténerként is. A Microsoft ajánlása szerint a függvényeket és a metódusokat ezzel a tag-gel célszerű ellátni, és itt röviden összefoglalni az általuk megvalósított funkcionalitást. Példa: korábbi példák közül jó néhány.
Ez a tag nagyon hasonlít a summary-ra, a különbség a kettő között az, hogy míg a summary függvényekhez és metódusokhoz lett kitalálva, addig a remarks osztályoknál és interfészeknél használandó. A Visual Studio mindenhol alapból a summary-t ajánlja fel (a /// beírása után automatikusan beszúrja a forráskódba), ezért ezt kézzel át kell írni típusok kommentezése esetén. Példa: korábbi példák közül jó néhány.
Ez a tag az osztály tulajdonságainak felkommentezésére használható. Itt célszerű röviden összefoglalni, hogy mit és miért tárolunk el ezekben a tulajdonságokban, illetve adott esetben a módosíthatósági megkötésekre is fontos felhívni a figyelmet (pl.: csak olvasható). Íme, egy egyszerű példa:
Ez a tag általában a code-dal együtt használatos. Eme dokumentációs kommenttel példakódot adhatunk az adott osztály vagy függvény használatára, elérésére. (Az example tag alapból a tartalmát nem forráskód stílusban jeleníti meg, ezért van szükség a code tag-re). Példa: lásd code példa.
Ez a tag a függvény paramétereinek kommentezésére szolgál. Itt azt szokás megadni, hogy mit reprezentál az adott paraméter, módosítjuk-e a paraméter értéket a metódusban, illetve van-e a bemenő értékre valamilyen megkötés. Íme, egy egyszerű példa
Ezt a tag-et akkor szokás használni, ha egy függvény paraméterére szeretnénk hivatkozni valahol a kommentben (például valahol a summary-n belül). A hivatkozott paraméter nevét a name attribútumon keresztül lehet megadni. Íme, egyszerű példa (az előző példa kibővítése):
Ez a tag a generikus paraméterekhez történő megjegyzésfűzésre használható. Itt célszerű leírni, hogy az adott paraméterrel mit szeretnénk csinálni, illetve van-e rá valamilyen megkötés. A typeparam egyaránt használható generikus függvényeknél és generikus osztályoknál is. Íme, egyszerű példa:
Ezen tag segítségével lehet kommentben generikus paraméterre hivatkozni. A hivatkozást a name attribútumon keresztül kell megadni. Fontos, ha magára a generikus osztályra vagy függvényre szeretnénk a kommentben utalni, akkor nem használhatjuk a <,> jeleket, mivel az összezavarná az XML értelmezőt. Emiatt használjunk inkább a {} zárójeleket, vagy a html-nél is használt < > párost. Íme, egy egyszerű példa:
Ezzel a tag-gel a függvények visszatérési értékéhez lehet kommentet fűzni. Úgy is fogalmazhatunk, hogy a param ellentett párja, csak itt nincs returnsref. Általában itt a visszaadott típusban történő reprezentációról szokás egy-két szót ejteni. Íme, egy egyszerű példa:
A Java-val ellentétben, ahol kötelező kiírni a függvény által le nem kezelt kivételek teljes listáját a szignatúránál, C#-ban erre nincsen se mód, se lehetőség. Viszont ez egy eléggé hasznos dolog, ezért célszerű mindenesetben (még ha nem is készül dokumentáció a kommentekből, akkor is) az exception tag-et használni. (Illetve a lekezelt kivételekre is érdemes így felhívni a figyelmet). A cref attribútumon keresztül kell megadni a lehetséges Exception osztály nevét. A nyitó és a záró tag-ek közé pedig 2 információt ajánlott leírni: mikor keletkezhet ez a kivétel, és levan-e kezelve. Íme, egy egyszerű példa:
Ezzel a kommenttel azt írhatjuk le, hogy egy adott függvény milyen jogok mellett hívható meg, vagy egy adott típus milyen jogok mellett használható. Ha van rá bármilyen megkötés csak akkor van értelme ennek a kommentnek. Íme, egy értelmetlen példa:
A dokumentációs kommentekkel való ismerkedés után folytassuk tovább az utunkat a dokumentációgenerálásával. Ez a név kicsit félrevezető lehet, ugyanis itt nem arról van szó, hogy egy kész chm, vagy html alapú dokumentációt generáltatunk le a rendszerrel, hanem ebben a terminológiában azt értjük ez alatt, hogy a dokumentációs kommentekből egy xml dokumentum generálódik, amely egy helyen és egységes ábrázolja a kommenteket. Vagyis ez a dokumentáció modellje, ha úgy vesszük, ahonnan a dokumentáció megjelenítő majd kinyeri az adatokat.
Tehát ebben a részben az XML dokumentum előállításával és felépítésével fogunk foglalkozni. A dokumentációs kommentekből az XML fájl előállításához mindösszesen a C# fordítóra van szükségünk. Ennek van egy olyan speciális kapcsolója, amellyel az adott cs forrásállományból képes előállítani a megfelelő dokumentációs modellt. Ez a kapcsoló a /doc. Íme, egy egyszerű példa, amelyet a VS Command Promt-ból lehet kiadni:
Ennek persze van egy egyszerűbb és kényelmesebb módja is. Visual Studio-ban a projekt-en jobb egér gombbal kell kattintatni és ott a helyi menüből a Properties lehetőséget kell kiválasztani. Az új ablakban a Build fülre kell átváltani, majd ennek az Output szekciójában meg kell keresni az XML documentation file jelölőnégyzetet. Ezt pipálja be! Ilyenkor alapból a lefordított dll mellé helyezi el az xml fájlt, vagyis bin/debug mappába.
Ezek után nézzük meg, hogy mit is tartalmaz egy ilyen XML fájl. Íme, egy egyszerű példa:
A forrásállomány: Pair.cs
A belőle generált modell: PairDocumentation.xml
A generált XML állományban minden dokumentációs komment kap egy egyedi azonosítót, egyfelől az egymásra történő hivatkozás megkönnyítése végett, másrészt pedig a dokumentáció megjelenítőnek is szüksége van erre. Ennek az egyedi azonosítónak az előállítása egy viszonylag hosszú algoritmus alapján történik. Ezért az algoritmussal nem untatom a nagyérdeműt (akit esetleg érdekel, az megtalálhatja az MSDN-en), viszont a fentebbi kódrészletbeli példán keresztül megmutatom, mennyi információ tárol el a rendszer csak az azonosítókban.
A T:DocComDemo.Pair’2 részei:
T: A dokumentációs komment egy típushoz tartozik. Ha például egy metódushoz tartozna, akkor M lenne, vagy ha egy eseményhez, akkor pedig E.
DocComDemo.Pair: A teljes neve, annak az objektumnak, amelyhez a kommentet fűztük. (Metódusok esetén az esetleges paraméterek típusa is fel lenne itt sorolva.)
’2: 2 generikus paramétere van az osztálynak.
Végezetül elérkeztünk a dokumentáció megjelenítőhöz, amely értelmet ad a modellben tárolt adatoknak. Mint, ahogy azt a bevezetőben is említettem, alapból nem tartozik ilyen eszköz a Visual Studio-hoz, ezért ezt külön kell beszerezni. A Microsoft ajánlása erre a saját fejlesztésű SandCastle nevezetű program, amelyet az alábbi címről lehet letölteni: http://sandcastle.codeplex.com/.
A szoftver feltelepítése után úgy tudjuk használni a programot, hogy elindítjuk a hozzá tartozó grafikus felületet. Sajnos ez alapból nem jelenik meg a Start menüben, ezért nekünk kell megkeresünk és futtatnunk adminisztrátori jogokkal. Alapból az alábbi elérési úton keresztül érhetjük el: C:\Program Files\Sandcastle\Examples\Generic\SandcastleGui.exe.
A felületen keresztül meg kell adni az dokumentációs kommentekkel ellátott alkalmazás, vagy osztály könyvtár lefordított exe-jét, vagy dll-jét. Ezenkívül a C# fordító által generált XML fájlt is meg kell adni, illetve az esetleges + osztálykönyvtárakat is, amelyeket külön adtunk a projekthez hozzá. Ezek után be kell még állítanunk a dokumentáció nevét, a megjelenítési stílusát (alapból vs2005, de a prototype is egész jó), illetve a leendő formátumát (chm, sima html, vagy hxs). Végezetül már csak rá kell kattintani a Build gombra, ahol először el kell menteni a projektet és csak utána kezdődhet meg a tényleges munka. A végleges dokumentáció elkészítésének ideje nagyban függ a projekt méretéttől, de az általánosságban elmondható róla, hogy nem sieti el a dolgot.
Fordítás közben töménytelen log információt kapunk, amelyek viszont nem túl sok hasznos információval szolgál. Ha elsőre nem generálja le rendesen a dokumentációt, akkor célszerű letölteni a SandCastle-höz készült kis segédalkalmazást, amely egyrészt a rengeteg log-ot képes érhető, emészthető formába átkonvertálni, illetve nagyobb testreszabhatóságot is biztosít. Az alábbi címről tölthető le a SandCastle Help File Builder nevezetű program: http://shfb.codeplex.com/.
A dokumentációs kommentek használata mindenféleképpen javaslott, ugyanis így átláthatóbb lesz tőle a programkód, illetve lehet belőle dokumentációt gyártani és még az IntelliSence is fel tudja használni!