Best Practices für die Pflege dokumentierter Codebeispiele?

Ein gutes SDK (Software Development Kit) enthält viele gut dokumentierte Beispiele. Es enthält auch gute Tutorials und Entwicklerleitfäden, die Konzepte in logischen Abfolgen vorstellen und in der Regel nur die relevanten Auszüge aus dem Beispielcode zeigen. (Niemand möchte ein 200-zeiliges Programm inline in einem Buch sehen, aber es ist wichtig, diesen 20-zeiligen Auszug zu zeigen, der ein Prinzip genau dort in dem Abschnitt zeigt, der über dieses Prinzip spricht.)

Dies schafft eine Wartungsherausforderung: Im Laufe einer Reihe von Releases ändern sich Schnittstellen oder bevorzugte Codierungsmuster. Eine IDE (eine Code-Entwicklungsumgebung) bietet Tools zum Auffinden von Beispielprogrammen, die aktualisiert werden müssen (z. B. alle Stellen finden, an denen diese Funktion aufgerufen wird), aber sie helfen nicht bei Referenzen in der Dokumentation. Was meiner Erfahrung nach normalerweise passiert, ist, dass jemand vor einer Veröffentlichung die Dokumentation durchblättert und nach verdächtigen Codeschnipseln sucht. Dies ist natürlich nicht 100% zuverlässig. (Bearbeiten: Die vollständigen Beispiele werden regelmäßig getestet, aber das garantiert nicht, dass die Auszüge in der Dokumentation mit dem vollständigen Beispiel synchron bleiben.)

Derzeit verlassen wir uns auf die Technischen Redakteure, die sich hoffentlich daran erinnern, welche Beispiele wo in der Dokumentation ausgenommen wurden, um zu reagieren, wenn sich der Beispielcode oder die relevanten Schnittstellen ändern. Das Team beherrscht die Bug-Tracking- und Source-Control-Systeme, einschließlich des Abonnierens von Check-Ins, aber wir verlassen uns immer noch auf das persönliche Wissen der Leute, was zu einem Problem wird, wenn Leute das Team verlassen. (Wie so oft hat das Testen der Dokumentation für die Qualitätssicherung eher eine geringe Priorität.)

Ich suche nach Praktiken , die erfolgreich eingesetzt wurden , um die fortlaufende Genauigkeit von Codebeispielen in der Dokumentation zu verbessern.

RE Ihre letzte Bearbeitung: Sie sollten Ihre Auszüge auf jeden Fall jedes Mal, wenn Sie Ihre Dokumentation erstellen, aus der vollständig getesteten Quelle extrahieren. Natürlich löst dies von Hand nicht die Wartungsprobleme, aber es ist einfach zu automatisieren. Sehen Sie sich die Ergänzungen an, die ich gestern Abend zu meiner Antwort gemacht habe.

Antworten (7)

Python hat ein nützliches Modul namens doctest. Es wird häufig verwendet, um Tutorial-Dokumentation und Beispiele zu validieren, die als Kommentare in den Code eingebettet sind.

Das Modul doctest sucht nach Textteilen, die wie interaktive Python-Sitzungen aussehen, und führt diese Sitzungen dann aus, um zu überprüfen, ob sie genau wie gezeigt funktionieren. Es gibt mehrere gängige Möglichkeiten, doctest zu verwenden:

[...]

Tutorial-Dokumentation für ein Paket zu schreiben, großzügig illustriert mit Input-Output-Beispielen. Je nachdem, ob die Beispiele oder der erläuternde Text hervorgehoben werden, hat dies den Beigeschmack von „literate testing“ oder „ausführbarer Dokumentation“.

Da es sich bei dem Code, an dem Sie interessiert sind, lediglich um Auszüge aus der vollständigen Quelle handelt, würden Sie die Auszüge aus dem getesteten Code anhand einiger Metadaten extrahieren. Tools wie Doxygen sind für diesen Zweck vorgesehen.

Ein sprachunabhängiger Ansatz wäre, den vollständigen Quellcode für jeden Auszug in den Quellcode der Bibliothek aufzunehmen oder dort, wo sich die primäre Dokumentation befindet. Wenn Sie dann Ihr Tutorial/Entwicklerhandbuch erstellen möchten, führen Sie doctestbei Bedarf automatisierte Tests mit dem Code durch, indem Sie Ihr xUnit-Äquivalent mit -ähnlichem Connector-Code verwenden, und extrahieren Sie dann die Auszüge mit Doxygen .

Unabhängig davon, welche spezifische Lösung Sie implementieren, besteht die Best Practice für die Wartung darin, dem DRY-Prinzip zu folgen . Tun Sie, was Sie können, um den gesamten Quellcode an einem Ort aufzubewahren. In Ihrem Fall klingt es so, als müssten Sie Ihre Auszüge aus dem ursprünglichen Beispielcode jedes Mal generieren, wenn Sie die Dokumentation generieren. Auf den Seiten 26-29 (DRY-Prinzip) und weiter auf den Seiten 100-101 gibt es einige Diskussionen zum Thema Testen und Pflegen von Codebeispielen in The Pragmatic Programmer . Die Autoren beschreiben vage, wie sie das erreicht haben, was Sie brauchen:

[...] DRY-Prinzip wollten wir keine Codezeilen aus den getesteten Programmen im Buch kopieren und einfügen. Das hätte bedeutet, dass der Code dupliziert wurde, was praktisch garantiert, dass wir vergessen würden, ein Beispiel zu aktualisieren, wenn das entsprechende Programm geändert wurde. Bei einigen Beispielen wollten wir Sie auch nicht mit dem Framework langweilen, das zum Kompilieren und Ausführen unseres Beispiels erforderlich ist. Wir wandten uns Perl zu. Ein relativ einfaches Skript wird aufgerufen, wenn wir das Buch formatieren – es extrahiert ein benanntes Segment aus einer Quelldatei, hebt die Syntax hervor und konvertiert das Ergebnis in die von uns verwendete Schriftsatzsprache.

Doctest ist eine geniale Idee. Wenn Sie einfach Ihren Beispielcode kompilieren, erfahren Sie, ob er legal ist. Wenn Sie auf Warnungen achten, erfahren Sie, ob (hoffentlich) veraltete Funktionen verwendet werden. Wenn Sie es testen, um zu sehen, ob es die erwartete Ausgabe erzeugt, erfahren Sie, ob es das tut, was es verspricht. Wenn Sie Stilprüfer, Fehlersucher und andere Linting-Tools darüber laufen lassen, werden Sie feststellen, ob Sie mit gutem Beispiel vorangehen. Dies deckt nicht jede Basis ab, aber es ist ein ausgezeichneter Anfang.

Ein Vorschlag ist, das Problem außerhalb der IDE und innerhalb Ihres Versionsverwaltungstools zu lösen.

Wenn Sie Ihre Dokumentation zusammen mit Ihrem Quellcode in dasselbe Repository einchecken, können Sie Befehlszeilentools wie „git grep“ verwenden, um Code und Dokumente gleichzeitig umzugestalten.

ReadTheDocs (ein beliebtes System zum Dokumentieren von Codebasen) hat ein interessantes Feature, das eine Antwort auf diese Frage geben könnte: literalinclude .

Mit dieser Direktive kann man Codebeispiele aus einer anderen Datei in die Dokumentation einbinden. Der besonders interessante Teil ist, dass eine Teilmenge von Zeilen über die Direktive aus der Quelldatei extrahiert werden kann, :lines:was bedeutet, dass die Quelldatei ein vollständiges (ausführbares, testbares) Beispiel sein könnte, während nur der für den dokumentierten Abschnitt relevante Ausschnitt in der erscheinen muss Dokumente.

Mit dieser Direktive wäre es theoretisch möglich, alle Beispiele in die Dokumentation innerhalb der Testsuite des Projekts aufzunehmen. Ich kann nicht sagen, dass ich selbst jemals so weit gegangen bin - aber nachdem ich mehr als einmal auf dieses genaue Problem gestoßen bin, bin ich jetzt versucht, es zu versuchen!

Ach, sehr cool! Es wäre sogar noch besser, wenn es eine Möglichkeit gäbe, Markierungen in die Datei einzufügen (anstelle von Zeilenreferenzen außerhalb der Datei), so dass, wenn jemand ein Include oder einige Codekommentare (hey, das könnte passieren) oder ähnliches hinzufügt, dies der Fall ist Werfen Sie das Extrahieren nicht ab.
Das wäre sicherlich das Ideal. Ich kann verstehen, warum sie es so gemacht haben (funktioniert mit allen Sprachen, und Sphinx soll heutzutage sprachunabhängig sein), aber es hat diesen Nachteil

Ich würde dies eigentlich mit meinem Grafikdesigner-Hut auf dem Kopf beantworten: Aller Code sollte im Layoutprogramm einen bestimmten Stil erhalten (insbesondere Schriftart, aber Schriftgröße, Ränder, Blocksatz), und dann suchen Sie einfach nach jeder Iteration dieses Stils. Es ist immer noch manuell, aber Sie werden nichts vermissen.

Die Codebeispiele haben ihr eigenes Tag, aber Sie müssen sich trotzdem jedes ansehen, es im vollständigen Beispiel finden und vergleichen, was ziemlich mühsam ist. (Wir haben Dutzende von Beispielen, die Hunderte von Auszügen aus einem etwa 1500-seitigen Dokumentsatz produzieren.) Ich frage mich, ob es eine Möglichkeit gibt, dies zu skripten, was vermutlich erfordern würde, einen Weg zu finden, die Auszüge für die Datei zu kommentieren, aus der sie stammen.
Verfügt die von Ihnen verwendete Buchsoftware über eine Publish-and-Subscribe-Funktion?
Nein, wir können Änderungen der Quellcodeverwaltung jedoch per E-Mail abonnieren (so stelle ich sicher, dass ich Benachrichtigungen zu Codeänderungen erhalte, die mir wichtig sind). Die Dokumente sind Docbook (v4.4) XML, geschrieben in einer Vielzahl von Editoren (persönliche Wahl); Wir verwenden Ant-Targets, um die Builds durchzuführen, sodass wir im Prinzip die Daten der letzten Modifikation in den relevanten Beispielen überprüfen könnten, aber wir bräuchten immer noch eine Möglichkeit zu sagen, dass „dieser Programmlistenblock von foo.java stammt“, um die Auswirkungen der Änderung zu überprüfen foo.java. (Hat das Sinn gemacht?)
...meist. Ich könnte einige Strategien vorschlagen, um Eigentümer im Auge zu behalten, aber keine getesteten oder optimierten Lösungen.

Es gibt mehrere Projekte, die mir in den Sinn kommen, die dies gut zu machen scheinen. Alle von ihnen verwenden sehr ähnliche Techniken. Eines ist das Qt-Framework , ein anderes ein Tool namens Doxygen und ein drittes das GTK+-Projekt .

In allen drei Fällen wird die Projektdokumentation primär aus dem eigentlichen Quellcode des Projekts gezogen. Beide werden zusammen gepflegt, oft in denselben Dateien.

Die Dokumentation wird als markierte Kommentare im Code gespeichert. Im Allgemeinen können die Markups alles spezifizieren, von der Erstellung von Dokumentationsseiten, Abschnitten auf einer Seite, Querverweisen, der Einbeziehung von Codebeispielen (einschließlich vollständiger und teilweiser Teile von Dateien) und sogar Bildern.

Qt und GTK+ verwenden beide benutzerdefinierte Tools, um dies zu erreichen.

Doxygen ist eigentlich ein Tool zum Erstellen von Dokumentation aus Code und verwendet sich als solches selbst, um sich selbst zu dokumentieren.

Die bewährte Methode wäre, dass der gesamte Code kompiliert und möglicherweise anhand einiger Coderegeln überprüft werden muss.


Bei meiner Arbeit machen wir das so, dass alle Beispiele in der Dokumentation markiert werden und dann während unserer nächtlichen Builds alle extrahiert und kompiliert werden. Wenn also jemand die Schnittstellen modifiziert, wird der nächtliche Build dies abfangen.

Um uns dabei zu helfen, haben wir einige benutzerdefinierte Skripte. Effektiv werden verschiedene Arten von Beispielen unterschiedlich gekennzeichnet, da sie unterschiedlichen Umbruchcode benötigen, um etwas zu sein, das kompiliert werden kann. Wir haben also Code, der nur ein kleiner Ausschnitt ist, vollständige Funktionen, vollständige Klassen und dann einige vollständige Projekte. Jede wird kompiliert, damit sie zumindest mit den Schnittstellen/Funktionen auf dem neuesten Stand sind.

Wir tun derzeit nichts für bestimmte Codierungskonventionen, aber wenn der erste Teil funktioniert, können Sie anschließend eine automatische Stilprüfung durchführen. Da wir dies nicht automatisch tun, gehen wir sie hin und wieder von Hand durch.

Wir testen die Beispiele in ihrer vollständigen Form. Wie stellen Sie sicher, dass die in der Dokumentation zitierten Auszüge mit den vollständigen, getesteten Beispielen synchron bleiben?
Es handelt sich entweder um externe Dateien, die in die Hilfethemen eingebunden werden (wir verwenden Flare, das sie Snippets nennt), oder sie sind mit einem bestimmten CSS-Stil gekennzeichnet (ursprünglich zur Formatierung, jetzt zur Codeextraktion). Diese werden dann den Hilfeseiten entnommen, in einen standardmäßigen Wrapping-Code verpackt, der sie nicht mehr zu einem Auszug macht, und dann kompiliert.

Wenn ich mich richtig erinnere, beschreibt The Pragmatic Programmer in dem Buch ausdrücklich, wie sie ihr Schreibsystem aufgebaut haben, um den Code extrahierbar und ausführbar zu machen.