Suche
Kolumne: Hitchhiker’s Guide to Docs as Code

Modulare Dokumentationen: Wie man sie baut und warum sie die Teamarbeit erleichtern

Ralf D. Müller, Gernot Starke

©S&S Media

In der letzten Ausgabe haben wir gezeigt, wie Sie mithilfe von AsciiDoc schnell zu ordentlich gestalteten Dokumenten kommen können. In der zweiten Folge unserer Kolumne möchten wir Ihnen Strukturierung und Modularisierung von Dokumentation vorstellen, einerseits zur Erleichterung von Teamarbeit, andererseits zur Verwendung einzelner Dokuteile für verschiedene Zielgruppen.

Im Gegensatz zu anderen Markup-Sprachen verfügt AsciiDoc über ein mächtiges Konzept zur Modularisierung: den Befehl include::path[attributes]. Damit können Sie Ihre Dokumentation auf mehrere Dateien aufteilen. Das erleichtert die Teamarbeit und verbessert die Übersichtlichkeit. Beispielsweise kann ein Masterdokument Verweise auf Unterdokumente erhalten (Listing 1). Darin inkludieren wir zwei AsciiDoc-Dateien (kapitel-1.adoc und kapitel-2.adoc).

:source-highlighter: coderay
:imagesdir: images

== Dies ist das Hauptdokument

Durch verschiedene `include`-Anweisungen modularisieren wir die Dokumentation:

include::kapitel/kapitel-1.adoc[leveloffset=+1]

include::kapitel/kapitel-2.adoc[leveloffset=+1]
== Kapitel 1: Übersicht

Eine Übersicht ist immer nützlich...

.Module unserer Dokumentation
image::uebersicht.png[]
== Kapitel 2: Schnittstellen

include::{sourcedir}SampleInterface.java[tag=signatur]

Wie üblich übersetzen wir unsere Dokumente mit Gradle:

> cd folge-2
> gradle asciidoctor

Der AsciiDoc-Prozessor erzeugt im Verzeichnis build/asciidoc/html5/ das passende HTML (Abb. 1). Dabei wurde einerseits das HTML-Dokument erzeugt und zusätzlich noch das referenzierte Diagramm in das build-Verzeichnis kopiert. Hierzu nutzen wir wieder eine Standardeinstellung des Asciidoctor-Plug-ins für Gradle: alle Dateien aus dem images-Verzeichnis werden automatisch in das build-Verzeichnis kopiert. Es bietet sich an, die Teile der Dokumentation wie im Beispiel mit dem eigentlichen Inhalt in Unterverzeichnisse zu legen. Dadurch ist das strukturierende Masterdokument sauber vom eigentlichen Inhalt getrennt. Auch das im AsciiDoc-Format vorliegende arc42-Template ist in dieser Struktur aufgebaut.

Abb.1: HTML-Ausgabe des modularisierten Dokuments

Abb.1: HTML-Ausgabe des modularisierten Dokuments

package demo;

class SampleAILibrary {

  // beantwortet alle Fragen

  // tag::signatur[]
  static String answerQuestion(String question) throws Exception
  //end::signatur[]
  {
      if (question==null) {
  //...

Sourcecode einbinden

AsciiDoc kann auch andere Dateiformate einbinden, z. B. Sourcecode (Listing 3), wobei wir auch einzelne Fragmente aus den Sourcen in die Dokumentation einbinden können. Dazu können Sie im Sourcecode Kommentare mit einer einfachen Tag-Syntax verwenden (Listing 4). Markus Schlichting schlägt vor, den inkludierten Code immer in einen automatisierten Test einzubetten. Dadurch können Sie die Erstellung aktueller Dokumentation vom Testergebnis des referenzierten Codes abhängig machen und stellen sicher, dass alle Beispiele in der Dokumentation stimmen. Cool, oder? Führt man den Gedanken weiter, lassen sich über die Tests auch Antworten von REST-Services erzeugen, die dann in die aktuelle Dokumentation einfließen.

Ein Hinweis: Der Pfad zu Bildern wird immer über das Attribut imagesdir relativ zum Hauptdokument aufgelöst, wohingegen der Pfad zu Dokumenten (include::) relativ zum aktuell eingebetteten Dokument aufgelöst wird. Das ist bei verschachtelten Dokumenten praktisch, nicht aber bei der Referenzierung von Sourcecode. Hier bietet es sich an, im Build-File ein sourcedir-Attribut mit dem entsprechenden absoluten Pfad zu setzen und dann wie in Listing 3 zu referenzieren.

Hitchhikers Guide to Docs as Code

Mit ihrer Kolumne Hitchhikers Guide to Docs as Code – kurz HHGDC – möchten die beiden Autoren Gernot Starke (innoq) und Ralf D. Müller (freier Softwareentwickler) die Mühen der Dokumentation lindern. Ihr Ansatz ist es Softwaredokumentation wie Code zu behandeln: schreiben, bauen, testen, committen, mergen.

Stakeholderspezifische Dokumentation

Unterschiedliche Projektteilnehmer benötigen oft nur einen spezifischen Teil der Dokumentation. Allerdings gibt es Überschneidungen, z. B. eine kurze Einführung in das Projekt. Solche stakeholderspezifischen Dokumente lassen sich nun leicht generieren. Man erzeugt einfach weitere Masterdokumente, bindet jedoch unterschiedlichen Inhalt ein oder ändert die Reihenfolge von Kapiteln. Dabei kann es passieren, dass ein Kapitel, das in der Hauptdokumentation auf erster Ebene erscheint, in einem anderen Dokument in der Gliederung auf zweiter oder dritter Ebene ist. Dann müssen wir Überschriftenebenen korrigieren. AsciiDoc bietet dafür eine elegante und einfache Lösung an: Über das Attribut levelOffset der include-Anweisung lassen sich die Überschriftenebenen korrigieren.

Damit Sie nicht ständig überlegen müssen, mit welcher Überschriftebene ein Unterdokument beginnt, können Sie jedes Unterdokument einheitlich mit Überschriftenebene 1 beginnen und eine entsprechende Korrektur beim Einbinden in andere Dokumente vornehmen (Listing 1). Auf diese Weise funktioniert Modularisierung auch in großem Stil: Das VENOM-Beispiel (Abb. 2) zeigt das: Zwei Hauptdokumente (Architektur- und Businessdokumentation, insgesamt deutlich über hundert Druckseiten) werden aus mehr als zwanzig einzelnen Teilen über include-Statements verwaltet.

Abb. 2: Übersicht der modularen VENOM-Dokumentation

Abb. 2: Übersicht der modularen VENOM-Dokumentation

Tipp: Bildverweise in Unterdokumenten
Über :imagesDir::<verzeichnis> teilt man asciidoctorj mit, wo die zu referenzierenden Bilder liegen. Das Verzeichnis wird relativ im Hauptdokument angegeben. Wird ein Unterdokument im Editor geöffnet, kennt dieser nicht den korrekten Verzeichnispfad und hat keine Chance, die Bilder anzuzeigen. Es sei denn, man hilft ihm mit folgender Anweisung: ifndef::imagesdir[:imagesdir: ../images]. Die Generierung über das Hauptdokument wird dadurch nicht geändert. Ein Editor kann somit aber auch die Bilder in Unterdokumenten anzeigen.

Fazit

Modularisierung der Dokumente vereinfacht die Zusammenarbeit im Team und ermöglicht das Wiederverwenden einzelner Fragmente in verschiedenen Kontexten. Sie können das Erstellen der Dokumentation vom Ergebnis automatisierter Tests einzelner Codefragmenten abhängig machen und damit die Aktualität Ihrer Dokumentation verbessern. Die Sourcen unseres leicht gewachsenen Beispiels liegen wieder in unserem GitHub-Repo. Mit dem Docs-as-Code-Ansatz geht es aber noch weiter. In der nächsten Folge zeigen wir, wie Sie unterschiedliche Ausgabeformate erzeugen können (HTML, PDF, docx, Confluence) und welche Vor- und Nachteile sich dabei ergeben. Bis dahin: Happy Docu-Coding!

Geschrieben von
Ralf D. Müller
Ralf D. Müller
Ralf D. Müller arbeitet als Architekt und Entwickler. Er erlebt täglich die Notwendigkeit effektiver Dokumentation. Außerdem ist er erklärter AsciiDoc-Fan und Committer bei arc42 sowie Gründer des docToolchain-Projekts.
Gernot Starke
Gernot Starke
    Informatikstudium an der RWTH Aachen, Dissertation über Software-Engineering an der J. Kepler Universität Linz. Langjährige Tätigkeit bei mehreren Software- und Beratungsunternehmen als Softwareentwickler, -architekt und technischer Projektleiter. 1996 Mitgründer und technischer Direktor des „Object Reality Center“, einer Kooperation mit Sun Microsystems. Dort Entwickler und technischer Leiter des ersten offizielle Java-Projekts von Sun in Deutschland. Seit 2011 Fellow der innoQ GmbH.  
Kommentare
  1. Thomas Falkenberg2017-11-08 17:42:27

    Danke für die Serie, sehr interessant!

    Kleine Korrektur:
    In Listing 2 und 3 sollte es heißen:
    „kapitel-1.adoc" respektive "kapitel-2.adoc", aktuell fehlt der Bindestrich.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.