[linux-l] API-Doc vs. Literate Programming (war: Warum gibt es keine einheitliche Dokumentation?)

Steffen Dettmer steffen at dett.de
Mo Jan 1 21:03:32 CET 2007


* Volker Grabsch wrote on Sun, Dec 31, 2006 at 07:35 +0100:
> On Thu, Dec 28, 2006 at 05:36:43AM +0100, Steffen Dettmer wrote:
> > Gibt es ein Dokusystem für Sourcecode-Dokumentation, was Java, Python,
> > C, C++ und Perl Doku nach plaintext/man, LaTeX/PDF kohärent erzeugen
> > kann?
> 
> Das ist nicht unbedingt nötig. Ein Tool für jede Sprache wäre ja auch
> schon super, solange man sich auf das Ausgabeformat einigt (z.B. eine
> Manpage pro Funktion oder sowas, wie bei den System-Calls).

Der Vorteil wäre, dass man einfach verlinken kann. In Deinem Beispiel
mit den bis zu drei "Levels" könnte man sich wünschen, dass z.B. die
highlevel Funtkionen auf die benutzten Lowlevel-Funktionen referenzieren
usw. Die Doku ist einheitlich bedienbar und lesbar. Das ist gar nicht so
unwichtig, finde ich. Man ist einfach schneller mit gewohnten
Systemen... 

> Daher ist es IMHO nicht so wichtig, ob ein API-Doc-Tool nun alle
> Sprachen unterstützt, oder gar vereinheitlicht. Es ist nicht wichtig,
> ob die Python- und die Java-API-Doc gleich aussehen, sondern ob die
> Python-API-Doc für einen normalen Python-Programmierer gut lesbar ist,
> und die Java-API-Doc für einen normalen Java-Programmierer wie gewohnt
> aussieht.

Doch, wenn ich ein Projekt in drei Sprachen implementieren, ziehe ich
vor, wenn die Doku in einem Format kommt. Warum soll eine Erklärung für
eine Python-Funktion unbedingt anders aussehen, als eine für Java?

> [Doxygen]
> >   Ich habe ähnliche APIs in C++ und Java. 
> 
> Das heißt, schreibe *eine* Doku, die beide APIs erklärt, und ggf. auf
> Unterschiede hinweist. [...] Aus diesem gemeinsamen Dokument (das auch
> aus mehreren Dateien bestehen kann) generierst du dann C++ und
> Java-Dateien, die du dann in den Compiler jagst.

Das klingt unrealistisch aufwändig...

> >   API Docs haben auch schon zwei Hauptzielgruppen: Benutzer (mit
> >   Unterzielgruppen) und Libentwickler.  Letzere möchten auch Infos, wie
> >   die Funktion heute gerade zufällig arbeitet, was die Benutzer gerade
> >   nicht wissen sollen.
> 
> Unterschiedliche Detail-Level. 

Nein, eben nicht!

Ziel der Benutzer-Dokumentation ist, interna nicht zu dokumentieren,
weil der Benutzer das nicht wissen soll, damit er sich nicht drauf
verlassen kann.

Für Libentwickler müssen natürlich genau die interna dokumentiert werden
- dafür interessieren ihn Beispielprogramme und update-Hinweise
vielleicht nicht.

> Das ist ja nun wirklich das geringste Problem. Im
> Literate-Programming-Ansatz aber automatisch mit enthalten.  Dann
> generierst du eben nicht eine Doku und das C++/Java-Zeugs, sondern 2
> Dokus und das C++/Java-Zeugs. :-)

Ja klar, wenn man was generieren kann, geht sowas sicherlich. Vielleicht
hat man noch unterschiedliche Sprachen etc.

> Was auch nett ist, und mit vorhandenen Mitteln funktioniert: Pack
> diese Details einfach in die privaten Funktionen/Methoden. Zumindest
> EpyDoc kann sowohl "public" als auch "private" Varianten der Doku
> erstellen.
> 
> Wobei in "private" halt auch alle internen und versteckten Attribute,
> Funktionen, etc. auftauchen. In JavaDoc/Doxygen geht das doch auch,
> oder?

Doxygen kann das definitiv, find ich aber doof.

Dokumentationsstruktur hat IMHO nichts mit Klassenstruktur zu tun. APIs
"per Funktion" bzw. "per Methode" zu dokumentieren, ist oft doof. Das
sieht man an der offiziellen JavaDoc gut. Das Interessante steht meist
in packages oder classes. Dass "String message" die Nachricht ist etc
ist meist nicht so überraschend...

Natürlich kann so eine Aufteilung manchmal helfen, klar. Allerdings hat
man ja oft ganze Klassen, die Implementierungsdetails darstellen (und in
der Benutzerdoku maximal als "Do not use" auftauchen). Methoden müssen
vielleicht auch public sein, weil bestimmte andere libs diese Aufrufen
können müssen. Die Sichtbarkeitsregeln sind ja sehr primitiv (public,
protected, private z.B.). Da sollte man nicht auch noch die Doku dran
festmachen. Oft gibts viele public Methoden, von denen der Benutzer im
"Normalfall" nur eine Handvoll aufrufen "sollte". Aber manchmal braucht
er vielleicht auch mehrere, besonders bei libs auf einer höheren Ebene
oder so.

> >   "Perfekte Beispiele" zu finden, geht auch nicht - irgendeinem fehlt
> >   "seins" ja immer.
> 
> Ich sprach nur von *guten* Beispielen. (Aber vom perfekten Programmierer ;-))

Na, ich wollte darauf hinaus, dass man es nicht (nur/vollständig) über
Beispiele sinnvoll dokumentieren kann.

> Außerdem haben Beispiele didaktischen Wert, d.h. sie sollten Teil der
> Erklärung sein oder zumindest interessante Randfälle beschreiben.

Didaktisch, genau. Ich find, der Normalfall sollte sein, dass Beispiele
einen (den) Standardanwendungsfall zeigen, oder einen "Gutfallablauf"
oder sowas in der Art. So sieht man oft gleich, wie ungefähr das
funktioniert und hat einen prima Startpunkt.

> Auf keinen Fall sollen sie "Howtos" sein, außer in dem Sinne, dass
> sie gängige Aufrufe darstellen, also eine "Howto" für die Library
> an sich darstellen. :-)

Ja, z.b., und zeigen, wie man bestimmte Mechanismen benutzen kann. Wenn
es da sowas gibt und ein verständliches Beispiel, benutzen die Leute
dass dann (eventuell ;)) auch. Sonst neigen Leute meiner Meinung nach
gern dazu, Funktionalität selbst "zu Fuss" zu implementieren. Am Ende
gibts dann private Funktionen, die man gar nicht bräuchte, weil die lib
das schon anbietet. Natürlich sind die verschiedenen privaten Funktionen
inkompatibel, und so... :)

> >   Didaktisch gut heisst oft, die API aus praktischer Benutzungssicht
> >   zu beschreiben. Das ist aber ungünstig als Referenz... 
> 
> Ich sehe da keinen allzu großen Widerspruch. Natürlich ist die API-Doc
> hauptsächlich eine Referenz. Aber ganze Klassen oder Module haben doch
> ebenfalls Kommentare, und die kann man super nutzen für einführende
> Worte und kleine Gesamt-Beispiele.

Ja, genau. Aber hier gibt es Grenzen. Doxygen kann immerhin "pages",
schon mal sehr schön, nur leider sind die "Anhang". Aber in hypertext
Dokumenten (PDF, HTML) ist das Recht egal. Doxygen kann eine "mainpage",
ganz wichtig. Die kann man gliedern. Allerdings kommt dann hier ein
"Grossteil" der "wichtigen" Doku rein. Gleichzeitig schränkt einen
Doxygen ein: Tabellen sind immer einfach und schlicht, Grafikeinbindung
ist mindestens "umständlich" usw. Da hat man dann oft neben der
Doxygen-Doku weitere Dokumente. Eine Spezifikation (im Prinzip oft die
API ohne Details, wenn die API gut aber knapp ist), vielleicht noch was
mit Hintergrundinfos zum Lösungsansatz etc. 

Hier hat man schon wieder das Problem, dass man eben nicht ein Format
hat, sondern im Beispiel hier ja schon zwei (wenn man Beispielprogramme
nicht noch extra zählt).
 
> Größere Beispiele sollten natürlich als eigenständige Programme in
> eigenen Dateien mitgeliefert werden.

Ja, das geht mit Doxygen sehr gut, finde ich.

> > pro-Funktion-Dokumentation ist meiner Meinung nach als API-Dokumentation
> > absolut unzureichend.
> > 
> >   Es muss auch erklärt werden, warum man welche Funktion nu wann aufruft
> >   oder nicht usw. Das an die Funktionen zu schreiben wird redundant und
> >   ach, geht überhaupt nicht.
> 
> Ja, natürlich. Ich habe doch oben nur übertrieben. Selbstverständlich
> kriegt nicht nur jede Funktion ihre Erklärung und Beispiele, sondern
> auch jede Klasse, jedes Modul, jedes Paket. Aber das ist doch normal,
> und in jedem API-Doc-System vorgesehen, oder?

Na ja, bei diversen Java-Sachen hat es zumindestens lange gedauert, bis
sich das rumgesprochen hat... ;)

Wie auch immer, gute Doku zu schreiben ist natürlich eine
Herrausforderung. Nicht einfacher, als Code zu schreiben, wird aber
häufiger unterschätzt.

Aber die Frage war ja, ob "ein Tool" reicht. Selbst mit Doxygen (wo
Klasse, Modul und Paket/Namespace unabhängig dokumentiert werden
können), trifft man schnell auf Grenzen.

Meiner Erfahrung nach macht sich folgendes gut:

- Powerpoint (od ähnl) Präsentation mit Überblick, Marketing-Charakter,
  referenziert, wie man weitere Infos bekommt
  --> für die "gucken wir uns das an oder nicht" Phase
  --> für die "ach, worum gehts denn nu bei der lib eigentlich" Fragen
  Hier könnte auch ein Video oder sowas eine gute Idee sein.

- Eine Webseite, wo man abschätzen kann, ob und wie das hinter dem
  Produkt (lib) stehende Projekt lebt (oder nicht ;)). Mit mindestens
  rudimentärer Online-Info (z.B. was macht das Teil so im Groben)
  Downloadlinks für Doku, releases etc.

- Release Notes. Muss extra, weil die andere Doku meist Teil des
  Releases, also der Freigabe, ist. Releases Notes müssen nach der
  Freigabe des "Produkts" (lib oder was man hat) gepflegt werden (known
  bugs / issues)

- Allgemeine (untypisierte) Infos. Kann ein Dokument oder auch eine
  Webseite sein - oder ein README oder INSTALL. Technisch natürlich
  evtl. auch keine doxygen "page" (bei kleineren Sachen)
  Enthält Informationen über den (od. einen möglichen) Context, die Art
  der Entwicklung (Prozesse und Qualitätsmanagement, Regeln, Tools,
  etc). Das sind Sachen aus der Spezifikation. Hat man eine, reicht das
  natürlich, aber wenn man nur z.B. Doxygen nimmt, muss das ja auch
  irgendwo stehen (kann bei kleinen Sachen natürlich entfallen). Enthält
  Informationen zu Installation etc., Systemanforderungen. Offene
  Punkte. Wo kriegt man neueste Version her, wer ist Ansprechpartner, wo
  kann ich support kaufen etc. Enthält ggf. auch, was ein "Handbuch"
  enthalten würde.

- nu endlich kommt API docu :-)

- Historie der Software nicht (kaum) in den Sourcen selbst sondern im
  SCM (CVS, SVN).

Hat man libs, wo zu erwarten ist, dass sie von vielen Entwicklern
genutzt wird, lohnt sich aufwändige Doku um so mehr. Vielleicht sogar
Tutorials für Leute bestimmter Erfahrungen. Für eine GUIs könnte man das
für Kenner von xlib und QT in zwei "Quickstarts" erklären oder sowas. Da
will man sicherlich auch ein anderes Dokument.

Stellt sich wieder die Frage, ob das noch alles von einem Tool gemacht
werden kann.

> > Ein Tool wie JavaDoc oder Doxygen löst IMHO ein anderes Problem. Nicht
> > das der knappen Doku, sondern es löst das Problem der Wartbarkeit (ein
> > bisschen).
> 
> Aber diese Probleme hängen doch zusammen. Sie nehmen redundante Arbeit
> ab, und sorgen dadurch dafür, dass sich der Autor auf die
> nicht-trivialen Teile der Doku konzentrieren kann.
> 
> Außerdem erzeugen API-Doc-Tools auch ohne Beschreibungs-Kommentare
> zumindest eine formale Dokumentation, was schonmal ein guter Anfang
> ist, wenn vorher gar nichts da war.

Mag sein, aber das hab ich persönlich noch nie so empfunden. Ich weiss
aber, dass es Leute gibt, die mit "source code Navigatoren" arbeiten
etc. Ich persönlich halte da überhaupt nichts von. Tot den
Klassenbrowsern :) Das führt nur dazu, dass man vermeidlich günstige
Klassen ableitet, aber vermutlich damit die Lib anders benutzt, als es
gedacht ist. Da hab ich schon nette Sachen gesehen... 

Aber mag Fälle geben, wo da funktioniert. Insbesondere bei nicht so ...
erm... durchdachten? APIs. Also APIs, die mehr oder weniger die
intuitive Idee des Entwicklers sind. Da haben anderen dann oft intuitiv
die gleiche Idee. Allerdings ist diese oft bei genauer Betrachtung
falsch oder suboptimal.

> Schau dir mal eine kleine Vorzeige-Lib von mir an. Sie ist nicht
> perfekt, demonstriert aber recht gut das Zusammenspiel von (Test-)
> Beispielen, Doku und Plaintext:
> 
>     http://www.profv.de/vopu/
> 
> Schau dir sowohl den Quellcode als auch die erzeugte API-Doc an.
> Beachte auch den "private"-Bereich der generierten Doku.

Quellcode? Phyton? Sorry, zu faul gerade :)

http://www.profv.de/vopu/doc/private/vopu-module.html

macht einen wirklich tollen Eindruck für eine API Doku. Aber mehr ist es
leider auch nicht. Für eine komplette Vorzeige Doku würden mir noch
einige Sachen fehlen. Beispielsweise warum es OrderedByCreation gibt.
Wenn ich Entwickler bin, frage ich mich vielleicht, wie ich
camelcase um einen Parameter erweitere, der angibt, ob der erste
Buchstabe klein sein soll (oder weiss ich was). Über interna steht da
nichts (was ja auch gut so ist, ist ja eine Benutzer Doku).

Allgemeines steht da auch nicht. Wann wurde das entwickelt, welche
Version ist das, warum wurde die verwendete Abstraktion gewählt (die
mich z.B. überrascht hat, sehe keinen Zusammenhang zwischen den
Funktionalitäten. Die Sourcen guck ich mir nicht weiter an, hab eh
keinen Plan von phyton. Obwohl ich mich z.B. Frage, ob es den Aufriss
eines StrinStreams Wert ist, der scheinbar nur "self.content += str"
implementiert (falls ich die Sourcen richtig verstehe, was mangels
Python Kenntnissen recht unwahrscheinlich ist).

Bei camelcase verstehe ich (der den Ausdruck nicht kannte) die Funktion
sogar nur über die Beispiele - find ich suboptimal (sollte beides
gehen). Natürlich auch nur wenn man erwartet, dass jemand die Funktion
benutzt, ohne die Hintergründe schon zu kennen. Wenn man eine solche
Ausbildung vorraussetzt, braucht und sollte man das natürlich nicht
dokumentieren.

Release-Informationen fehlen völlig (welche Version, von wann,
freigegeben oder experimentell, getestet oder nicht, welche
Qualitätsanforderungen, welche Sprache überhaupt usw. Welche Funktionen
würde ich hier hinzufügen, welche anderen hingegen wären hier eher
falsch einsortiert etc. (Das kommt wohl daher, dass es einfach eine
unsystematische Sammlung von Funktionen ist, die nach ihrem Autor
gruppiert sind, was normalerweise natürlich keinen Sinn macht). Also,
ich mein, ist klar dass Du sowas hier nicht brauchst, das Beispiel
"hinkt" also.

Macht hier "für Dich" natürlich keinen Sinn, Du weisst das ja auswendig
bzw. spielt es keine Rolle (das gilt vermutlich für die gesamte Doku
;)), aber wenn andere die Lib nutzen wollen würden, fehlten halt noch
viele Infos.

Es gibt keine Suche, dass ist bei einem "Webserver-Dienst" eigentlich
Schade. Der Index enthält neben vielen komischen (privaten?) Funktionen
(?) und viele __init__s nicht einen "menschlich-aussehenden Begriff".
Ich würde sowas wie "URL Verarbeitung" oder "Iterating objects" oder so
erwarten. Man weiss ja oft weder, ob eine bestimmte "gesuchte"
Funktion existiert, geschweige denn wie sie heisst...

> Das sollte die Dinge besser verständlich machen, die ich hier mühsam
> versuchte zu beschreiben. Literate Programming ist das nicht, aber
> es demonstriert die Verbindung zwischen Einführung, Beispielcode
> und Referenz.

Referenz sehe ich. "Beispielschnipsel" auch. Wirklich gut, prima. Für
"richtige" Beispiele, die auch zeigen, warum man die wichtigen
Funktionen wie benutzt etc., ist die Lib vermutlich zu trivial. Aber bei
kleinen einfachen Funktionen ist es (entgegen DRY) oft doch eine gute
Idee, die Funktion jeweils zu implementieren. Spart viele Abhängigkeiten
von Libs für Dreizeiler und damit spart das auch schnell viel
Wartungsaufwand (z.B. die alte lib kompiliert auf der neuen Zielplatform
nicht, kein Maintainer mehr, ...).

oki,

Steffen

-- 
Dieses Schreiben wurde maschinell erstellt,
es trägt daher weder Unterschrift noch Siegel.





Mehr Informationen über die Mailingliste linux-l