Literate Programming: Ideen für Menschen festhalten

[Posted by Benjamin Kober on 17 Dec 2016]

Vor kurzem bin ich auf den Artikel Literate Programming von Donald Knuth gestoßen. Da ich auch selber immer auf der Suche bin meine Projekte besser zu dokumentieren habe ich mich ein wenig mit seinem Ansatz beschäftigt.

Die Grundidee ist folgende: Programme sollten nicht in erster Linie für Maschinen geschrieben werden sondern damit andere Menschen sie gut verstehen können. Ein Programm sollte sich lesen lassen wie ein literarisches Werk und es sollte Freude machen sich damit zu beschäftigen. Um das zu erreichen wird der Programmcode wie eine Erzählung aufgebaut bei der Erklärungen und Quellcode miteinander verwoben werden. Aus dem so erstellten Text kann man zwei verschiedene Ausgaben erzeugen:

  • Eine saubere Dokumentation, die sich wie ein Buch liest
  • Ein compilierbarer Quelltext (oder bei interpretierten Sprachen ein ausführbares Skript)

Die Idee dahinter ist gut (wer will nicht eine Dokumentation, welche genauso interessant wie eine Erzählung ist) zeigt aber in der Praxis einige Probleme.

Man hat einen weiteren Erzeugungsschritt

Da der Quelltext in dieser Form nicht direkt kompilierbar ist braucht man immer ein weiteres Programm. Das macht es schwieriger mit anderen an einem Projekt zusammen zu arbeiten. Erzeugt man den funktionierenden Quelltext und macht diesen anderen zugänglich (damit sich der Kompilieraufwand verkleinert) hat man den eigentlichen Nutzen des ganzen Konzeptes wieder verpasst und eventuelle Änderungen von dritten müssen mit großem Aufwand in den ursprünglichen Quelltext eingefügt werden.

Auch beim Debuggen ergeben sich schnell Probleme da die Zeilenverweise auf den generierten Quelltext statt auf die ursprüngliche Quelle verweisen.

Möglicherweise kann man beiden Problemen mit besseren Tools abhelfen aber diese zu erstellen (und dauerhaft zu pflegen) ist mit großem Aufwand verbunden.

Es ist schwer fehlerhafte oder ineffektive Implementierungen aufzuzeigen

Vor kurzem habe ich einige Softwaredokumentationen gelesen die tatsächlich sehr interssant waren (eines war ein Dokument über die Implementierung von lua 5.0 bei dem anderen ging es um Graphendatenbanken). Keiner dieser Texte wurde gemeinsam mit dem Quelltext als “literate” Programm erstellt obwohl sie sich zum Teil intensiv mit Details der Implementierung beschäftigten. Was sehr dazu beitrug, dass diese Texte interessant waren und die Entscheidungen nachvollziehbar waren war, dass das propagierte Softwaredesign als ineffektiv oder fehlerhaft dargetstellten Ansätzen gegenübergestellt wurde. Das ist mit literate programing sehr schwer umsetzbar, da entweder das Programm nicht kompilieren würde oder die fehlerhaften Teile in keiner Weise validiert werden könnten.

Die Dokumentation ist statisch

Da die Dokumentation in einem nicht editierbaren Format vorliegt kann der Leser nicht unmittelbar Änderungen vornehmen. Entwickler am Projekt werden also mit hoher Wahrscheinlichkeit die Dokumentation nicht (oder nur ein einziges Mal ganz am Anfang) durchlesen.

Um das zu umgehen ist es sehr wichtig, das der beschreibende Text bereits im Quelltext gut lesbar ist und sich natürlich in den Programmcode einfügt.

Lösungsansätze

Das es Probleme gibt soll nicht heißen, die Idee hinter literate programing wäre schlecht. Gerade der Gedanke die Anordnung des Quelltextes danach zu wählen, wie man die Prinipien einem anderen erklären würde kann die Quellcodestruktur deutlich verbessern. Dadurch werden automatisch die Details einer Implementierung erst nach dem Konzept der Architektur erklärt was sofort zu einem besseren Verständnis sowohl der Details als auch der übergeordneten Konzepte beiträgt.

Den Quelltext als Erzählung aufbauen

In den meisten Sprachen lassen sich diese Prinzipien anwenden, indem man die Kommentare richtig nutzt und das Programm geschickt struckturiert, ohne ein Programm zu gebrauchen welches aus dem Ursprungstext erst richtigen Quellcode erzeugt. Bei Sprachen, welche nicht flexibel genug in Bezug auf die Struckturierung oder ihre Kommentare sind, sollte man ohnehin überdenken, ob man nicht lieber eine andere Sprache nutzen will.

Will man einige übergeordnete Konzepte oder zum Quelltext verschiedene Betrachtungsweisen (z.B. wenn man mehrere Erzählstränge paralell führt um einen bestimmten Aspeckt einer Architektur besonders heraus zu stellen) erklären kann man ein markdown-Dokument (oder welche Auszeichnungssprache man nutzen möchte) erstellen, in welchem Verweise auf den Quelltext eingefügt sind. Oft ist der Text nur dann verständlich, wenn man die Quelltexte sofort lesen kann und nicht erst ein weiteres Dokument öffnen muss. Daher sollte man für Dokumente dieser Art immer ein script oder ein tool haben, welches überprüft, ob die referenzierte Stelle mit dem Text im Dokument übereinstimmt und ansonsten eine Fehlermeldung ausgibt.

Einfache Markupsprachen in Kommentaren verwenden

Die Kommentare sollten in einem normalen Editor gut lesbar sein. Daher sollten keine Sprachen wie Tex oder html in den Kommentaren verwendet werden, sondern Markup-Sprachen wie asciidoc, markdown oder textile. Wenn der eigene Editor Bilder nicht unmittelbar anzeigt (was bei den meisten Texteditoren der Fall sein dürfte) sollten alle schematischen Darstellungen als Ascii-Art oder in einer sich intuitiv erschließenden Darstellungssprache erstellt werden (Verwendet man einen anderen Editor sollte man sich definitiv als Team darauf einigen und sich bewusst machen, wie stark man sich dadurch einschränkt).

Druckausgaben generieren (aber nicht Zwischenquellcode)

Man kann extra Programme nutzen um aus diesem Quelltext dann eine druckbare Dokumentation zu erstellen. Dabei sollte man darauf achten, dass an Stellen wo der Quelltext erklärt wird man unmittelbare Verweise auf den editierbaren Quellcode hat. Bei Opensource-Programmen kann man z.B. einen Link auf die passenden Zeilen in github hinterlegen (dort kann man online editieren). Oder man könnte mit einem extra Programm (z.B. als Browser Plugin) den Editor der Wahl des Benutzers an der passenden Zeile öffnen.

Tests als Dokumentation aufbauen

Viele Unit Test Systeme verfolgen die Idee von BDD. Dabei wird in weiten Teilen ohnehin normale, menschliche Sprache verwendet um das gewünschte Verhalten von Software zu dokumentieren. Man kann diese Unittest auch als Dokumentation schreiben und (mit den richtigen tools) auch eine Druckausgabe generieren.

Tags Literate Programming, Dokumentation, Software Entwicklung

Umgang mit Submodulen in git

[Posted by Benjamin Kober on 12 Feb 2012]

Was sind git Submodule?

Submodule bieten die Möglichkeit Unterprojekte in ein Repository einzubinden ohne dass ihre Versionsinformationen verloren gehen. Das ist sehr nützlich wenn ein Projekt von einem anderen Projekt als Abhängigkeit benötigt wird und dabei die genaue Version entscheidend ist.

Git stellt dafür den Befehl git submodule zur Verfügung.

$ git submodule add ${SUBREPO_URL}

Wird dieser Befehl ausgeführt lädt git das Projekt automatisch herunter und speichert die aktuellen Versionsinformationen im Index des Hauptprojektes. Dies ist sehr platzsparend da nur Verweise auf das Submodul gespeichert werden statt alles zu kopieren.

Umfassendere Informationen zu Submodulen finden sich bei Progit.

Bestehende Unterverzeichnisse als Submodul einbinden

Oft entwickelt sich die Projektstruktur aus den Gegebenheiten heraus ohne eine gezielte Planung. Oder Unterprojekte mussten erstellt werden bevor mit der Entwicklung des Hauptprojektes begonnen werden konnte. So kann es passieren, dass ein Projekt entsteht welches bereits Repositories in seinen Unterverzeichnissen enthält. In der Vergangenheit hatte ich das Problem, dass ich Unterprojekte nur über den weiter oben beschriebenen Befehl aufnehmen konnte. Wenn bereits ein Unterverzeichnis mit gleichem Namen existierte gab git beim Versuch das Repository des Unterprojektes auszuchecken eine Fehlermeldung aus. Damit das Repository als Unterprojekt aufgenommen wird muss auf jeden Fall der Pfad dorthin als Argument übergeben werden.

$ git submodule add ${SUBREPO_URL} ${existing/submodule/path}

Dieser Befehl wird auch dann verwendet, wenn der Name des Unterverzeichnisses anders als der des Repositories lauten soll.

Tags git

Arbeiten mit der Fehlerliste in Vim

[Posted by Benjamin Kober on 30 Nov 2011]

Beim Arbeiten mit Vim kommt man immer wieder mit einem temporären Puffer in Berührung, in welchem beispielsweise die beim Kompilieren zwischengespeichert werden. Dieser Buffer funktioniert als eine Art Link-Liste mit deren Hilfe man an die Position des jeweiligen Fehlers springen kann.

Beim Kompilieren wird der Puffer mit dem Befehl

:make

gefüllt werden. Das aktuelle Editierfenster springt automatisch zum ersten Fehler. Das ist sehr nützlich um sofort an die Stellen im Quelltext zu kommen, an denen man Korrekturen vornehmen muss.

Mit

:cfirst
:cnext
:cprevious
:clast

navigiert man von einer Stelle zur nächsten. Manchmal ist es allerdings sinnvoll die ganze Liste sehen zu können und anhand dessen eine Vorauswahl treffen zu können um Folge- oder weniger wichtige Fehler zu übergehen und sich auf die wichtigen Stellen konzentrieren zu können. Dazu wird folgender Befehl verwendet:

:copen

Es öffnet sich ein neues Fenster, in dem die Fehler und deren Stellen aufgelistet sind. Durch drücken der Entertaste springt man an die Stelle, welche auf der aktuellen Zeile verlinkt ist.

Weitere Anwendungen

Natürlich ist die Verwendung als Fehlerliste nur eine von vielen möglichen Verwendungen. Viele weitere Plugins setzen diese Funktionalität ebenfalls ein. Zum Beispiel benutzt das Plugin fugitive (Ein Wrapper zur Benutzung von git aus Vim heraus) sie für die Befehle Ggrep und Glog.

Tags vim, fugitive

Vim Virtual Block Modus

[Posted by Benjamin Kober on 08 Nov 2011]

Eines der wichtigsten Werkzeuge für jeden Programmierer ist der Editor. Ich persönlich bevorzuge Vim für diese Aufgabe. Auf ein besonders nützliches Feature dieses Editors möchte ich heute eingehen:

Den visuellen Block Modus

Dieser Modus ermöglicht es Text spaltenweise zu bearbeiten. Man erreicht ihn unter normalen Umständen mit der Tastenkombination “CTRL-V”. Vor allem, wenn man Tabellarische Daten oder Quelltexte bearbeitet kann man das gut gebrauchen. So lassen sich beispielsweise ähnliche Anweisungen in einem Quelltext mit nur einem Befehl schreiben, ändern oder Teile davon löschen, ohne dass man die entsprechende Befehlsfolge in jeder Zeile neu ausführen muss. Allerdings funktioniert das nur dann so richtig gut, wenn die jeweiligen Spalten genau übereinander liegen und exakt die gleiche Länge haben. Was kann man tun um mit diesem Problem fertig zu werden.

Suchen und Ersetzen im visuellen Block Modus

Ein weiteres nützliches Feature von Vim ist der “substitute”-Befehl. Dieser kann in Kombination mit dem visuellen Block Modus viele Problemlösungen erleichtern. Wechselt man bei gewähltem visuellen Bereich in den ex-Modus wird als Kontext aber leider nicht der ausgewählte Bereich, sondern alle Zeilen in denen der Bereich liegt ausgewählt. Den visuellen Bereich gibt man mit /\%V an. Zum Beispiel

:'<,'>s/\%Vpattern/ersatz/g

Den visuellen Bereich nachträglich anpassen

Manchmal möchte man den visuellen Bereich für mehrere Befehle verwenden. Um den selben Bereich wie beim vorigen Mal auszuwählen gibt man einfach gv ein.

In anderen Fällen möchte man die Auswahl des Bereiches vielleicht erweitern oder anpassen, ohne den ganzen Bereich erneugt auszuwählen. Hierzu gibt man während man im visuellen Modus ist die Befehle o oder O ein um den Curser jeweils in die engegegngesetzte Ecke des visuellen Bereiches zu bewegen bzw. an das andere Ende der Zeile.

Weitere Möglichkeit und Erklärungen zum visuellen Modus bekommt man mit

:help visual

Tags vim

Vordefinierte Variablen beim gcc ermitteln

[Posted by Benjamin Kober on 24 Oct 2011]

Manchmal möchte man gerne die Defines des Compilers wissen. Dies geschieht zum Beispiel wenn man platformspezifische Informationen mit #ifdef Anweisungen berücksichtigen möchte oder muss. Leider ist es kaum möglich diese Angaben aus der Dokumentation zu ermitteln. Die folgende Befehlsfolge hilft weiter:

$ touch empty.c
$ gcc -v -dD -E empty.c

Tags gcc

Änderungen an getrackten Dateien in git ignorieren

[Posted by Benjamin Kober on 06 Sep 2011]

Manchmal möchte man Dateien nur einmal in git einchecken und sie danach in die .gitignore-Datei packen. Sie dienen dann als eine Art template, welches jeder bei sich anpassen kann ohne das diese Änderungen Auswirkungen auf den auf dem Server gespeicherten Stand haben. Dabei tritt das Problem auf, dass git Dateien welche einmal in das Repository aufgenommen wurden immer im Index aktualisiert auch wenn sie in der Ignore-Liste stehen.

Mit dem Befehl

$ git update-index --assume-unchanged ${FILE} ...

können die betreffenden Dateien und Ordner ignoriert werden. Dies hat ausserdem den Vorteil dass der

$ git status

Befehl unwichtige Änderungen nicht anzeigt und man sich auf das konzentrieren kann was wichtig ist. Will man die Datei wieder aufnehmen so führt man den Befehl

$ git update-index --no-assume-unchanged ${FILE} ...

aus um die Dateien nicht länger zu ignorieren.

Tags git

Blog mit Jekyll

[Posted by Benjamin Kober on 10 May 2011]

Dies ist der erste Eintrag in meinem Blog. Anders als gewöhnliche Blogs basiert er auf Jekyll.

Was ist so cool daran?

Normalerweise sitzt man an seinem Browser und tippt die Einträge direkt über das Webinterface ein. Aber wie wir alle wissen ist ein Browser kein ordentlicher Editor. Ausserdem lassen sich die einmal eingegebenen Daten nicht mehr ordentlich verwalten, sobald sie einmal auf dem Server sind.

Welche Möglichkeiten haben wir?

Ideal wäre es mit git arbeiten zu können und die Dateien in einem einfachen ASCII-Format zu speichern. Sprachen wie textile, asciidoc und markdown bieten sich dafür an.

Auf meiner Suche nach einer Lösung dieser Art stieß ich auf den Artikel Blogging like a Hacker von Tom Preston Werner (einem der github-Gründer). Offensichtlich hatte er das gleiche Problem. Er schrieb die Blogging-Software mit der dieser Blog erstellt wird. Da das ganze aber git-basiert ist lässt es sich wunderbar mit github integrieren. Eine Anleitung dazu findet sich unter http://pages.github.com. Endlich ist es möglich Webseiten und Blogs so zu verwalten, wie man es sich immer gewünscht hat.

Tags jekyll, github, git