Docs-as-Code – Die Werkzeuge
Schlechte Dokumentation kostet Geld
In der letzten Folge unseres Artikels haben wir Ihnen den Docs-as-Code-Ansatz erklärt und das wichtigste Werkzeug näher gebracht. Bei Docs-as-Code dreht sich alles darum, dass Sie Ihre Dokumentation als reinen Text verwalten. Was machen Sie aber, wenn das nicht reicht? In dieser Folge lernen Sie docToolchain kennen, die Open-Source-Lösung zur Unterstützung des Docs-as-Code-Ansatzes.
Übersicht
Die Übersicht der Werkzeugkette in Abb. 1 zeigt Ihnen die einzelnen Komponenten unseres Ansatzes. Den Teil im grünen Kasten kennen Sie schon. Ihre Dokumentation basiert auf dem arc42-Template im AsciiDoc-Format. Dieses ist modular aufgebaut und die Module werden per include:: in das Hauptdokument referenziert (Schritt 1). Über Asciidoctor als Kommandozeilen-Werkzeug oder Plugin für Gradle bzw. Maven generieren Sie anschließend HTML (Schritt 2).
Die Schritte 3 und 4 erläutern wir Ihnen in diesem Artikel anhand praktischer Beispiele.
UML-Modellierung
In AsciiDoc können Sie vorhandene Diagramme und Grafiken direkt referenzieren und auch die Verwendung von PlantUML haben wir Ihnen gezeigt. Beides hat Grenzen. PlantUML scheitert an der Modellierung umfangreicher Diagramme, mangels geeigneter Möglichkeiten, das Layout nach Ihren Vorstellungen Einfluss zu beeinflussen. Erstellen Sie Ihre Diagramme hingegen mit einem UML-Modellierungs-Tool, müssen Sie Ihre Diagramme per Hand exportieren, um sie dann aus AsciiDoc heraus zu referenzieren. Wenn Sie z. B. den Namen einer Komponente in Ihrer Modellierung ändern, wird es schwierig, nur die Diagramme erneut zu exportieren, die sich geändert haben: Oft ist unklar, welche Diagramme von dieser Namensänderung betroffen sind. Somit müssen Sie regelmäßig alle Diagramme aktualisieren. Dies ist auf Dauer zu umständlich. Es wäre doch toll, wenn Sie den Export Ihrer Diagramme und sogar der Notizen aus Ihrem UML-Modell automatisch über den Build Ihrer Dokumentation vornehmen könnten!
Für gängige UML-Tools ist die Wahrscheinlichkeit hoch, dass ein solcher automatischer Export funktioniert. Wir haben es für Sie exemplarisch mit einigen oft verwendeten Applikationen ausprobiert.
UML-Tools fernbedienen
Der EnterpriseArchitectTM (kurz EA) von Sparx Systems ist ein echtes Modellierungswerkzeug, in dem Sie Elemente in mehreren Diagrammen verwenden und somit modellieren können. Für jedes Element gibt es die Möglichkeit, Notizen zu erstellen. Der EA verfügt über eine COM-Schnittstelle, so dass Sie ihn von außerhalb der Anwendung fernsteuern können. Ein Visual-Basic-Skript und schon öffnen sie den EA unsichtbar, laufen durch das Modell und exportieren alle Diagramme mitsamt den hinter den Elementen liegenden Notizen. Dieses Skript bauen Sie dann in Ihr Build-Skript ein, um es so (genauso wie Ihre anderen Software-Buildschritte) aufzurufen. In Gradle geht das ganz einfach über einen Task.
Listing 1: Einfacher Gradle Task
task einfacherTask (
dependsOn: [],
description: 'eine Beschreibung Ihres Tasks'
){ doLast {
// hier können Sie in Groovy definieren, was
// Ihr Task machen soll
} }
Für das konkrete Beispiel rufen Sie das VB-Skript aus Groovy auf. Klingt doch nicht einfach? Jetzt kommt docToolchain in’s Spiel!
docToolchain
Im Grunde sind solche Automatisierungen, wie die gerade eben beschriebene, einfach. Der Teufel steckt aber im Detail. Um es Ihnen einfacher zu machen, haben wir das Open-Source-Projekt docToolchain ins Leben gerufen. In diesem Projekt ist der oben beschriebene Task schon fertig ausprogrammiert und Sie können ihn einfach verwenden. Eine Übersicht über alle zur Zeit vorhandenen Tasks zeigt die docToolchain-Übersicht in Abb. 2. Ausführliche Beschreibungen finden Sie in der Dokumentation [1].
Was aber, wenn nicht der richtige, von Ihnen benötigte, Task in docToolchain umgesetzt ist? Vielleicht verwenden Sie ja ein anderes Tool zum zeichnen Ihrer Diagramme?
Wir wollen docToolchain nicht nur als Werkzeug verstanden wissen, sondern auch als Idee, was Sie mit Dokumentation alles machen können. Falls Sie dann eine der in docToolchain vorhandenen Ideen in Ihrer eigenen Werkzeugkette anwenden möchten, dann finden Sie sicherlich einen Task in docToolchain, den Sie als Template für Ihre eigene Umsetzung nutzen können. Dem entsprechend stellen wir Ihnen jetzt noch weitere Möglichkeiten vor, wie Sie Ihre aktuellen Werkzeuge auch in Zukunft zur Pflege Ihrer Dokumentation einbinden können.
Lesen fremder Daten
Ein vorhandenes Dokumentationswerkzeug fernzusteuern und Daten zu exportieren bindet sie technisch eng an dieses Werkzeug: Während des Build-Prozesses muss dieses Werkzeug zur Verfügung stehen. Lesen Sie doch einfach direkt die Daten aus der Quelle – der Datei, in die Ihr Werkzeug die Daten persistiert! Dieser Ansatz ist nicht immer möglich, da nicht alle Dateiformate gut genug dokumentiert sind. Im Fall von MS Excel haben wir aber Glück. Sie finden in der Apache POI-Bibliothek ein gutes Werkzeug, um eine Excel-Datei direkt und ohne Umwege zu lesen.
In docToolchain wird dies genutzt, damit Sie Tabellen einfacher pflegen können. Der Task exportExcel sucht nach allen Excel-Dateien im Projekt, öffnet sie und konvertiert den Inhalt Arbeitsblatt für Arbeitsblatt nach AsciiDoc. Das Ergebnis includieren Sie einfach wieder in Ihre Dokumentation.
Versionierung
Vielleicht haben Sie beim Lesen des Artikels auch schon darüber nachgedacht, welche Dateien Sie jetzt am besten unter Versionskontrolle stellen.
Die binären Ausgangsdateien Ihrer Werkzeuge, also Sparx Enterprise Architect und MS Excel? Die exportierten Dateien?
In der Softwareentwicklung gilt es als falsch, generierte Dateien zu versionieren. Dabei handelt es sich auch meist um compilierten Sourcecode und somit binäre Dateien, die Sie schlecht versionieren können. Bezüglich der Ausgangsdateien stellt sich wohl niemand die Frage der Versionierung, solange es sich um Textdateien handelt. Da in diesen Dateien Ihre Arbeit steckt, werden sie selbstverständlich versioniert. Bei Verwendung des Docs-as-Code-Ansatzes dreht sich das Blatt auf einmal – zumindest bezüglich der von Ihnen verwendeten Dokumentationstools. Die Ausgangsdateien sind meist binär, die exportierten Daten entweder Grafiken oder Texte.
Die Erfahrung hat uns gezeigt, dass auch in diesem Fall die binären Ausgangsdateien einer Versionierung und somit eines Backups unterliegen sollten. Git kommt mit solchen Dateien ganz gut zurecht. Sollten Sie diese Dateien aber schon anderweitig verwalten, weil Sie z. B. Ihr UML-Modell in der Datenbank speichern, dann ist das auch in Ordnung. In diesem Fall sollte sich im Code-Repository jedoch ein klarer Hinweis auf die Quellen befinden.
Bezüglich der exportierten Texte und Grafiken weichen wir vom Schema des Softwareentwicklers ab und nehmen auch diese generierten Artefakte unter Versionskontrolle. Das hat zwei entscheidende Vorteile:
- Zum Einen können Sie mit diesen Dateien besser einen Vergleich durchführen und somit Änderungen besser nachverfolgen.
- Zum Anderen geht es hier aber auch um die Werterhaltung der Dokumentation. Unter Umständen ändern sich die Werkzeuge, mit denen Sie die binären Ausgangsdateien bearbeiten können, und Sie stellen irgendwann fest, dass Sie diese nicht mehr bearbeiten können. Dann stehen Ihnen immer noch die generierten Artefakte zur weiteren Bearbeitung zur Verfügung.
Der Idealfall
Gerne stellen wir Ihnen auch noch vor, wie im Idealfall (aus Sicht Ihrer Werkzeugkette) die Bearbeitung Ihrer Diagramme aussehen kann. Stellen Sie sich ein flexibles Dateiformat vor, welches sich beim Referenzieren aus AsciiDoc wie eine Grafik verhält, beim Öffnen mit Ihrer Diagrammsoftware jedoch die Beschreibung des Diagramms als XML preisgibt, so dass Sie es einfach weiter (als Vektorgrafik!) bearbeiten können.
Unmöglich? Draw.io speichert Metadaten im PNG-Format, um genau diese Magie zu implementieren: Geben Sie einfach Ihrem Diagramm von Anfang an die Dateiendung .png anstatt .xml und Draw.io kümmert sich um den Rest. Wir verwenden gerne die Endung .dio.png, um auf einen Blick die ansonsten versteckten Metadaten zu erkennen.
Apropos Meta-Daten im PNG-Format: Auch PlantUML nutzt dieses Feature und versteckt den Quellcode der Diagramme dort.
java -jar plantuml.jar -metadata ihr-diagramm.png
Hinweis: viele Programme (u. a. Paint.net) ignorieren die Meta-Daten in PNG-Dateien oder löschen sie sogar. Bearbeiten Sie die Diagramm-Datei mit einer solchen Software, könnten die Metadaten verloren gehen. Aber dafür haben Sie Diagramme ja unter Versionkontrolle...
Ausgabeformate
Zurück zur Übersicht der Werkzeugkette: In Schritt Zwei erzeugen Sie mit Asciidoctor im Regelfall HTML. Aber wie erzeugen Sie andere Ausgabeformate?
Backends
Asciidoctor benutzt zum Erzeugen verschiedener Ausgabeformate sogenannte Backends. Das funktioniert prima mit den integrierten Backends für HTML5 und docBook, ebenso wenn Sie mit reveal.js Präsentationen erstellen möchten [2]. Jedoch gibt es auch über diese eingebauten Formate hinaus weitere Möglichkeiten.
Asciidoctor unterstützt PDF als Plugin. Lassen Sie sich nicht vom Versionszusatz -alpha irritieren. Das Plugin ist ausgereift genug, um es für technische Dokumentation zu verwenden!
Sie aktivieren das Plugin in Ihrem Build, indem Sie eine Zeile hinzufügen:
dependencies {
asciidoctor 'org.asciidoctor:asciidoctorj-diagram:1.5.11'
asciidoctor 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.15'
}
Anschließend sollten Sie den Asciidoctor-Task duplizieren. In Gradle ist es leicht möglich, zwei getrennte Tasks zu erstellen, die beide vom Asciidoctor-Task "erben". Dies ermöglich es Ihnen, für die Generierung von PDF andere Attribute zu setzen, als für die Generierung von HTML.
// common settings for asciidoctor
// this is needed for PDF generation with plantUML
tasks.withType(AsciidoctorTask) { docTask ->
sourceDir = file("src/docs/")
sources { include "Part-2-DocToolchain.adoc" }
requires = ['asciidoctor-diagram']
}
task generateHTML ( type: AsciidoctorTask ) {
backends = ['html5']
}
task generatePDF ( type: AsciidoctorTask) {
backends = ['pdf']
}
Mit .yaml-basierten Styles können Sie anschließend noch jedes Detail des PDFs konfigurieren. Der PDF-Theming-Guide ist Ihnen dabei behilflich [3]. So haben Sie für die PDF-Ausgabe die Kontrolle über Formatierungen, die nur bei seitenorientierten Formaten Sinn machen, wie z. B. unterschiedliche Fußzeilen für linke und rechte Seite. Einige umfangreiche Beispiele für die Generierung von PDF aus AsciiDoc finden Sie auf dem Github-Account des iSAQB, etwa beim Foundation-Lehrplan [4].
DOCX
Möchten Sie Ihre Dokumentation im Office-Open-XML-DOCX-Format erstellen, so dass sie z. B. mit MS-Word gelesen werden kann, so ist ein Zwischenschritt notwendig. AsciiDoc bzw. Asciidoctor ist mit dem docBook-Format im Hinterkopf entwickelt worden und Asciidoctor unterstützt docBook als internes Backend. Sie können also davon ausgehen, dass sich alle Formatierungen beim Erstellen Ihrer Dokumentation auch in der docBook-Ausgabe von Asciidoctor wiederfinden.
Dies nutzen wir und wandeln mit Hife von Pandoc (dem Schweizer Taschenmesser der Formatkonvertierung) anschließend das docBook-Format weiter in DOCX oder auch ePUB [5]. Dazu benötigen Sie eine funktionsfähige Installation von Pandoc – insbesondere muss das Pandoc-Tool per Kommandozeile ausführbar sein.
Confluence
Für den Export Ihrer Dokumentation aus anderen Werkzeugen haben wir Ihnen oben drei verschiedene Ansätze vorgestellt. Auch in Bezug auf Ausgabeformate gibt es weitere Ansätze. Confluence, als ein bekannter Vertreter eines Wikis, ist ein webbasiertes Werkzeug und verfügt über eine REST API. Es nutzt einen XHTML-Dialekt als internes Speicherformat. Was liegt also näher, als die AsciiDoc-Dokumentation zuerst nach HTML5 (das ist von Natur aus XHTML-konform) zu wandeln, per Gradle Tasks ein wenig zu transformieren und dann per REST API nach Confluence zu übertragen?
Die Transformation ermöglichte es Ihnen, die Ausgabe an die Zielumgebung anzupassen. Während sich in HTML eine einzige große Seite als praktisch erweist, konvertieren wir mit docToolchain die Seite für Confluence entsprechend der Überschriften in mehrere kleinere Seiten. So entsteht eine Seitenstruktur und die Kommentarfunktion am Ende einer Seite kann effektiver genutzt werden (s. Abb. 3).
Fazit
Nachdem wir Ihnen im ersten Artikel unserer Docs-as-Code-Reihe zeigten, wie Sie mit AsciiDoc und arc42 den Docs-as-Code-Ansatz für Ihre Architekturdokumentation umsetzen können, haben wir Ihnen in dieser Folge einen Einblick gegeben, wie Sie aus diesem Ansatz noch mehr machen können, indem Sie weitere Schritte der Dokumentationserstellung in Ihren Build integrieren. Das Open-Source-Tool docToolchain unterstützt Sie dabei und bietet die oben genannten Build-Schritte als vorgefertigte Tasks.
In der nächsten Folge zeigen wir Ihnen, wie Sie verschiedene Dokumentationsartefakte zu einer Website zusammenführen und somit alles unter ein Dach bringen. Noch mehr Informationen finden Sie in der Zwischenzeit auch auf Docs-as-Co.de [6], diesen Artikel als Docs-as-Code-Version auf Github [7] und die Dokumentation von docToolchain [1].
In diesem Sinne wünschen wir viel Erfolg mit Docs-as-Code.
- docToolchain: Dokumentation
- docToolchain: mit reveal.js Präsentationen erstellen
- Github: PDF-Theming-Guide
- Github: Foundation-Lehrplan
- Pandoc
- Docs-as-Co.de
- Artikel als Docs-as-Code-Version