Document Weaver

Literate Programming quergedacht

Dr. Meik Teßmer

2024-05-29

Version: 0.6.1

1 Schwierigkeiten des klassischen Literate Programming

Ausgangspunkt: Knuth [, 1984] + How to read

WEB-Pipeline.

Warum eignet sich WEB wie auch noweb und neweb nicht?

  • Problem beim Einsatz für Config Management
  • Support der Editoren für gemischte Dateien eher schlecht, Tools ebenfalls (Linter, Unittests)
  • Bugfixing/Make Errors/Debugger Lines: nicht im gemischten Dateien → Suche ist schwierig
  • Organisation der kleinen Module zu größeren Einheiten

2 Bisher geleistete Vorarbeit

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:

  • Wie unterteile ich das Gesamtwerk geschickt in kleinere und daraus bestehende größere Teile?
  • In welcher Reihenfolge führt man den Leser heran? Gibt es möglicherweise mehr als einen sinnvollen Weg und damit mehrere Einstiegspunkte? Beispiel: Anfänger vs. erfahrener Entwickler
  • Wie sollen OO-Systeme beschrieben werden, deren Funktionalität sich erst aus der Kooperation von Klassen/Objekten ergibt und den Fokus auf die Kommunikation legt?

Daran schließt sich direkt die Frage nach dem Kommunikationsmedium an:

  • Ist “linearer” Text, angereichert mit Verweisen (ggf. auch klickbar), noch sinnvoll? → Problemlösen: Schritt-für-Schritt erzwingt eine lineare Abfolge!
  • Sind grafisch unterstützte Ansätze wie Mind Maps hilfreich, die eher einen Netzwerk-Charakter unterstützen?

Wie erfolgreich ein Medium beim Leser ist, hängt zu einen Gutteil von dessen Vorerfahrung ab. Dieser Umstand bietet einen möglichen Ansatzpunkt:

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

    1. Allgemeine Einführung
    2. Vision
    3. Hauptkomponenten
    4. Aufteilung dieser in Teilkomponenten und deren weitere Verfeinerung in Folgeabschnitten

    Dies entspricht dem top-down-Ansatz, der vom klassischen LP genutzt wird.

  2. Der erfahrene Entwickler nutzt Programme/Dokumentation für:

    • Bug Fixing
    • Fortbildung

    Er benötigt einen möglichst schnellen und zielgerichteten Zugriff und hat kein Interesse an Einführungen.

3 Alternativer Ansatz

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.

docweaver-Pipeline.

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()

1 ⟨Hauptfunktion⟩≡ ◁ 0 2 ▷

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.

4 Tests

4.1 C

2 ⟨Hauptfunktion⟩≡ ◁ 1 3 ▷

int main(void)
{
    printf("Hello World!\n");

    return 0;
}

4.2 C++

3 ⟨Hauptfunktion⟩≡ ◁ 2 5 ▷

int main()
{
    std::cout << "Hallo Welt!\n";
}

4.3 Java

4 ⟨Hauptmethode⟩≡

public class HalloWelt {
    public static void main(String[] args) {
        System.out.println("Hallo Welt!");
    }
}

4.4 Go

5 ⟨Hauptfunktion⟩≡ ◁ 3

func main() {
    fmt.Println("Hallo Welt!")
}

5 Ausblick

TODO:

  • Kommandozeilenparamter:

    • v: verbose
    • V: Version und eingebaute Sprachen
    • c: Kommentar-RegExp

6 ⟨build-script⟩≡

#!/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

5.1 Code Chunks

Hauptfunktion
0 1 2 3 5
Hauptmethode
4
build-script
6
Knuth, Donald E.: Literate Programming. In: Comput. J. Bd. 27. Oxford, UK, Oxford University Press (1984), Nr. 2, S. 97–111
Marneffe, Pierre-Arnoul de: Holon Programming: A Survey : Univ. de Liège, Service d’Informatique, 1973