Literate Programming quergedacht
Dr. Meik Teßmer
2024-05-29
Version: 0.6.1
Ausgangspunkt: Knuth [, 1984] + How to read
Warum eignet sich WEB wie auch noweb und neweb nicht?
klass. LP: kleine Einheiten (Module aka Sections), bestehend aus documentation, definitions, code → inspiriert von Pierre-Arnoul de Marneffe: Holon programming
The “Holon” concept has been introduced in biological and behavior sciences by Koestler. This concept proceeds from the work of Simon. It is used for instance to analyze complex living organisms or complex social systems. This neologism is from Greek “holos”, i.e., whole, and the suffix “-on” meaning “part”. A holon is a “part of a whole”. The reader is forewarned to not mix up the holon concept with the “module” one.
“Hierarchy”: Each holon is composed by other holons which are “refinements” of the former holon. These holons are submitted to some rigid rules; they perform the “detail” operations which, put together, compose the function of the former holon.
“Tendency to Integration”: The holon integrates with other holons in the hierarchy according to a flexible strategy. This integration must be understood as a will to close cooperation with the other holons for the emergence of a “tougher” and more efficient component.
[Marneffe, 1973, pp. 8-9]
Grundidee ist im Wesentlichen top-down; trägt dieser Ansatz noch immer, insbesondere bei OO? Gerade exploratives Entwickeln funktioniert eher anders.
Eludicative Programming ist da näher… Sie erschlagen die Trennung mit einem Side-by-Side-Betrachter. Das ist allerdings ein anderer Ansatz: Hier geht es um ein Programmierparadigma, nicht um die Darstellung von Code. Das Paradigma führt zu einer anderen Herangehensweise bei der Entwicklung: Erst denken, Gedanken in Textform niederlegen (1. Stufe der Korrektur), Text in Code-Form überführen (2. Stufe der Korrektur).
Einzig die Frage der Organisation des Codes bleibt offen:
Daran schließt sich direkt die Frage nach dem Kommunikationsmedium an:
Wie erfolgreich ein Medium beim Leser ist, hängt zu einen Gutteil von dessen Vorerfahrung ab. Dieser Umstand bietet einen möglichen Ansatzpunkt:
Der Anfänger ist (zumindest heute noch) schriftlich geprägt durch lineare Inhalte. Erst schleppend werden diese ergänzt, aber wir sind noch weit entfernt von Alan Kays Vision des Dynabooks[link] bzw. Neal Stephensons Fibel aus Diamond Age[link]. Für diese Lesergruppe bietet sich eine klassische Abfolge an:
Dies entspricht dem top-down-Ansatz, der vom klassischen LP genutzt wird.
Der erfahrene Entwickler nutzt Programme/Dokumentation für:
Er benötigt einen möglichst schnellen und zielgerichteten Zugriff und hat kein Interesse an Einführungen.
Welche Möglichkeiten gibt es, beiden Anforderungen gerecht zu werden?
Eine Idee: Code und Dokumentation werden Seite an Seite
entwickelt, aber nicht in derselben Datei. Damit unterscheidet
sich dieser Ansatz von Knuths Literate Programming, nutzt aber den
Gedanken der Inklusion von Code in die Dokumentation, in dem Code-Teile
in die Dokumentation eingeblendet werden. Als Ergebnis erhält man eine
LP-konforme Datei, die wiederum mit neweave
ins
Markdown-Format und mit pandoc in beliebige Zielformate konvertiert
werden kann. Der Verarbeitungsablauf für docweaver
sieht
somit wie abgebildet.
Wie werden nun Code-Abschnitte bezeichnet? Im klassischen LP-Ansatz besteht diese Notwendigkeit nicht, aber wenn bestimmte Code-Abschnitte eingebunden werden sollen, müssen sie a) benannt und b) in ihrem Umfang definiert werden. Eine Möglichkeit ist, die Kommentarfähigkeit der jeweiligen Programmiersprache zu nutzen und dort die benötigten Angaben zu hinterlegen. Ein Beispiel für die Definition eines Bereichs:
#<<Filter definieren>>=
def ein_filter():
pass
#@
Normalerweise ist es kein Problem, an einer beliebigen Stelle eine Kommentarzeile einzufügen. Die Einbindung erfolgt unter Angabe der Quelle-Datei, gefolgt von einem Doppelpunkt und dem Bereichsnamen sowie der fortlaufenden Nummer (gezählt wird ab 0). Damit ist es möglich, wie im klassischen LP auch zusammenhängende Code-Abschnitte umzusetzen:
Folgende Funktion definiert einen Filter:
Weiter geht ...
Die folgende Zeile fügt den zweiteiligen Code Chunk
Hauptfunktion
aus der Datei weaver.py
ein:
0 ⟨Hauptfunktion⟩≡
1 ▷
if __name__ == "__main__":
main()
print()
Eine Schwierigkeit ist festzustellen, welche Kommentarzeichen
relevant sind. Die Sprachangabe am Ende der Einbindungszeile hilft
dabei, die richtigen Zeichen für die jeweilige Sprache zu wählen.
docweaver
ergänzt in der .nw-Datei für jeden Code-Chunk die
notwendigen Sprach-Hinweise, so dass anschließend ein passendes Syntax
Highlighting möglich ist.
int main(void)
{
("Hello World!\n");
printf
return 0;
}
int main()
{
std::cout << "Hallo Welt!\n";
}
public class HalloWelt {
public static void main(String[] args) {
System.out.println("Hallo Welt!");
}
}
5 ⟨Hauptfunktion⟩≡
◁ 3
func main() {
.Println("Hallo Welt!")
fmt}
TODO:
Kommandozeilenparamter:
#!/bin/sh
if [ -z "${NOWEB_CODE}" ]; then
NOWEB_CODE=`pwd`/code
fi
[ -d "${NOWEB_CODE}" ] || mkdir -p "${NOWEB_CODE}"
FILES=""
for f in ${FILES}; do
newtangle -R "$f" < "${NOWEB_SOURCE}" > "${NOWEB_CODE}/$f"
done