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

Volker Grabsch vog at notjusthosting.com
So Dez 31 07:35:27 CET 2006


On Thu, Dec 28, 2006 at 05:36:43AM +0100, Steffen Dettmer wrote:
> > Ich kann zu Java, Python, ... Programmen eine API-Doc generieren
> > (JavaDoc, EpyDoc), aber das meistens nur nach HTML. Mit etwas Glück
> > auch noch nach LaTeX bzw. PDF. Ein kohärentes Stück Doku innerhalb
> > *einer* Software wird damit schon schwer gemacht. Ganz zu schweigen
> > von Einheitlichkeit über mehrere Software-Pakete hinweg.
> 
> 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).

Sind sehr viele Sprachen in einem einzigen Projekt zusamen, sind wohl
eher "noweb" oder andere Literate-Programming-Tools zu empfehlen. Denn
in solch einem Projekt nützt es auch nichts, 'zig verschiedene API-Docs
in ein Dokument zusammen zu fassen. Nein, das Dokument muss über dem
Code stehen, das Zusammenspiel erklären, u.s.w.

Zumal eher davon abzuraten ist, zu viele unterschiedliche Sprachen zu
nehmen. Selbst die allergrößten Projekte kommen mit 3 Sprachen locker
aus. Eine sehr-lowlevel-Sprache für systemspezifische Dinge (C, C++),
dann eine für die Performance- oder Speicherbedarfs-kritischen Stellen
(C++, Pascal, Ocaml, ...) und eine für die sehr-highlevel-Dinge, also
den größten Teil (Ocaml, Python, Scheme, Haskell, ...). Normalerweise
braucht man nur 1 oder 2 dieser Layer.

Hinzu kommen dann noch 1 oder 2 Sprachen für das Maintaining (Make,
Shell-Scripts, ...), aber selbst das ist meistens unnötig, weil das
einem auch die highlevel-Sprachen abnehmen können. Pythons "distutils"
sind ein hervorragendes Beispiel dafür.

Und dann noch 1 oder 2 Sprachen für die Doku (Manpage, LaTeX, reST, ...).
Eine Sprache sollte da aber ausreichend sein, die zweite ist dann für
die Diplomarbeit oder das gedruckte Buch.

Will sagen, wenn du einen Mix aus Python, Perl und PHP hast, ist die
API-Generierung dein geringstes Problem. 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.

[Doxygen]
>   Ich habe ähnliche APIs
>   in C++ und Java. Einerseits möchte ich die Doku nicht hin- und
>   herkopieren und redundant pflegen, andererseits ist sie auch nicht
>   genau gleich usw. Doxygen kennt \copydoc, aber auch das hat Nachteile
>   (der Javaentwickler muss C++ Sourcen ändern oder umgekehrt etc).

Wieso schreibst du nicht eine gemeinsame Doku für beides? Okay, ist
aufwändiger, und automatische Tools kannst du vergessen, aber der
Ansatz des Literate-Programming scheint hier besser geeignet zu sein
als der traditionelle. Ein alter Klassiker ist dabei "noweb".

Das heißt, schreibe *eine* Doku, die beide APIs erklärt, und ggf. auf
Unterschiede hinweist. Ebenfalls dort hinein könnten die konkreten
C++ und Java-Codes, die müssen im gerenderten Dokument natürlich nicht
unbedingt auftauchen.

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 heißt, der Code enthält nicht die Doc, sondern die
Doci enthält den Code. Das ist der Ansatz des Literate-Programming.
Praktische Tipps oder Aufwand-Nutzen-Abschätzung kann ich dir aber leider
nicht geben, weil ich das bisher noch nicht praktiziert habe.

Vielleicht kennst sich ja hier jemand anderes mit Literate-Programming
aus und kann was empfehlen bzw. davon abraten?

>   Das Problem liegt wohl weniger im Tool als wohl eher im Problem selbst
>   (d.h., ich glaube, das Problem ist vielleicht gar nicht elegant
>   lösbar).

Wenn du willst, kannst das hier ja mal in diesem gerade von mir
gesponsorten Literate-Programming-Thread diskutieren. :-)

> > Was macht man bei API-Docs? Nunja, der perfekte Programmierer und
> > Dokumentator erklärt sein Programm in einem großen Text mit
> > entsprechenden Codeteilen. ("Literate Programming")  Diese Doku ist
> > didaktisch gut aufbereitet, sodass jeder ohne Probleme in den Code
> > hinein findet. Pro Funktionseinheit/Modul ein Unterkapitel, u.s.w.
> 
> Na ja, geht gar nicht perfekt. 
> 
>   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. 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. :-)

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?

>   "Perfekte Beispiele" zu finden, geht auch nicht - irgendeinem fehlt
>   "seins" ja immer.

Ich sprach nur von *guten* Beispielen. (Aber vom perfekten Programmierer ;-))

Die Beispiele haben Wert als Testcode. Unter Python fischt "doctest"
diese Dinger heraus und testet sie, zusätzlich kann und sollte man
natürlich auch noch Unit-Tests machen.

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

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. :-)

>   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.

Größere Beispiele sollten natürlich als eigenständige Programme in
eigenen Dateien mitgeliefert werden.

> > Der normale Programmierer, wie ich, ist schon froh, wenn jede Funktion
> > einen nicht-trivialen Docstring besitzt. 
> 
> 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?

In Python kann fast alles einen Docstring haben: Module, Pakete (Datei
__init__.py), Klassen, Funktionen/Methoden. In Java und anderen Sprachen
sicherlich auch durch entsprechende Index-Dateien im
Paket/Modul-Verzeichnis.

> > Also kommt ein API-Doc-Generator her. 
> 
> 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.

> > Es wäre zu schön, wenn die Tools nicht blind nach HTML konvertieren
> > würden, sondern erstmal nach reST.  
> 
> Wieso dass denn, die JavaDoc/Doxygen-Kommentare kann man ja auch im
> plain text lesen (was man als Entwickler ja oft auch macht).
> Also wozu nu hier noch reST?

Das Java-Markup ist nicht so berauschend. Python-Docstrings haben
kein "künstliches" Markup, sondern eben reST, das überwiegend genauso
aussieht, wie man es im Plaintext eh machen würde. *Sowas* nenne
ich lesbaren Plaintext.

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.

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.


Viele Grüße,

    Volker

-- 
Volker Grabsch
---<<(())>>---
Administrator
NotJustHosting GbR



Mehr Informationen über die Mailingliste linux-l