Development/Tutorials/API Documentation (de): Difference between revisions
DrSlowDecay (talk | contribs) (More translation) |
No edit summary |
||
(9 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
__TOC__ | __TOC__ | ||
{{Box|Definition| | {{Box|Definition| | ||
Line 17: | Line 17: | ||
Dieses Dokument versucht den apidox Prozess nicht zu ausführlich werden zu lassen, indem es einige dirkekte Tips gibt, wie man apidox schreibt. Es gibt dann doch die [[Policies/Library Documentation Policy|library apidox policies (englisch)]], die sehr viel strenger sind. Es schadet nicht, auch dort mal einen Blick reinzuwerfen. | Dieses Dokument versucht den apidox Prozess nicht zu ausführlich werden zu lassen, indem es einige dirkekte Tips gibt, wie man apidox schreibt. Es gibt dann doch die [[Policies/Library Documentation Policy|library apidox policies (englisch)]], die sehr viel strenger sind. Es schadet nicht, auch dort mal einen Blick reinzuwerfen. | ||
{{note (de)|Die eigentliche Beispieldokumentation auf dieser Seite wird nicht übersetzt, da API Dokumentation in der Regel auf englisch verfasst werden, um eine internationale Mitarbeit zu ermöglichen}} | |||
== APIDOX Basics == | == APIDOX Basics == | ||
APIDOX | APIDOX werden durch das [http://www.doxygen.org Doxygen] Dokumentationswerkzeug verarbeitet. Dieses Werkzeug liest den Quellcode der Applikation (oder Bibliothek) und erzeugt schön formatierte Dokumentation daraus. Es gibt ein gutes [http://www.stack.nl/~dimitri/doxygen/manual.html Referenz Handbuch (auf englisch)] -- doch für die Grundlagen muß dieses nicht vollständig gelesen werden. | ||
{{Tip| | {{Tip|Doxygen muß für die Arbeit an apidox der Applikation nicht installiert sein. Alle paar Stunden erzeugt das [http://www.englishbreakfastnetwork.org/ EnglishBreakfastNetwork] apidox für alle bekannten KDE Module. Logfiles und die eigentlichen Apidox werden ebenfalls bereitgestellt, um Fehlermeldungen zu entdecken und diese zu beheben. Das ist zwar nicht die schellste Methode apidox zu schreiben und zu korrigieren, doch es erledigt diese Aufgabe. Ein paar Stunden Arbeit am Tag, um an der apidox zu arbeiten, reichen aus.}} | ||
{{Tip| | {{Tip|Hast du Doxygen installiert und möchtest die apidox erzeugen, benutze das kdedoxygen.sh Skript wie es in [[Development/Tools/apidox|apidox (englisch)]] beschrieben ist.}} | ||
Die Grundlagen von apidox sind einfach und machen Spaß: Man schreibt einfach Kommentare in den Code, die erklären wofür dieser ist. Diese Kommetare sind fast das gleiche wie das, was man sowieso in die header des Codes schreiben muß, so ist das ganze also nicht so schwer. | |||
APIDOX | APIDOX werden in speziellen Kommentaren geschrieben. Diese Kommentare starten mit /** (Schrägstrich, Stern, Stern) -- und das ist es, was sie besonders macht. Der Rest des Kommentars ist einfacher Text, der den Teil des Programms beschreibt. Dieser Text wird vom Doxygen Prozessor interpretiert, damit dadurch passende Beschreibungen der Parameter und Rückgabewerte erfolgen kann. Doch die Dokumentation ist recht unkompliziert: Man schreibt einfach, was eine Methode tut innerhalb von /** und */, so wie folgendes Beispiel: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** This method increases the sexyness of Kontact and should as | /** This method increases the sexyness of Kontact and should as | ||
* such be called whenever possible (i.e. instead of having idle | * such be called whenever possible (i.e. instead of having idle | ||
Line 40: | Line 42: | ||
*/ | */ | ||
void incSexyness(KInstance *instance); | void incSexyness(KInstance *instance); | ||
</ | </syntaxhighlight> | ||
Für eine vernünftige apidox muß jedes "Ding" des Programms dokumentiert werden. "Dinge" sind hierbei Verzeichnisse, Dateien, Namensräume, Klassen, Methoden, Aufzählungen und Variablen. Man kann eventuell Dateien und Verzeichnisse auslassen und sich nur auf die letzteren Punkte konzentrieren. Komplette apidox sehen ungefähr so aus: | |||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** Namespace for KDE network-related classes */ | /** Namespace for KDE network-related classes */ | ||
namespace KDENetwork { | namespace KDENetwork { | ||
Line 56: | Line 58: | ||
}; | }; | ||
} | } | ||
</ | </syntaxhighlight> | ||
Wie man sieht, ist jede Schachtelungsebene der eben erwähnten "Dinge" mit einem Kommentar versehen -- Der Namensraum, die Klasse und die Methode. Private "Dinge" benötigen keine apidox, protected "Dinge" jedoch schon. | |||
Es ist wichtig, jede einzelne Schachtelungsebene zu dokumentieren, denn läßt man einen Ebene aus, ignoriert Doxygen die inneren ebenso und man findet diese nicht mehr wieder. Angenommen man würde im obigen Beispiel die Klassendokumentation weglassen, dann würde die Dokumentation für die Methode Socket() ebenfalls verschwinden. Das ist eine der typischen Fallen beim Schreiben von apidox. | |||
Und wenn man nur eine Erklärung für jeden Teil seines Programmes schreibt, hat man schon einen großen Teil des Weges zu einer kompletten apidox hinter sich gelassen. Diese Erklärungen zu schreiben macht das Programm einfacher für andere Entwickler zu verstehen und zeigt einem oft schon sub-optimale Designs oder Namenswahlen. Auf diese Art gewinnen beide Seiten. | |||
Man findet in der Liste von unterstützen Tags auch Beispiele für ausgefallenere apidox -- Erklärung von Parametern oder wie man die apidox mit Beispielen und Personendaten versieht. Es lohnt sich auch nachzusehen, wie man apidox aktiviert, doch es ist auch möglich die Arbeit aufzuteilen: Du schreibst die apidox selber und fragst den Originalautor (mailto:groot@kde.org), diese für dein Modul zu aktivieren. Er verspricht (zunmindest in der englischsprachigen Originalversion) das dann zu tun. | |||
== APIDOX in neuem Code schreiben == | == APIDOX in neuem Code schreiben == | ||
Wenn mann neuen Code schreibt und dabei apidox verwenden möchte, sollte man am besten KDevelop benutzen. Vernünftig konfiguriert kann dieses automatisch ein Grundgerüst für apidox einfügen, man muß dann nur noch die eigentlichen Beschreibungen einfügen. Und man muß sich nicht mehr mit apidox kommandos rumärgern. | |||
Wenn man sich nicht in dieser günstigen Lage befindet, sollte die folgende Checkliste einen durch die schlimmsten Untiefen beim Schreiben von apidox führen: | |||
'''1. | '''1. Schreibe die apidox direkt mit dem Code zusammen''' | ||
Wenn man es mit etwas Disziplin schafft, direkt beim Schreiben einer Funktion foo(), wo man sich sowieso Gedanken über den gewünschten Effekt machen muss, auch gleich an die apidox zu denken, spart man sich diese Zeit sicherlich später, wenn man nicht mehr mühsam herausfinden muss, was die Funktion foo() eigentlich machen soll. | |||
Das heißt nicht, dass man es auf diese Art und Weise machen muss, doch es bietet sich an. Durch die apidox werden auch Entscheidungen bezüglich des Designs dokumentiert. Auch wird dokumentiert, was ein bestimmter Codeabschnitt eigentlich macht, unabhängig davon, was er aktuell tut. Das macht es möglich, unabhängig zu überprüfen, ob der Code das tut, wozu er geschrieben ist. Das liegt daran, dass es bereits in der apidox dokumentiert wurde. | |||
'''2. | '''2. Dokumentierte deine Header vollständig''' | ||
Die Header sind das, was den Benutzern als erstes vom Code ins Auge springt (in diesem Zusammenhang sind Entwickler Benutzer, die Code wiederverwenden). Aus diesem Grund sollen sie vollständig sein, d.h. jede noch so kleine Struktur sollte im Header dokumentiert werden. Im Einzelnen: | |||
* | *Jede Datei sollte einen Kommentar haben, der den Nutzen dieser Datei beschreibt. Das wird von den KDE Richtlinien sowieso vorgeschrieben -- am Anfang der Datei sollte einfach vermerkt werden, wofür die Datei gut ist und in groben Zügen, was sie definiert. Das sollte in einem /** @file */ Kommentar erfolgen. | ||
* | * Jeder Namensraum (namespace) sollte einen Kommentar haben. Ein bestimmter Namensraum benötigt nur einmal im Quellcodebaum einen Kommentar, doch es kann nicht schaden ihn bei jedem Auftreten erneut zu beschreiben -- nur kurz sollte es sein. Diese Kommentare sind einfache apidox Kommentare zwischen /** und */; keine besonderen Befehle wie bei Dateien das @file Befehl.<br> | ||
< | Man sollte nur sicherstellen, dass der Kommentar direkt vor dem Namensraum steht und nichts dazwischen steht. Das folgende Beispiel zeigt, wie es aussehen soll: | ||
<syntaxhighlight lang="cpp-qt">/** The Ungulate namespace collects classes and methods | |||
pertaining to hooved animals. */ | pertaining to hooved animals. */ | ||
namespace Ungulate { | namespace Ungulate { | ||
</ | </syntaxhighlight> | ||
: | :Im nächsten Beispiel hat jemand etwas Extracode zwischen den apidox Kommentar und den Namensraum, der dokumentiert werden soll, gebracht. Das könnte Doxygen zu Fehlern bringen (in diesem Fall ist es einfach den Fehler zu finden) oder die Dokumentation des Namensraum kann sich plötzlich auf etwas ganz anderes beziehen (dann ist der Fehler schwer zu finden). | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** The Ungulate namespace collects classes and methods | /** The Ungulate namespace collects classes and methods | ||
pertaining to hooved animals. */ | pertaining to hooved animals. */ | ||
class Mammal; | class Mammal; | ||
namespace Ungulate { | namespace Ungulate { | ||
</ | </syntaxhighlight> | ||
:There is not much you can do about this except to be watching when you insert code -- don't separate apidox from the thing they are documenting. | :There is not much you can do about this except to be watching when you insert code -- don't separate apidox from the thing they are documenting. | ||
*Every class should have a comment. Classes are the important building blocks of your application or library, so this is one place where writing lots helps. Write down why the class exists. Write down what it is supposed to do. Give an example of how to use it. Explain how not to use it, or what prerequisites it has (for instance, lots of classes need a KInstance object, but don't document that explicitly).<br />The same caveats apply as with namespace apidox: make sure the class follows its apidox immediately. | *Every class should have a comment. Classes are the important building blocks of your application or library, so this is one place where writing lots helps. Write down why the class exists. Write down what it is supposed to do. Give an example of how to use it. Explain how not to use it, or what prerequisites it has (for instance, lots of classes need a KInstance object, but don't document that explicitly).<br />The same caveats apply as with namespace apidox: make sure the class follows its apidox immediately. | ||
Line 101: | Line 104: | ||
*Every enumeration type should have a comment explaining what the enumeration is for, even if it's just /** Various constants */. | *Every enumeration type should have a comment explaining what the enumeration is for, even if it's just /** Various constants */. | ||
*Every enumeration value should have a comment too, to explain what it represents. Don't rely on the name of the enumeration value being sufficiently expressive.<br />For the purposes of readability, I suggest that you document enumeration values after the value, as opposed to the documentation format for namespaces, classes and methods where you write the documentation in front of the thing you are documenting. The format of the documentation is slightly different. Instead of writing /** Documentation */ in front, you write /**< Documentation afterards */, where the < denotes that the documentation applies to the thing just past.<br />It looks like this: | *Every enumeration value should have a comment too, to explain what it represents. Don't rely on the name of the enumeration value being sufficiently expressive.<br />For the purposes of readability, I suggest that you document enumeration values after the value, as opposed to the documentation format for namespaces, classes and methods where you write the documentation in front of the thing you are documenting. The format of the documentation is slightly different. Instead of writing /** Documentation */ in front, you write /**< Documentation afterards */, where the < denotes that the documentation applies to the thing just past.<br />It looks like this: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
enum State { | enum State { | ||
none, /**< No bracket seen */ | none, /**< No bracket seen */ | ||
Line 108: | Line 111: | ||
dquote /**< Found double quotes */ | dquote /**< Found double quotes */ | ||
}; | }; | ||
</ | </syntaxhighlight> | ||
'''3. Watch this space!''' | '''3. Watch this space!''' | ||
Line 139: | Line 142: | ||
'''Documentation for a file:''' The newline after @file is significant! The text after @author is listed in a special Authors section of the apidox; you can list multiple authors. | '''Documentation for a file:''' The newline after @file is significant! The text after @author is listed in a special Authors section of the apidox; you can list multiple authors. | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** @file | /** @file | ||
* This file is part of AnApplication and defines | * This file is part of AnApplication and defines | ||
Line 146: | Line 149: | ||
* @author Mostly by me | * @author Mostly by me | ||
*/ | */ | ||
</ | </syntaxhighlight> | ||
'''Documentation for a namespace:''' | '''Documentation for a namespace:''' | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** | /** | ||
* This namespace collects functions related to | * This namespace collects functions related to | ||
* counting and enumeration of mammals and their limbs. | * counting and enumeration of mammals and their limbs. | ||
*/ | */ | ||
</ | </syntaxhighlight> | ||
'''Documentation for a class:''' Some Doxygen special commands are used here to provide additional information. @author (as with files) identifies authors of the code; these are collected in a special ''Authors:'' section of the apidox. You can list more than one author. The @since tag tells users since when the class has existed. It is usual to put a KDE release number here. | '''Documentation for a class:''' Some Doxygen special commands are used here to provide additional information. @author (as with files) identifies authors of the code; these are collected in a special ''Authors:'' section of the apidox. You can list more than one author. The @since tag tells users since when the class has existed. It is usual to put a KDE release number here. | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** | /** | ||
* This class represents a Moose in the woodland | * This class represents a Moose in the woodland | ||
Line 171: | Line 174: | ||
* @since 3.5 | * @since 3.5 | ||
*/ | */ | ||
</ | </syntaxhighlight> | ||
'''Method documentation:''' We can use @author and @since just like we do for classes. In addition, there are the parameters of the method that can be described. @p is used to refer to them in running text, and @param is used to construct a list of parameter descriptions that is specially formatted. Finally, @return entries describe the values that may be returned by the method. | '''Method documentation:''' We can use @author and @since just like we do for classes. In addition, there are the parameters of the method that can be described. @p is used to refer to them in running text, and @param is used to construct a list of parameter descriptions that is specially formatted. Finally, @return entries describe the values that may be returned by the method. | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** | /** | ||
* This method names a particular Moose and as a side effect | * This method names a particular Moose and as a side effect | ||
Line 193: | Line 196: | ||
*/ | */ | ||
bool name(const QString &name, bool santa = false); | bool name(const QString &name, bool santa = false); | ||
</ | </syntaxhighlight> | ||
Enum documentation is described in the section on writing new apidox. The same kind of documentation as for classes applies, with the addition of the documentation for each enumerated value which belongs inline. | Enum documentation is described in the section on writing new apidox. The same kind of documentation as for classes applies, with the addition of the documentation for each enumerated value which belongs inline. | ||
Line 199: | Line 202: | ||
== Beliebte Fehler == | == Beliebte Fehler == | ||
Dieser Abschnitt listet einige beliebte Fehler auf, die einem beim Schreiben der Apidox unterlaufen können. Typischerweise sind das leicht zu übersehende Fehler, die seltsame Fehlermeldungen produzieren, aber auch ein paar stilistische Fehler die vermieden werden sollten, werden angesprochen. | |||
'''Fehlende APIDOX''': Man ''weiß'', dass man die dox für die Klasse "Moose" geschrieben hat, doch nach der Generierung ist sie nicht sichtbar. Man ''weiß'' auch, dass eine auf Dateiebene sichtbare Funktion int foo() dokumentiert wurde, doch die ist auch nicht da. Was geht hier vor? | |||
Der häufigste Fehler, der zu "fehlender" apidox führt ist, zu vergessen, die umgebenden Strukturen zu dokumentieren. Die "Struktur" im Quellcode kommt von den Dateien, den Namensräumen, Klassen und Methoden. Um also eine Klasse zu dokumentieren muss man den Namensraum dokumentieren, in dem sie sich befinden (sofern es einen gibt) und die Datei in dem sie sich befindet. Um eine Methode zu dokumentieren, muss man die Klasse dokumentieren, in dem sie sich befindet (und so wiederum den Namensraum und die Datei). So die einfachste Daumenregel ist es, einfach ''alles'' zu dokumentieren. | |||
{{note (de)|Diese Regel ist nicht ganz richtig: Klassen benötigen nicht, dass die Datei dokumentiert wird, in der sie sich befinden, aus diesem Grund kann man den /** @file */ Kommentar auslassen für Dateien, die nur Klassen und Namensräume beinhalten. | |||
Beachte das Klassen in einem Namensraum erfordern, dass der Namensraum dokumentiert wird, doch Klassen im :: Namensraum benötigen keine Extradokumentation. | |||
Etwas unklar ist das bei anonymen Namensräumen. | |||
{{note (de)| | |||
Für Funktionen in der Dateiebene, also Funktionen, die in einer Datei definiert werden und nicht in einem Namensraum oder einer Klasse ''muß'' die Datei, in der sie definiert ist, dokumentiert werden. Das gilt meistens für Dateien die eine Sammlung von nicht-Methoden Funktionen zur Verfügung stellen.}} | |||
'''Broken parameter documentation:''' Documenting parameters to methods can be done two ways: you can document <em>none</em> of them, or you can document | '''Broken parameter documentation:''' Documenting parameters to methods can be done two ways: you can document <em>none</em> of them, or you can document | ||
Line 241: | Line 225: | ||
and case-sensitivity! -- and then the description. The description can | and case-sensitivity! -- and then the description. The description can | ||
span multiple lines. | span multiple lines. | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** Calculate the root-mean-square distance from the | /** Calculate the root-mean-square distance from the | ||
* origin to the given integral coordinate. | * origin to the given integral coordinate. | ||
Line 249: | Line 233: | ||
* @param x x-coordinate | * @param x x-coordinate | ||
*/ | */ | ||
</ | </syntaxhighlight> | ||
When you document all the parameters like this, Doxygen will complain if | When you document all the parameters like this, Doxygen will complain if | ||
Line 267: | Line 251: | ||
of a parameter (or anything else, really, but it only makes sense in front | of a parameter (or anything else, really, but it only makes sense in front | ||
of a name of a parameter). Like this: | of a name of a parameter). Like this: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** Calculate the root-mean-square distance from the origin to | /** Calculate the root-mean-square distance from the origin to | ||
* the given integral coordinate which is given as a pair @p x, | * the given integral coordinate which is given as a pair @p x, | ||
Line 274: | Line 258: | ||
*/ | */ | ||
double distance(int x, int y, bool nonFree=false); | double distance(int x, int y, bool nonFree=false); | ||
</ | </syntaxhighlight> | ||
'''Misuse of tags in running text:''' This boils down to the warning | '''Misuse of tags in running text:''' This boils down to the warning | ||
Line 298: | Line 282: | ||
element that may be replaced in a method call or string or something, so | element that may be replaced in a method call or string or something, so | ||
it crops up all the time. You know, you write some thing like this: | it crops up all the time. You know, you write some thing like this: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
/** This method connects to a database. The connection string is | /** This method connects to a database. The connection string is | ||
* composed of a username, password, host and database name as | * composed of a username, password, host and database name as | ||
Line 306: | Line 290: | ||
* @return true if the connection succeeded. | * @return true if the connection succeeded. | ||
*/ | */ | ||
</ | </syntaxhighlight> | ||
This bit of dox is terribly broken, because the whole sample connection | This bit of dox is terribly broken, because the whole sample connection | ||
Line 320: | Line 304: | ||
== KDE spezifische Tags == | == KDE spezifische Tags == | ||
'''@bc''': | '''@bc''': Diese Markierung zeigte Binärkompatibilität an, ähnlich wie es ''@since'' tut. Das Argument hinter ''@bc'' zeigt den Bereich der Binärkompatibilität (zum Beispiel KDE4) an. Klassen, die nicht mit ''@bc'' markiert sind, können in einigen Modulen als inkompatibel markiert werden, damit sie vermieden werden. | ||
Beispiel: | |||
< | <syntaxhighlight lang="cpp"> | ||
/** | /** | ||
* This class emulates a Moose. | * This class emulates a Moose. | ||
Line 329: | Line 313: | ||
* with next-generation mooses. | * with next-generation mooses. | ||
*/ | */ | ||
</ | </syntaxhighlight> | ||
'''@libs''': | '''@libs''': Diese Markierung zeigt an, welche Bibliotheken mit einer bestimmten Klasse gelinkt werden sollen. Auch wenn es normalerweise der Name des Verzeichnisses ist, in dem sich die Klasse befinden, ist dies nicht immer der Fall. | ||
Beispiel: | |||
< | <syntaxhighlight lang="cpp"> | ||
/** | /** | ||
* This class emulates a Moose. | * This class emulates a Moose. | ||
Line 340: | Line 324: | ||
* @a -lkdeui or use \$(LIB_KDEUI) in the KDE build framework. | * @a -lkdeui or use \$(LIB_KDEUI) in the KDE build framework. | ||
*/ | */ | ||
</ | </syntaxhighlight> | ||
== Code Beispiele in APIDOX == | == Code Beispiele in APIDOX == | ||
Es kann nützlich sein, Beispielcode zur APIDOX einer Klasse hinzuzufügen. Sehr nützlich ist es auf jeden Fall für Leser, die sich fragen, wie man eine Klasse genau zu benutzen hat. Die meisten Klassen in {{path|kdelibs/kdecore}} haben Beispielcode. | |||
Ein Weg, um Beispielcode zu schreiben ist es, @code und @endcode um den Block des Beispielcodes in den Doxygenkommentaren selber zu legen, wie im folgenden Beispiel: | |||
<syntaxhighlight lang="cpp-qt"> | |||
< | |||
/** | /** | ||
* This class represents a Moose. | * This class represents a Moose. | ||
Line 361: | Line 341: | ||
* @endcode | * @endcode | ||
*/ | */ | ||
</ | </syntaxhighlight> | ||
Auf diese Art wird es in den meisten Beispielen in {{path|kdelibs}} gemacht. Das funktioniert auch ganz gut, man kann sich bei den Beispielen aufs wesentliche beschränken. | |||
Ein wichtiges Problem dieser Herangehensweise um Beispielcode zu schreiben ist es, dass der Code niemals geprüft wird, ob er wirklich funktioniert. Die meisten Codebeispiele sind so gepackt, dass es schwer ist, diese in einen funktionsfähigen Code umzuschreiben, der wirklich kompiliert und läuft. | |||
Um dieses Problem zu lösen, kann man ''richtigen Code'' schreiben, der wirklich kompiliert (als Teil dr Test-Suite für den Code, den man sowieso hat) und exakt beschreibt, wie eine Klasse in einem richtigen Programm benutzt werden soll. Man muß jedoch nicht den gesamten Code in die APIDOX übernehmen, sondern braucht nur die interessanten Teile zu markieren. Um das zu bewerkstelligen, wird eine Datei in das <tt>tests</tt> Unterverzeichnis eingefügt. Dann kann man das Doxygen @include-Tag benutzen, um den Code dieser Datei in die API Dokumentation zu übernehmen. | |||
in | |||
<tt>tests | |||
{{warning (de)|Benutze nicht @example! Es macht etwas total anderes als was du erwarten könntest (zum Beispiel fügt es keinen Beispiel-Code ein).}} | {{warning (de)|Benutze nicht @example! Es macht etwas total anderes als was du erwarten könntest (zum Beispiel fügt es keinen Beispiel-Code ein).}} |
Latest revision as of 16:40, 15 July 2012
API (Application Programming Interface) Dokumentation ist die Dokumentation eines Programmes und seiner Schnittstellen. Durch Dokumentation wird einem Entwickler, der mit oder an dem Programm arbeitet, erklärt, wie Dinge funktionieren und wie und welche Methoden aufzurufen sind.
API Dokumentation wird machmal auch API Referenz Handbuch (API reference manual) genannt. Es muß nicht nur ein Referenz Handbuch sein, obwohl es umfangreiches zusätzliches Material, wie Anleitungen, Zeitleisten, etc., enthalten kann. Auf dieser Seite wird alles Material welches die API eines Codes dokumentiert und erklärt "apidox" genannt.
Gute apidox benötigt etwas Mühe zum schreiben -- doch sicherlich weniger Mühe als gute Benutzer Dokumentation, da du als Entwickler für andere Entwickler schreibst und eklärst wie Code funktioniert und was er tun soll. So dein Publikum ist bereit damit zu arbeiten. Der Vorteil von apidox zeigt sich, wenn jemand anderes (oder sogar du selbst einige Monate später) den Code (wieder)verwenden oder erweitern möchte. Gute apidox bedeutet, dass jemand neues kommen kann, den Code schnell versteht und nützliche Patches erstellen kann. Gerade für Bibliotheken kann apidox es ermöglichen, diese wie eine Black Box zu benutzen (und so sollte es auch sein), da die benötigte Dokumentation vorliegt und die Dokumentation sich nicht in den tiefen des (vielleicht gar nicht vorliegenden) C codes befindet.
Vorwort
Mit APIDOX wird es anderen Entwicklern ermöglicht, auf ein Programm zuzugreifen. Sie sind nicht unbedingt notwenig doch sie helfen neuen Leuten, die an dem Programm arebeiten möchten oder den Code ohne große Änderungen wiederverwenden möchten, sicherlich eine Menge.
Ein Blick auf die Qt Dokumentation (englisch) ermöglicht es, einen Eindruck von guter apidox Dokumentation zu bekommen. Dort sieht man eine Stilkonsistenz, die sich durch die gesamte Dokumentation zieht. Dadurch kann man eine Menge über Qt lernen, nur indem man die Dokumentation liest. Es ist nicht notwendig, die Anleitungsprogramme auszuführen oder den Quellcode zu lesen um herauszufinden, was ein Parameter in einer bestimmten Methode einer Bibliothek macht. Es wird alles bereits erläutert.
Apidox zu schreiben besteht aus zwei Teilen. Der erste Teil ist technischer Natur: Man muß den Code verstehen, der dokumentiert werden soll, oder zumindest wissen, was er tun soll und wie er benutzt werden muss. Der andere Teil ist reine Disziplin: apidox ist am nützlichsten, wenn es sorgfältig und ausführlich benutzt wird.
Dieses Dokument versucht den apidox Prozess nicht zu ausführlich werden zu lassen, indem es einige dirkekte Tips gibt, wie man apidox schreibt. Es gibt dann doch die library apidox policies (englisch), die sehr viel strenger sind. Es schadet nicht, auch dort mal einen Blick reinzuwerfen.
APIDOX Basics
APIDOX werden durch das Doxygen Dokumentationswerkzeug verarbeitet. Dieses Werkzeug liest den Quellcode der Applikation (oder Bibliothek) und erzeugt schön formatierte Dokumentation daraus. Es gibt ein gutes Referenz Handbuch (auf englisch) -- doch für die Grundlagen muß dieses nicht vollständig gelesen werden.
Die Grundlagen von apidox sind einfach und machen Spaß: Man schreibt einfach Kommentare in den Code, die erklären wofür dieser ist. Diese Kommetare sind fast das gleiche wie das, was man sowieso in die header des Codes schreiben muß, so ist das ganze also nicht so schwer.
APIDOX werden in speziellen Kommentaren geschrieben. Diese Kommentare starten mit /** (Schrägstrich, Stern, Stern) -- und das ist es, was sie besonders macht. Der Rest des Kommentars ist einfacher Text, der den Teil des Programms beschreibt. Dieser Text wird vom Doxygen Prozessor interpretiert, damit dadurch passende Beschreibungen der Parameter und Rückgabewerte erfolgen kann. Doch die Dokumentation ist recht unkompliziert: Man schreibt einfach, was eine Methode tut innerhalb von /** und */, so wie folgendes Beispiel:
/** This method increases the sexyness of Kontact and should as
* such be called whenever possible (i.e. instead of having idle
* time, you might think of calling this method and helping
* Kontact gain even more popularity). You might even insert it
* into your own event loop to ensure it is called as often as
* possible. If these calls decrease the number of new features,
* it's still no problem to call it.
*/
void incSexyness(KInstance *instance);
Für eine vernünftige apidox muß jedes "Ding" des Programms dokumentiert werden. "Dinge" sind hierbei Verzeichnisse, Dateien, Namensräume, Klassen, Methoden, Aufzählungen und Variablen. Man kann eventuell Dateien und Verzeichnisse auslassen und sich nur auf die letzteren Punkte konzentrieren. Komplette apidox sehen ungefähr so aus:
/** Namespace for KDE network-related classes */
namespace KDENetwork {
/** Wrapper for a TCP/IP socket */
class Socket {
public:
/** Constructor. Calls listen() on some random high port. */
Socket();
private:
int fd;
};
}
Wie man sieht, ist jede Schachtelungsebene der eben erwähnten "Dinge" mit einem Kommentar versehen -- Der Namensraum, die Klasse und die Methode. Private "Dinge" benötigen keine apidox, protected "Dinge" jedoch schon.
Es ist wichtig, jede einzelne Schachtelungsebene zu dokumentieren, denn läßt man einen Ebene aus, ignoriert Doxygen die inneren ebenso und man findet diese nicht mehr wieder. Angenommen man würde im obigen Beispiel die Klassendokumentation weglassen, dann würde die Dokumentation für die Methode Socket() ebenfalls verschwinden. Das ist eine der typischen Fallen beim Schreiben von apidox.
Und wenn man nur eine Erklärung für jeden Teil seines Programmes schreibt, hat man schon einen großen Teil des Weges zu einer kompletten apidox hinter sich gelassen. Diese Erklärungen zu schreiben macht das Programm einfacher für andere Entwickler zu verstehen und zeigt einem oft schon sub-optimale Designs oder Namenswahlen. Auf diese Art gewinnen beide Seiten.
Man findet in der Liste von unterstützen Tags auch Beispiele für ausgefallenere apidox -- Erklärung von Parametern oder wie man die apidox mit Beispielen und Personendaten versieht. Es lohnt sich auch nachzusehen, wie man apidox aktiviert, doch es ist auch möglich die Arbeit aufzuteilen: Du schreibst die apidox selber und fragst den Originalautor (mailto:[email protected]), diese für dein Modul zu aktivieren. Er verspricht (zunmindest in der englischsprachigen Originalversion) das dann zu tun.
APIDOX in neuem Code schreiben
Wenn mann neuen Code schreibt und dabei apidox verwenden möchte, sollte man am besten KDevelop benutzen. Vernünftig konfiguriert kann dieses automatisch ein Grundgerüst für apidox einfügen, man muß dann nur noch die eigentlichen Beschreibungen einfügen. Und man muß sich nicht mehr mit apidox kommandos rumärgern.
Wenn man sich nicht in dieser günstigen Lage befindet, sollte die folgende Checkliste einen durch die schlimmsten Untiefen beim Schreiben von apidox führen:
1. Schreibe die apidox direkt mit dem Code zusammen
Wenn man es mit etwas Disziplin schafft, direkt beim Schreiben einer Funktion foo(), wo man sich sowieso Gedanken über den gewünschten Effekt machen muss, auch gleich an die apidox zu denken, spart man sich diese Zeit sicherlich später, wenn man nicht mehr mühsam herausfinden muss, was die Funktion foo() eigentlich machen soll.
Das heißt nicht, dass man es auf diese Art und Weise machen muss, doch es bietet sich an. Durch die apidox werden auch Entscheidungen bezüglich des Designs dokumentiert. Auch wird dokumentiert, was ein bestimmter Codeabschnitt eigentlich macht, unabhängig davon, was er aktuell tut. Das macht es möglich, unabhängig zu überprüfen, ob der Code das tut, wozu er geschrieben ist. Das liegt daran, dass es bereits in der apidox dokumentiert wurde.
2. Dokumentierte deine Header vollständig
Die Header sind das, was den Benutzern als erstes vom Code ins Auge springt (in diesem Zusammenhang sind Entwickler Benutzer, die Code wiederverwenden). Aus diesem Grund sollen sie vollständig sein, d.h. jede noch so kleine Struktur sollte im Header dokumentiert werden. Im Einzelnen:
- Jede Datei sollte einen Kommentar haben, der den Nutzen dieser Datei beschreibt. Das wird von den KDE Richtlinien sowieso vorgeschrieben -- am Anfang der Datei sollte einfach vermerkt werden, wofür die Datei gut ist und in groben Zügen, was sie definiert. Das sollte in einem /** @file */ Kommentar erfolgen.
- Jeder Namensraum (namespace) sollte einen Kommentar haben. Ein bestimmter Namensraum benötigt nur einmal im Quellcodebaum einen Kommentar, doch es kann nicht schaden ihn bei jedem Auftreten erneut zu beschreiben -- nur kurz sollte es sein. Diese Kommentare sind einfache apidox Kommentare zwischen /** und */; keine besonderen Befehle wie bei Dateien das @file Befehl.
Man sollte nur sicherstellen, dass der Kommentar direkt vor dem Namensraum steht und nichts dazwischen steht. Das folgende Beispiel zeigt, wie es aussehen soll:
/** The Ungulate namespace collects classes and methods
pertaining to hooved animals. */
namespace Ungulate {
- Im nächsten Beispiel hat jemand etwas Extracode zwischen den apidox Kommentar und den Namensraum, der dokumentiert werden soll, gebracht. Das könnte Doxygen zu Fehlern bringen (in diesem Fall ist es einfach den Fehler zu finden) oder die Dokumentation des Namensraum kann sich plötzlich auf etwas ganz anderes beziehen (dann ist der Fehler schwer zu finden).
/** The Ungulate namespace collects classes and methods
pertaining to hooved animals. */
class Mammal;
namespace Ungulate {
- There is not much you can do about this except to be watching when you insert code -- don't separate apidox from the thing they are documenting.
- Every class should have a comment. Classes are the important building blocks of your application or library, so this is one place where writing lots helps. Write down why the class exists. Write down what it is supposed to do. Give an example of how to use it. Explain how not to use it, or what prerequisites it has (for instance, lots of classes need a KInstance object, but don't document that explicitly).
The same caveats apply as with namespace apidox: make sure the class follows its apidox immediately. - Every method should have a comment explaining what it does and what the parameters are for. Method parameters should be documented using @param. Don't rely on the name of the method or the parameters to be fully self-documenting. Besides, writing these things down properly will trigger Doxygen errors if you change them in an incompatible way later -- and that is going to save you lots of time in finding source and binary incompatibilities and explaining to users why their code suddenly doesn't do what they expect (assuming it compiles at all). So good method apidox is an additional insurance against making bad changes. Same caveats apply.
- Every enumeration type should have a comment explaining what the enumeration is for, even if it's just /** Various constants */.
- Every enumeration value should have a comment too, to explain what it represents. Don't rely on the name of the enumeration value being sufficiently expressive.
For the purposes of readability, I suggest that you document enumeration values after the value, as opposed to the documentation format for namespaces, classes and methods where you write the documentation in front of the thing you are documenting. The format of the documentation is slightly different. Instead of writing /** Documentation */ in front, you write /**< Documentation afterards */, where the < denotes that the documentation applies to the thing just past.
It looks like this:
enum State {
none, /**< No bracket seen */
bracket, /**< Found a ( for grouping */
squote, /**< Found a single quote */
dquote /**< Found double quotes */
};
3. Watch this space!
Watch the English Breakfast Network for the results of your apidox work. Check the log files for errors -- Doxygen can complain quite loudly.
4. Write a main page for your application.
This is usually done in a separate file Mainpage.dox in the top-level of a library or application. The file's content is just a single apidox comment that starts with /** @mainpage title ; the rest of the file is just a long comment about what the library or application is for.
APIDOX in altem Code korrigieren
Writing apidox in old code is a lot like writing the same apidox in new code, except that there is more cruft in the way. The number 1 tip to follow is: watch the logs on English Breakfast Network. Those will show you what errors there are in the apidox. However, Doxygen can't catch everything that is wrong with the documentation on its own, so you will have to do some reading yourself. The other tips for new apidox apply equally here: you want to document everything, in a consistent style. If methods show up on the generated apidox pages with no documentation, you know that you have more apidox to write. (Doxygen may provide an error message, but doesn't do that everywhere in the current setup because there would just be too many.)
In old apidox, you are more likely to suffer from the following symptoms:
- Missing parameter documentation (because parameters were renamed, or added, or removed, or something).
- Missing method documentation.
- Missing class documentation.
- Documentation that has wandered off on its own and is attached to the wrong thing now.
The first of these can be fixed by correcting the parameter documentation. See the examples section. The next two -- missing documentation that you can see is there in the source files but that does not show up in the generated HTML pages, is usually a matter of missing documentation on surrounding blocks. See the common pitfalls section, and make sure that the surrounding classes, namespaces and files all have documentation.
The last problem can best be fixed by moving the offending documentation back to where it belongs (really, it's not the documentation that is at fault, it's whatever has squeezed in -- the home-breaker -- between the documentation and the thing it was originally attached to). You could use some Doxygen special tags to avoid moving stuff around like that, but it does not help the understandability of the source much.
Beispiel APIDOX
So what does documentation look like in the headers? How do you write a method documenation that describes the parameters as well? This section contains boilerplate for most common situations. Doxygen does not require a strict style -- it will ignore whitespace and asterisks at the beginning of a line, so you can make the documentation ASCII-pretty.
Documentation for a file: The newline after @file is significant! The text after @author is listed in a special Authors section of the apidox; you can list multiple authors.
/** @file
* This file is part of AnApplication and defines
* classes Ungulate and Moose.
*
* @author Mostly by me
*/
Documentation for a namespace:
/**
* This namespace collects functions related to
* counting and enumeration of mammals and their limbs.
*/
Documentation for a class: Some Doxygen special commands are used here to provide additional information. @author (as with files) identifies authors of the code; these are collected in a special Authors: section of the apidox. You can list more than one author. The @since tag tells users since when the class has existed. It is usual to put a KDE release number here.
/**
* This class represents a Moose in the woodland
* simulator. A single Moose object can be created,
* but it is more useful to instantiate Moose::Factory
* by calling Moose::factory(), and then calling spawn()
* for each new Moose, since that maintains the ecological
* balance far better.
*
* @author Adriaan de Groot <[email protected]>
* @since 3.5
*/
Method documentation: We can use @author and @since just like we do for classes. In addition, there are the parameters of the method that can be described. @p is used to refer to them in running text, and @param is used to construct a list of parameter descriptions that is specially formatted. Finally, @return entries describe the values that may be returned by the method.
/**
* This method names a particular Moose and as a side effect
* sets whether or not the Moose is treated as a Reindeer.
* When @p santa is @c true, the name of the moose is set to
* the next of the available Reindeer (if possible).
*
* @param name name to assign to the Moose, which is only
* relevant if the moose is not a Reindeer.
* @param santa is this Moose assigned to Santa? if so, the
* name is irrelevant.
*
* @return @c true if naming the Moose succeeded
* @return @c false if naming the Moose failed. This only
* happens if the Moose is assigned to Santa duty
* but there are already eight named Reindeer.
*/
bool name(const QString &name, bool santa = false);
Enum documentation is described in the section on writing new apidox. The same kind of documentation as for classes applies, with the addition of the documentation for each enumerated value which belongs inline.
Beliebte Fehler
Dieser Abschnitt listet einige beliebte Fehler auf, die einem beim Schreiben der Apidox unterlaufen können. Typischerweise sind das leicht zu übersehende Fehler, die seltsame Fehlermeldungen produzieren, aber auch ein paar stilistische Fehler die vermieden werden sollten, werden angesprochen.
Fehlende APIDOX: Man weiß, dass man die dox für die Klasse "Moose" geschrieben hat, doch nach der Generierung ist sie nicht sichtbar. Man weiß auch, dass eine auf Dateiebene sichtbare Funktion int foo() dokumentiert wurde, doch die ist auch nicht da. Was geht hier vor?
Der häufigste Fehler, der zu "fehlender" apidox führt ist, zu vergessen, die umgebenden Strukturen zu dokumentieren. Die "Struktur" im Quellcode kommt von den Dateien, den Namensräumen, Klassen und Methoden. Um also eine Klasse zu dokumentieren muss man den Namensraum dokumentieren, in dem sie sich befinden (sofern es einen gibt) und die Datei in dem sie sich befindet. Um eine Methode zu dokumentieren, muss man die Klasse dokumentieren, in dem sie sich befindet (und so wiederum den Namensraum und die Datei). So die einfachste Daumenregel ist es, einfach alles zu dokumentieren.
Beachte das Klassen in einem Namensraum erfordern, dass der Namensraum dokumentiert wird, doch Klassen im :: Namensraum benötigen keine Extradokumentation. Etwas unklar ist das bei anonymen Namensräumen.
Für Funktionen in der Dateiebene, also Funktionen, die in einer Datei definiert werden und nicht in einem Namensraum oder einer Klasse muß die Datei, in der sie definiert ist, dokumentiert werden. Das gilt meistens für Dateien die eine Sammlung von nicht-Methoden Funktionen zur Verfügung stellen.
Broken parameter documentation: Documenting parameters to methods can be done two ways: you can document none of them, or you can document all of them for a given method. There is no middle ground (that doesn't generate gobs of errors that you should fix).
If you document all of your parameters (which is a good thing to do, and generates things in a nicely formatted fashion), then your method apidox consists first of a general description of the method and then a bunch of @param tags which describe each individual parameter. The @param tag is followed by the name of the parameter -- watch out for spelling and case-sensitivity! -- and then the description. The description can span multiple lines.
/** Calculate the root-mean-square distance from the
* origin to the given integral coordinate.
*
* @param y y-coordinate, which is on an axis perpendicular to the
* x-axis, yet still in the same plane.
* @param x x-coordinate
*/
When you document all the parameters like this, Doxygen will complain if you misspell parameter names, or forget some, or mention parameters that are not there. This will force you to update the documentation if you change the method signature. And that's a good thing.
Additional pitfalls are putting the type of the parameter in the list, like @param int x, which makes "int" the name of the parameter. Another pitfall is that @param should come after the general description. Once the @param list starts, nothing can stop it except for other list-style Doxygen tags like @since, @author or @return. So write @param after the story and before, say, @return.
If you document none of the parameters, you do not use the @param tag at all. You can talk about your parameters by writing @p before the name of a parameter (or anything else, really, but it only makes sense in front of a name of a parameter). Like this:
/** Calculate the root-mean-square distance from the origin to
* the given integral coordinate which is given as a pair @p x,
* @p y. If @p nonFree is true, use ESR instead of RMS in the
* computation.
*/
double distance(int x, int y, bool nonFree=false);
Misuse of tags in running text: This boils down to the warning above about where to put @param: not every Doxygen tag can go anywhere. Some start lists or basically end the general description part of a description, so you need to avoid using them in running text.
Chosing between Doxygen errors and compiler warnings: If you are going to document your parameters, you need to name them. If you are defining a stub method, this can lead to compiler warnings.
Accidental tags: It can be easy to accidentally use Doxygen tags in running text -- email addresses, backslash escapes, those are the easy ones. Watch the Doxygen logs and escape that at sign with a backslash when needed (i.e. write \@ to get an at sign). It's probably a good idea to avoid the backslash style of apidox entirely; at the same time, if you happen to write \moose, Doxygen will complain that that is an invalid tag.
Accidental HTML: If you use < and > in your apidox, these may confuse Doxygen -- especially if you write things like <service> which look like HTML tags. This is a common way of writing some kind of element that may be replaced in a method call or string or something, so it crops up all the time. You know, you write some thing like this:
/** This method connects to a database. The connection string is
* composed of a username, password, host and database name as
* follows:
* <username>:<password>@<host>//<database>
*
* @return true if the connection succeeded.
*/
This bit of dox is terribly broken, because the whole sample connection string will be interpreted as (bad) HTML and ignored. There are two solutions:
- Write \< instead of just < to escape the < and make Doxygen output it normally. Doxygen is smart enough to turn this into < in HTML output. This has only a minimal impact on readability of the dox in the header files themselves.
- Use the HTML formatting that Doxygen makes available, and write <i>foo</i> instead of <foo>. This produces nicer output with italics instead of plain text, so it is easier to spot what is the replaceable part of the text. The downside is that it has a larger visible impact on the apidox in the headers.
- Superfluous @ref
- It can be tempting -- certainly if you've written dox for other projects -- to use #method or @ref method to force a reference to another method somewhere. Relax, it's not needed and usually causes Doxygen warnings to boot. Just name the method normally, make apidox and watch the references appear naturally.
KDE spezifische Tags
@bc: Diese Markierung zeigte Binärkompatibilität an, ähnlich wie es @since tut. Das Argument hinter @bc zeigt den Bereich der Binärkompatibilität (zum Beispiel KDE4) an. Klassen, die nicht mit @bc markiert sind, können in einigen Modulen als inkompatibel markiert werden, damit sie vermieden werden.
Beispiel:
/**
* This class emulates a Moose.
* @bc KDE4.2 Compatibility is expected to break
* with next-generation mooses.
*/
@libs: Diese Markierung zeigt an, welche Bibliotheken mit einer bestimmten Klasse gelinkt werden sollen. Auch wenn es normalerweise der Name des Verzeichnisses ist, in dem sich die Klasse befinden, ist dies nicht immer der Fall.
Beispiel:
/**
* This class emulates a Moose.
* @libs
* @a -lkdeui or use \$(LIB_KDEUI) in the KDE build framework.
*/
Code Beispiele in APIDOX
Es kann nützlich sein, Beispielcode zur APIDOX einer Klasse hinzuzufügen. Sehr nützlich ist es auf jeden Fall für Leser, die sich fragen, wie man eine Klasse genau zu benutzen hat. Die meisten Klassen in kdelibs/kdecore haben Beispielcode.
Ein Weg, um Beispielcode zu schreiben ist es, @code und @endcode um den Block des Beispielcodes in den Doxygenkommentaren selber zu legen, wie im folgenden Beispiel:
/**
* This class represents a Moose.
* The correct way of generating Meese is to use the factory:
*
* @code
* Moose::Factory outlet = Moose::factory();
* Moose *m = outlet.spawn();
* @endcode
*/
Auf diese Art wird es in den meisten Beispielen in kdelibs gemacht. Das funktioniert auch ganz gut, man kann sich bei den Beispielen aufs wesentliche beschränken.
Ein wichtiges Problem dieser Herangehensweise um Beispielcode zu schreiben ist es, dass der Code niemals geprüft wird, ob er wirklich funktioniert. Die meisten Codebeispiele sind so gepackt, dass es schwer ist, diese in einen funktionsfähigen Code umzuschreiben, der wirklich kompiliert und läuft.
Um dieses Problem zu lösen, kann man richtigen Code schreiben, der wirklich kompiliert (als Teil dr Test-Suite für den Code, den man sowieso hat) und exakt beschreibt, wie eine Klasse in einem richtigen Programm benutzt werden soll. Man muß jedoch nicht den gesamten Code in die APIDOX übernehmen, sondern braucht nur die interessanten Teile zu markieren. Um das zu bewerkstelligen, wird eine Datei in das tests Unterverzeichnis eingefügt. Dann kann man das Doxygen @include-Tag benutzen, um den Code dieser Datei in die API Dokumentation zu übernehmen.
Links
englische Liste der unterstützen Doxygen Tags
- Hier ist eine Liste von allen verfügbaren Dokumentations-Tags von Doxygen von der offiziellen Seite. Beachte, das diese Seite ein Backslash vor einem Tag benutzt, während diese Seite immer das At-Zeichen benutzt. Beides ist erlaubt, doch in KDE sollte zu Gunsten der Konsistenz das At-Zeichen benutzt werden.