Tworzenie dokumentacji w systemie Doxygen.
Warto komentować kod. Warto robić to w taki sposób, aby później możliwe było automatyczne wygenerowanie dokumentacji projektu.
Przy dużych przedsięwzięciach żadna poważna firma nie pozwoli sobie na odstępstwa od tych zasad. Współdziałanie programistów oraz prawidłowy nadzór architektów oprogramowania jest możliwy głównie poprzez dobrze udokumentowany kod. Ale i przy małych projektach odpowiednio sformatowane komentarze mogą się przydać. Małe programy lubią się przecież rozrastać, a niektóre, dobrze działające fragmenty kopiujemy często do innych projektów. I właśnie wtedy przydaje się dokumentacja kodu.
Czy warto jednak korzystać z programu Doxygen? Przedstawię w tym artykule kilka aspektów związanych z używaniem tego systemu, a odpowiedź na powyższe pytanie zostawiam Czytelnikowi.
Spis treści:
- Kilka informacji wstępnych.
- Szybki start w świecie "Doxy".
- Sposoby komentowania.
- Doxywizard, tj. minimum wysiłku, maksimum korzyści.
- Szczegóły związane z plikiem konfiguracyjnym.
- Możliwości.
- Znaczniki komentarzy.
- Tworzenie odnośników.
- Tworzenie list.
- Pomijanie komentarzy.
- Co jeszcze potrafi Doxygen?
- Czego zrobić się nie da?
- Porównanie systemów tworzących dokumentację projektu.
- Przykład kodu skomentowanego dla systemu Doxygen.
Kilka informacji wstępnych
Doxygen to system tworzenia dokumentacji kodu źródłowego, stworzony dla wielu języków programowania, m.in. dla języka Python, C, C++, JAVA i PHP.
Autorem projektu jest Dimitri van Heesch.
Program dostępny jest na licencji GNU/LINUX, a więc tym staranniej powinniśmy spróbować zapamiętać nazwisko twórcy.
Doxygen rozwijany jest w systemie Linux oraz MAC OS X, ale dostępny jest również na innych platformach UNIX'owych i w MS Windows.
Doxygen na podstawie odpowiednio formatowych komentarzy kodu źródłowego generuje dokumentację w następujących formatach:
- HTML,
- PDF,
- RTF,
- PostScript,
- format HTML Help (format plików pomocy w środowisku Windows - *.chm),
- XML,
- Man pages (strony dla podręcznika man),
- LaTeX
Doxygen jest kompatybilny z innymi popularnymi systemami tworzenia dokumentacji - Javadoc (/** ...@... */) oraz QT-doc (/*! ...\... */).
Doxygen bardzo ułatwia tworzenie dokumentacji, jednak nie można zapominać, że efekt końcowy zależy głownie od nas.
Jak każde udane przedsięwzięcie programistyczne jest to program, z jednej strony, bardzo łatwy w obsłudze, z drugiej - daje duże możliwości.
Szybki start w świecie "Doxy"
Instalacja programu Doxygen w systemie Windows jest bardzo prosta. Standardowa polega na parokrotnym kliknięciu klawisza "Next".
Czytelnicy zainteresowani instalacją w innych systemach operacyjnych powinni zapoznać się z podręcznikiem Doxygena ("Doxygen manual").
Sposoby komentowania
Aby komentarz był "czytelny" dla Doxygena, musimy skorzystać z któregoś z poniższych sposobów.
/**
* Komentarze
*/
|
/*!
* Komentarze
*/
|
Oczywiście wewnątrz komentarza możemy używać szeregu znaczników, które ułatwiają automatowi wygenerowanie dokumentacji. Np.
@author XYZ (w składni Javadoc), albo
\author XYZ (w składni QT-doc).
Znaczniki szerzej zostaną omówione w dalszej części.
Gwiazdki bezpośrednio przed tekstem komentarza są opcjonalne. Można napisać tak:
/**
Komentarze
*/
|
/*!
Komentarze
*/
|
Trzecim, dodatkowym sposobem, jest zapis:
///
/// Komentarz
///
|
//!
//! Komentarz
//!
|
Trzeba jednak pamiętać, że nad lub pod komentarzem z tekstem musi znaleźć się co najmniej jeden inny komentarz (np. pusty, tak jak powyżej).
Doxywizard, tj. minimum wysiłku, maksimum korzyści
Jeśli już stworzyliśmy prawidłowo skomentowany kod, następnym krokiem jest uruchomienie Doxywizard.
Jest to program, który w przyjazny sposób przeprowadzi nas przez proces konfigurowania parametrów dokumentacji, a następnie wygeneruje ją.
Po uruchomieniu Doxywizard pojawi się bardzo intuicyjny interfejs.
W "Step 1: Configure doxygen" włączmy opcję "Wizard...".
Następnie podajemy kilka podstawowych informacji odnośnie projektu: nazwę, wersję, ścieżkę do kodów źródłowych, itd. Pamiętajmy, aby zaznaczyć opcję "Scan recursively", jeśli poszczególne pliki naszego projektu znajdują się w drzewie katalogów.
Po ustawieniu opcji klikamy "OK" i w "Step 2" zapisujemy plik konfiguracyjny o domyślnej nazwie "Doxyfile".
Pozostaje nam jeszcze tylko wybranie katalogu roboczego ("Step 3") oraz kliknięcie "Start" ("Step 4").
Poczekajmy chwilę na informację "*** Doxygen has finished" i... gotowe!
W czterech prostych krokach stworzyliśmy dokumentację.
Szczegóły związane z plikiem konfiguracyjnym
Doxywizard pozwolił nam w łatwy sposób stworzyć plik konfiguracyjny programu (w punkcie "Step 2"). To właśnie od tego pliku zależy, jak będzie zachowywał się Doxygen przy generowaniu dokumentacji. Warto poświęcić czas na poprawne skonfigurowanie pliku Doxyfile, bo może on przydać się nie tylko przy ponownym generowaniu dokumentacji bieżącego projektu, ale także przy kolejnych (należy wtedy pamiętać jedynie o zmianie ścieżek katalogów).
Plik konfiguracyjny można stworzyć na trzy sposoby:
- Wygenerować go korzystając z opcji "Wizard..." programu Doxywizard (tak, jak zrobiliśmy to przed chwilą),
- Skorzystać z opcji "Expert..." Doxywizard,
- Stworzyć go w linii poleceń na podstawie wzorcowego pliku konfiguracyjnego.
W podkatalogu "bin" katalogu instalacyjnego znajduje się główny plik programu - "doxygen.exe". Wzór pliku konfiguracyjnego można stworzyć poleceniem:
doxygen.exe -g nazwaPlikuKonfiguracyjnego
bądź samym: doxygen.exe -g
(wzór zostanie zapisany pod domyślną nazwą "Doxyfile").
Następnie należy wyedytować ten plik i pozmieniać zapisane w nim opcje według uznania (w większości przypadków sprowadza się to do wpisania przy opcji słowa "YES" bądź "NO").
Aby wygenerować dokumentację wydajemy polecenie:
doxygen.exe nazwaPlikuKonfiguracyjnego
bądź samo doxygen.exe
jeśli nasz plik nazywa się "Doxyfile".
Z pewnością tryb "Wizard..." szybko przestanie nam wystarczać i spróbujemy któregoś z dwóch pozostałych sposobów na stworzenie pliku konfiguracyjnego.
Sposoby drugi i trzeci są bardzo podobne. Tryb "Expert..." stanowi jedynie graficzny interfejs, który pozwala w łatwy sposób edytować plik Doxyfile.
Kilkanaście zakładek tego trybu pozwala na swobodną konfigurację programu.
- Zakładka "Project"
Podstawowe opcje działania automatu.
- "Build"
Opcje sposobu tworzenia dokumentacji.
- "Messages"
Opcje komunikatów.
- "Input"
Opcje ścieżek do źródeł.
- "Source Browser"
Opcje cytowania źródeł.
- "Index"
Opcje tworzenia indeksu.
- "HTML", "LaTeX", "RTF", "man", "XML"
Opcje tworzenia dokumentacji w postaci (odpowiednio) stron HTML, dokumentu LaTeX, RTF, stron man oraz pliku XML.
- "DEF"
Opcje generowania definicji AutoGen. W najnowszej wersji (Doxygen 1.5.1) współpraca między Doxygenem a programem AutoGen nie jest jeszcze w pełni zaimplementowana.
- "PerlMod"
Opcje pozwalające na stworzenie modułu do PERLa, który "przechwyci" strukturę kodu wraz z dokumentacją. Podobnie jak powyżej, opcje te są jeszcze niekompletne.
- "Preprocessor"
Opcje przetwarzania poleceń preprocesora.
- "External"
Opcje tworzenia odsyłaczy do zewnętrznej dokumentacji.
- "DOT"
Opcje wykorzystywane przy tworzeniu grafów zależności między klasami, itp.
- "Search"
Opcje tworzenia funkcji wyszukiwania w dokumentacji HTML. Należy pamiętać, że do działania wyszukiwarki potrzebny jest serwer z zainstalowanym PHP.
Możliwości
Możliwości programu Doxygen są naprawdę duże. Oprócz setek opcji w pliku konfiguracyjnym powiększa je mnogość znaczników, które możemy, a nawet powinniśmy, umieszczać wewnątrz komentarzy.
Znaczniki komentarzy
Zacznijmy od strony głównej dokumentacji. Domyślnie nie ma na niej żadnych informacji, są jedynie nazwa projektu oraz linki nawigacyjne.
Aby dodać jakiś tekst na stronę główną (np. opis projektu, charakterystykę ważniejszych metod, itp.), należy użyć znacznika
@mainpage bądź
\mainpage. Ja będę dalej korzystał z pierwszego sposobu zapisu znaczników, właściwego dla Javadoc.
Jeśli dokumentujemy klasę, funkcję bądź zmienną, należy pamiętać, że mogą one mieć jeden opis skrócony oraz jeden opis szczegółowy.
Opis skrócony można rozpocząć znacznikiem
@brief, np.
/** @brief Opis skrócony.
* Dalej opis skrócony.
* Dalej opis skrócony.
*
* Dopiero tu rozpoczyna się opis szczegółowy.
*/
Opis skrócony kończy się dopiero po pustej linii komentarza. Trzeba jednak pamiętać, że opis skrócony powinien być... krótki. Zazwyczaj nie ma sensu, aby rozciągał się na więcej niż jedną linijkę.
Przy rozróżnieniu między komentarzami skróconymi i szczegółowymi ważna jest konfiguracja "JAVADOC_AUTOBRIEF". Domyślnie, w wersji 1.5.1 jest ona wyłączona.
Jeśli włączamy opcję "JAVADOC_AUTOBRIEF", za opis skrócony uznany będzie tekst do pierwszej kropki, po której następuje spacja bądź złamanie linii. Wszystko co znajduję się po tym, jest opisem szczegółowym.
Czyli np.:
/** Opis skrócony. Opis szczegółowy.
*/
/** Opis skrócony.
* Opis szczegółowy.
*/
Przy tworzeniu komentarzy dotyczących całego projektu, warto użyć poniższych znaczników:
@author XYZ
@date 2006.12.12
@version 1.0
Niektóre, często używane znaczniki, znajdują się w poniższej tabeli.
Pozostałe dostępne są w "Doxygen manual".
@b slowo
|
Wyświetla "slowo" czcionką pogrubioną.
|
@e slowo
|
Wyświetla "slowo" czcionką pochyłą.
|
@c slowo
@p slowo
|
Wyświetla "slowo" czcionką maszynową.
|
@code
@endcode
|
Stworzony zostaje blok kodu. Jest on interpretowany jako kod C / C++, ale można go używać komentując kod napisany także w innych językach.
Blok ten jest odpowiednio sformatowany.
|
@exception obiektWyjatku Opis wyjatku
@throw obiektWyjatku Opis wyjatku
|
Opis obiektu wyjątku.
Kolejne, przylegające do siebie linie rozpoczęte od "@exception" zostają zgrupowane w jeden paragraf. Np.:
@exception std::out_of_range Parametr jest poza zakresem.
|
@image format nazwaPliku ["opis zdjecia"] [<sizeindication>=<size>]
|
Wstawienie obrazka.
Zamiast "format" należy wstawić "html" bądź "latex" (tylko te dwa formaty są obsługiwane).
Zamiast "nazwaPliku" wpisujemy nazwę pliku. Jeśli zawiera ona spację, to umieszczamy ją w cudzysłowach.
Należy wcześniej zdefiniować opcję "IMAGE_PATH", np. IMAGE_PATH = mojeObrazki
Kolejne dwa argumenty są opcjonalne.
Można określić opis obrazka (należy pamiętać o niezbędnych cudzysłowach).
Ostatni argument definiuje szerokość i wysokość obrazka i można go używać tylko przy formacie "LaTeX".
|
@n
<br>
|
Wymusza nową linię.
|
@note tekst
|
Tworzy paragraf z dodatkową wiadomością (notatką).
Zostanie on wyszczególniony w dokumentacji.
Kolejne, przylegające do siebie linie rozpoczęte od "@note" zostają zgrupowane w jeden paragraf informacyjny.
|
@page nazwa tytul
@ref nazwa
|
Znacznik "@page" wskazuje, że zawartość nowego bloku nie jest ściśle związana z jakąś klasą, czy zmienną.Stworzony zostaje osobny blok z informacjami, do którego później możemy się odnieść za pomocą "@ref". Np.:
/**
* @page strona1 Strona nr1
* Szczegolowy opis...
*/
/**
* Opis...
* Wiecej informacji znajdziesz tutaj: @ref strona1.
*/
Jeśli tworzymy dokumentację w formie strony internetowej, to "tytul" stanie się odnośnikiem do innej strony.
"nazwę" najbezpieczniej jest tworzyć z małych liter, ewentualnie można dodać cyfry.
|
@subpage nazwa tytul
|
Stworzone zostają podstrony w jakiejś stronie. Do podstron można się odnosić za pomocą "@ref" w analogiczny sposób jak do stron.
|
@par
@par tytul
|
Stworzony zostaje nowy paragraf z dokumentacją. Jeśli podamy tytuł, zostanie on odpowiednio wyszczególniony. Np.:
/**
* Normalny tekst
*
* @par Informacje
* Zawartosc paragrafu
*
* @par
* Nowy paragraf, bez nazwy.
*/
|
@param nazwaParametru Opis
|
Opis parametrów przyjmowanych przez metodę.
Np.:
@param i Argument typu int.
Znacznik ten ma dwa opcjonalne atrybuty: "in" oraz "out". Używa się ich, jeśli parametry służą zarówno do przyjmowania jak i zwracania wartości. Przykład użycia:
@param[out] destination Pamiec do ktorej skopiujemy dane.
@param[in] source Pamiec, z ktorej skopiujemy dane.
Kolejne, przylegające do siebie komendy "@param" zostają zgrupowane w jeden paragraf (kolejne parametry wypisywane są w osobnych liniach).
|
@relates nazwaFunkcji
|
Funkcja o takim znaczniku umieszczona zostanie wewnątrz dokumentacji funkcji o nazwie "nazwaFunkcji".
Znacznik ten przydaje się przy dokumentowaniu funkcji, które nie są funkcjami zaprzyjaźnionymi, a mimo to są silnie związane z jakąś klasą. Np. umieszczenie nad jakąś funkcją komentarza:
/** @relates obslugaNapisow
* Opis funkcji...
*/
spowoduje dodanie dokumentacji tej funkcji do dokumentacji funkcji "obslugaNapisow"
|
@return opis zwracanej wartosci
|
Opis zwracanej przez funkcję wartości. Np.:
@return Liczba typu float
|
@verbatim
@endverbatim
|
Stworzony zostaje blok tekstu, który nie jest analizowany przez automat Doxygena.
|
Chcąc użyć w dokumentacji któregoś ze znaków: $, @, \, &, ~, <, >, #, %, musimy zastosować backslash.
- \$
- \@
- \\
- \&
- \~
- \<
- \>
- \#
- \%
Tworzenie odnośników
Program automatycznie zastępuje adresy www i adresy e-mail linkami.
Linki tworzą się też same jeśli użyjemy nazwy znanych Doxygenowi klas.
Przy nazwach zmiennych i funkcji trzeba użyć "::". Np. jeśli chcemy odwołać się do metody "member" z klasy "Test", napiszemy:
Test::member, lub
Test::member(int), jeśli mamy kilka przeładowanych metod.
Tworzenie list
Tworząc dokumentację może zajść potrzeba zrobienia listy. I w tym przypadku możemy zrobić to na kilka sposobów.
Listy nienumerowane tworzy się wstawiając "-" przed każdym elementem listy. Listy numerowane tworzy się wstawiając "-#" przed każdym elementem.
Np.:
/**
* A list of events:
* - mouse events
* -# mouse move event
* -# mouse click event\n
* More info about the click event.
* -# mouse double click event
* - keyboard events
* -# key down event
* -# key up event
*/
W dokumentacji zobaczymy następujący tekst:
- mouse events
- mouse move event
- mouse click event
More info about the click event.
- mouse double click event
- keyboard events
- key down event
- key up event
Można też używać
niektórych znaczników html (ich pełna lista jest w podręczniku Doxygena).
Lista z wykorzystaniem tagów wyglądałaby następująco:
/**
* A list of events:
* <ul>
* <li> mouse events
* <ol>
* <li>mouse move event
* <li>mouse click event\n
* More info about the click event.
* </ol>
* <li> keyboard events
* <ol>
* <li>key down event
* <li>key up event
* </ol>
* </ul>
*/
Pomijanie komentarzy
Sprawa jest bardzo prosta. Jeśli tylko nie rozpoczniemy komentarza od
to zostanie on pominięty przez automat Doxygena.
Np. poniższe komentarze języka C
nie zostaną dołączone do dokumentacji:
/*
* Ten komentarz nie zostanie uwzględniony przez Doxygena
*/
// Ten też nie
Co jeszcze potrafi Doxygen?
- Jeśli w projekcie są obiekty (klasy, metody, zmienne, itp...), które nie zostały skomentowane, możemy mimo wszystko włączyć je do dokumentacji projektu ustawiając zmienną "EXTRACT_ALL" na "YES".
- Jeżeli włączymy opcję "SOURCE_BROWSER" to z komentarzy znikną te, sformatowane jako dokumentacja kodu dla Doxygena. Pozostałe komentarze się nie zmienią.
- Program ma własny preprocesor kodu C, dzięki czemu komendy preprocesora C (np.
#define) zostaną prawidłowo odczytane.
Opcja ta (ENABLE PREPROCESSING) jest domyślnie włączona w pliku konfiguracyjnym (w wersji 1.5.1).
- Doxygen tworzy automatycznie wykresy dziedziczenia w kodzie wykorzystującym programowanie zorientowane obiektowo. Jeśli potrzebujemy bardziej rozbudowanych wykresów (np. wykresy zależności, współpracy, odwołań), to trzeba skorzystać z narzędzia "dot" z pakietu "graphviz", a w konfiguracji należy włączyć opcję "HAVE_DOT".
Czego zrobić się nie da?
Jak widać możliwości Doxygena są ogromne. A więc może zapytajmy: z czym sobie nie radzi, z czym ma problemy?
- Doxygen nie obsługuje kilku popularnych języków, np. Perl, SQL, Bash shell scripts, Visual Basic, Ruby,
- Przydałaby się więcej opcji związanych z wyglądem generowanej dokumentacji, np. większe wsparcie dla kaskadowych arkuszy styli,
- Doxygen mógłby modyfikować przy kolejnym generowaniu dokumentacji tylko te pliki, które się zmieniły,
- Dokumentacja HTML nie jest w pełni zgodna z ze standardem XHTML 1.0 Strict,
- Można by rozbudować statystyki dokumentowanego kodu. Mogłyby pojawić się informacje o liczbie zmiennych, metod, klas, średnia liczba linii przypadająca na jeden plik, liczbie globalnych / publicznych zmiennych.
Wbrew pozorom, takie statystyki mogłyby być ważne. Np. dla architektów oprogramowania w większych firmach.
Trzeba jednak zaznaczyć, że wszystkie te słabe punkty (oraz inne, których nie wymieniłem) znane są autorowi projektu i planuje się poprawę funkcjonalności programu Doxygen w kolejnych wersjach.
Porównanie systemów tworzących dokumentację projektu
Pod adresem
http://en.wikipedia.org/wiki/Comparison_of_documentation_generators znajduje się dobre porównanie wielu popularnych programów do automatycznego generowania dokumentacji.
Przykład kodu skomentowanego dla systemu Doxygen
/**
* @mainpage
* @par About MGallery:
* Soon more info.
* @author Mateusz Gurgul
* @date 2007.02.09
* @version 1.0
* @par Contact:
* If you have any questions, suggestions, etc., please visit my homepage: @a http://www.MateuszGurgul.com
* @par TODO:
* See @ref todo
*/
/**
* @page ClassDiagram Class Diagram
*
* @image html ClassDiagram.png "Class Diagram"
*/
/**
* @page todo List of TODO
*
* -# Przemyśleć podejście bazodanowe w kontekście przechowywania plików.
* -# Wielojęzyczność.
* -# Warstwa abstrakcji dostępu do bazy (AdoDB).
*
* @n Wkrótce lista poszerzy się. @n
*/
/// Link file with ConfigurationManager class
require '../ConfigurationManager.php';
/// Create new ConfigurationManager object (singleton)
$config = ConfigurationManager::getInstance();
/// Include all necessary classes
$config->includeAll();
/// Create new front controller object
$MGallery = new FrontController();
/// Run the application
$MGallery->run();
/**
* Front controller.
* Główna klasa, kontrolująca wszelkie działania aplikacji.
* @note FrontController musi być uruchamiany jako pierwszy.
*/
class FrontController implements IController {
private $config;
/**
* Kontruktor front controllera.
* @param void
* @return void
*/
public function __construct() {
$this->config = ConfigurationManager::getInstance();
}
/**
* Główna metoda front controllera.
* Metoda jest uruchamiana przy starcie aplikacji. To tutaj zapada decyzja
* którą akcję wykonywać, to tutaj inicjalizuje się zmienne niezbędne w
* obiektach akcji.
* @n Klasa obsługuje wyjątki, które zgłaszane mogą być w dowolnym
* miejscu programu.
* Jeśli klasa z obługą wyświetlania błędów nie jest dostępna,
* wyświetlany jest niesformatowany tekst informujacy o wystąpieniu błędów.
* @param void
* @return void
*/
public function run() {
...
}
}