Ist es besser, Funktionen in der Header-Datei oder der Quelldatei zu dokumentieren?

86

In Sprachen, die zwischen einer "Quell" - und "Header" -Datei (hauptsächlich C und C ++) unterscheiden, ist es besser, Funktionen in der Header-Datei zu dokumentieren:

(gestohlen von CCAN )

/**
 * time_now - return the current time
 *
 * Example:
 *  printf("Now is %lu seconds since epoch\n", (long)time_now().tv_sec);
 */
struct timeval time_now(void);

oder in der Quelldatei?

(gestohlen von PostgreSQL)

/*
 * Convert a UTF-8 character to a Unicode code point.
 * This is a one-character version of pg_utf2wchar_with_len.
 *
 * No error checks here, c must point to a long-enough string.
 */
pg_wchar
utf8_to_unicode(const unsigned char *c)
{
...

Beachten Sie, dass einige Dinge nur in der Kopfzeile definiert sind, z. B. Strukturen, Makros und static inlineFunktionen. Ich spreche nur von Dingen, die in einer Header-Datei deklariert und in einer Quelldatei definiert sind .

Hier sind einige Argumente, die mir einfallen. Ich neige dazu, in der Quelldatei zu dokumentieren, daher sind meine Argumente für "Pro-Header" möglicherweise etwas schwach.

Pro-Header:

  • Der Benutzer benötigt den Quellcode nicht, um die Dokumentation anzuzeigen.
    • Die Quelle kann unbequem oder sogar unmöglich zu beschaffen sein.
    • Dies hält die Schnittstelle und die Implementierung weiter auseinander.

Pro-Source:

  • Dadurch wird der Header viel kürzer und der Leser kann das Modul als Ganzes aus der Vogelperspektive betrachten.
  • Es verbindet die Dokumentation einer Funktion mit ihrer Implementierung, sodass leichter erkennbar ist, dass eine Funktion das tut, was sie sagt.

Seien Sie bei der Beantwortung vorsichtig mit Argumenten, die darauf beruhen, was Tools und "moderne IDEs" können. Beispiele:

  • Pro-Header: Durch das Falten des Codes können kommentierte Header besser navigiert werden, indem die Kommentare ausgeblendet werden.
  • Pro-Source: Mit der Find this global definitionFunktion von cscope gelangen Sie zur Quelldatei (wo sich die Definition befindet) und nicht zur Header-Datei (wo sich die Deklaration befindet).

Ich sage nicht, dass Sie solche Argumente nicht vorbringen, aber denken Sie daran, dass nicht jeder mit den von Ihnen verwendeten Tools so vertraut ist wie Sie.

Joey Adams
quelle
Dieselbe Frage kann für Pascal / Delphi gelten, wo es keine Quell- und Header-Dateien, sondern Interface- und Implementierungsabschnitte gibt.
Jan Doggen

Antworten:

96

Meine Sicht...

  • Dokumentieren Sie, wie die Funktion in der Header-Datei oder genauer in der Nähe der Deklaration verwendet wird.

  • Dokumentieren Sie die Funktionsweise der Funktion (wenn dies aus dem Code nicht ersichtlich ist) in der Quelldatei oder genauer gesagt in der Nähe der Definition.

Für die Vogelperspektive in der Kopfzeile benötigen Sie nicht unbedingt die Dokumentation, die Sie schließen müssen - Sie können Gruppen von Deklarationen gleichzeitig dokumentieren.

Grundsätzlich sollte der Anrufer an Fehlern und Ausnahmen interessiert sein (wenn sie nur übersetzt werden können, während sie sich durch die Abstraktionsebenen ausbreiten), sodass diese in der Nähe der relevanten Deklarationen dokumentiert werden sollten.

Steve314
quelle
13
+1 - dh dokumentieren Sie die Schnittstelle in der Kopfzeile. Die blutigen Details zum Wie und Warum in der Quelle.
quick_now
2
Für Bibliotheksheader, in denen keine Quelle verfügbar ist, fügen Sie möglicherweise Vor- und Nachbedingungen usw. hinzu, um beim Testen zu helfen. Fügen Sie außerdem die O (n) -Leistung hinzu, wenn dies sinnvoll ist, sodass Benutzer der Bibliothek eine sinnvolle Auswahl treffen können.
Patrick Hughes
Natürlich sind Deklaration und Definition manchmal ein und dasselbe.
Deduplikator
@Deduplicator - Wenn die gleichen Regeln auch im Sonderfall noch zum richtigen Ergebnis führen, warum diese Regeln für jeden Sonderfall wiederholen? Sicherlich sollte ein Deduplizierer das nicht wollen?
Steve314
1
@Deduplicator - das ist natürlich ein stark überlegter Grund, warum du deinen Rat nicht befolgst, aber ich halte mich daran.
Steve314
34

Wenn Sie ein Tool wie Doxygen verwenden (beachten Sie, dass es im ersten Beispiel wirklich wie ein Doxygen-Kommentar aussieht, weil er mit beginnt /**), spielt das keine Rolle - Doxygen durchsucht Ihre Header- und Quelldateien und sucht Alle Kommentare, um die Dokumentation zu generieren.

Ich wäre jedoch eher geneigt, die Dokumentationskommentare in die Überschriften zu setzen, in denen sich die Deklarationen befinden. Ihre Kunden werden sich mit den Kopfzeilen befassen, um mit Ihrer Software zu kommunizieren. Die Kopfzeilen sind das, was sie in ihre eigenen Quelldateien aufnehmen. Dort werden sie zuerst nachsehen, wie Ihre API aussieht.

Wenn Sie sich beispielsweise die meisten Linux-Bibliotheken ansehen, enthält Ihr Linux-Paketverwaltungssystem häufig ein Paket, das nur die Binärdateien der Bibliothek enthält (für "normale" Benutzer mit Programmen, die die Bibliothek benötigen), und Sie haben ein "dev" -Paket, das diese enthält enthält die Überschriften für die Bibliothek. Der Quellcode wird normalerweise nicht direkt in einem Paket geliefert. Es wäre wirklich umständlich, wenn Sie den Quellcode einer Bibliothek irgendwo abrufen müssten, um die Dokumentation der API zu erhalten.

Jesper
quelle
2
+1 - mit dem Vorbehalt, dass Sie, selbst wenn Sie Doxygen verwenden, niemals direkt aus der Quelle lesen werden. Doxygen-Annotationen sind manchmal sogar als Standardmuster nützlich, nach denen gesucht werden muss. Es ist praktisch, wenn die gefundene Annotation in der Nähe des beschriebenen Codes liegt.
Steve314
1
@ Steve314 Natürlich habe ich nicht gesagt, dass Sie sich niemals den Quellcode einer Bibliothek ansehen möchten - aber das wäre nicht der erste Ort, an dem Sie nach dem Aussehen und der Verwendung der API suchen würden.
Jesper
Ich würde auch empfehlen, alles, was mit der API zu tun hat, im Header (oder zumindest entweder im Header oder in der Quelle) zu belassen, da dies potenzielle Inkohärenzen bei der Aktualisierung der Dokumentation an der einen und nicht an der anderen Stelle vermeiden würde.
Jopasserat
12

Wir haben dieses Problem (vor ungefähr 25 Jahren) gelöst, indem wir eine Reihe von #Defines (z. B. public, private usw., die in <nothing> aufgelöst wurden) erstellt haben, die in der Quelldatei verwendet werden konnten und von einem awk-Skript gescannt wurden (horrors) !), um die .h-Dateien automatisch zu generieren. Dies bedeutet, dass sich alle Kommentare in der Quelle befanden und (falls zutreffend) in die generierte .h-Datei kopiert wurden. Ich weiß, dass es ziemlich altmodisch ist, aber es hat diese Art der Inline-Dokumentation erheblich vereinfacht.

Peter Rowell
quelle
1
hmm ich weiß, dass diese art der sache nützlich sein kann, aber aus meiner
sicht
1
Um Donald Rumsfeld (einen Mann, den ich nicht mochte) zu paraphrasieren : "Sie programmieren mit den Werkzeugen, die Sie haben, nicht mit den Werkzeugen, die Sie sich gewünscht haben." Jede Sprache, mit der ich in den letzten 40+ Jahren gearbeitet habe, hatte mindestens eine große Warze (wenn nicht mehr). Unsere Lösung a) funktionierte, b) verwendete Tools, die zu der Zeit existierten, c) ließ uns unsere Zeit damit verbringen, um Umsatz generierenden Code herauszubekommen.
Peter Rowell
Auch wenn ich mich wahrscheinlich nicht dafür entschieden hätte, ist dies eine interessante Möglichkeit, mit Kommentaren in Kopfzeilen umzugehen. Befinden sich die generierten Header in der Versionskontrolle? oder ist dies ein Release-Prozess, um die Quelle weitervertreibbar zu machen? (aber nicht von den Entwicklern verwendet)
ideasman42
Oh, ich habe das gleiche Muster kürzlich in einem Projekt gesehen, das ≥ 2000 begann, und sie waren so stolz auf ihre clevere Erfindung…
5gon12eder
3
In unserem Fall haben wir keine der generierten Dateien unter Versionskontrolle gehalten, da sie leicht und direkt von nachverfolgten Dateien (wieder) abgeleitet wurden.
Peter Rowell
9

Angenommen, dies ist Code in einem größeren Projekt (in dem Entwickler häufig zwischen Quellcode und Headern wechseln) , und vorausgesetzt, dies ist keine Bibliothek / Middleware, in der andere möglicherweise keinen Zugriff auf den Quellcode haben. Ich habe festgestellt, dass dies funktioniert Beste...

  • Kopfzeilen:
    Nur bei Bedarf kurze Kommentare mit 1 bis 2 Zeilen.
    Manchmal sind auch Kommentare über einer Gruppe verwandter Funktionen hilfreich.
  • Quelle:
    Dokumentation auf API direkt über der Funktion (Klartext oder Sauerstoff, wenn Sie es vorziehen) .
  • Behalten Sie die Implementierungsdetails bei, die nur für Entwickler relevant sind, die den Code im Funktionskörper ändern.

Der Hauptgrund dafür ist, dass die Kommentare nahe am Code bleiben. Ich habe festgestellt, dass Dokumente in Kopfzeilen häufiger nicht mit Änderungen am Code synchronisiert werden (das sollten sie natürlich nicht, aber sie taten es in unserem Projekt unter am wenigsten) . Außerdem können Entwickler Dokumentation zu den Funktionen hinzufügen, wenn sie Änderungen vornehmen, selbst wenn Header-Dokumente vorhanden sind ... an einer anderen Stelle. Verursachen von Double-Ups oder nützlichen Informationen, nur um in einem der Dokument-Strings zu sein.

Natürlich können Sie eine Konvention auswählen und sicherstellen, dass alle Entwickler der Konvention folgen. Ich fand die Konvention gerade über der natürlichsten und verursacht die geringsten Probleme bei der Wartung.


Zuletzt, für große Projekte - es gibt eine Neigung nicht kleine Korrekturen in einem Header zu machen , wenn Sie wissen , seine potenziell 100 oder die 1000 von Dateien verursachen würden neu zu kompilieren , wenn andere Versionskontrolle aktualisieren - Halbierungs Fehler zu verlangsamen.

ideasman42
quelle
5

Meiner (eher eingeschränkten und voreingenommenen) Meinung nach bin ich eine quellcodeorientierte Denkweise. Wenn ich in C ++ Kleinigkeiten bearbeite, bearbeite ich die Header-Datei normalerweise einmal und schaue sie mir dann nie wieder an.

Wenn ich Dokumentation in die Quelldatei lege, sehe ich sie immer, wenn ich Codes bearbeite oder lese. Ich denke, es ist eine Gewohnheit.

Aber das bin nur ich ...

MattyD
quelle
1
Funktioniert nicht sehr gut, wenn Sie nur eine kompilierte Bibliothek und die Header-Datei haben. In diesem Fall ist mehr Info in der Kopfzeile eine gute Sache, weil es die einzige Schnittstellendokumentation ist, die Sie haben.
quick_now
Sie könnten Dokumentation mit doxygen erstellen - es wird auch aus .c-Dateien entnommen. So können Sie mit kompilierten Bibliotheken problemlos Dokumentationen verteilen. Das Problem liegt jedoch in der IDE, die Header-Dateien analysieren und Ihnen während der Verwendung der Funktion Dokumentation zur Verfügung stellen kann. Vielleicht kann sie aber auch ein Deploy-Skript lösen, mit dem Funktionskommentare von .c in .h kopiert werden.
Vit Bernatik
5

Kommentare sind keine Dokumentation. Die Dokumentation für eine Funktion besteht normalerweise aus 2 KB Text, möglicherweise mit Diagrammen - siehe beispielsweise die Dokumentation für Funktionen im Windows SDK. Selbst wenn Ihr Kommentar zu Dokument dies zulässt, machen Sie den Code, der den Kommentar enthält, unlesbar. Wenn Sie Dokumentation erstellen möchten, verwenden Sie ein Textverarbeitungsprogramm.

Neil Butterworth
quelle
Update, es ist heutzutage viel einfacher zu dokumentieren (mit Sachen wie Qt Creator da draußen), um nur den Doxygen (oder Klon) Weg zu dokumentieren Die Arbeit ist für Sie erledigt. Aus diesem Grund bezweifle ich, dass die Leute zu einem Textverarbeitungsprogramm springen wollen, um ihren Code zu dokumentieren. Ich habe das schon 2005 gemacht, aber das würde ich jetzt nie machen. Sogar die Verwendung eines HTML-Editors scheint mittlerweile ziemlich archaisch zu sein.
Osirisgothra
@osirisgothra Doxygen- "Dokumentation" mag einfach zu machen sein und erzeugt sicherlich viele schnell geschriebene LOCs, aber der Wert der erstellten "Dokumentation" bleibt in den allermeisten Fällen umstritten. Doxygen-Kommentare sind weder eine gute Dokumentation (fast alle wichtigen Details fehlen im Allgemeinen) noch gute Kommentare (sie wiederholen in der Regel das, was bereits aus der Signatur hervorgeht). Ich denke, nbt ist richtig zu sagen, dass echte Dokumentation am besten nicht mit Code vermischt wird, da dies die Lesbarkeit des Codes beeinträchtigt. Es wird sowieso aus dem Takt geraten, dafür gibt es keine Silberkugel.
cmaster
4

Wenn die Stakeholder Ihres Quellcodes (z. B. eine kleine Bibliothek) aus "Benutzern" (anderen Entwicklern, die die Funktionalität Ihrer Bibliothek nutzen, ohne sich an deren Implementierung zu beteiligen) und "Entwicklern" (Ihnen und anderen Entwicklern, die die Bibliothek implementieren) bestehen Geben Sie dann die "Benutzerinformationen" in die Kopfzeile und den "Implementierungshinweis" in die Quelle ein.

In Bezug auf den Wunsch, die Header-Dateien nicht mehr als unbedingt notwendig zu ändern - ich nehme an, wenn Ihre Bibliothek nicht "in einem verrückten Fluss von Änderungen" ist, werden sich die "Schnittstelle" und die "Funktionalität" nicht viel ändern, und auch nicht sollten sich die Header-Kommentare zu häufig ändern. Andererseits müssen Quellcode-Kommentare mit dem Quellcode synchronisiert ("frisch") gehalten werden.

rwong
quelle
0

Der springende Punkt bei der Verwendung von Doxygen ist, dass Sie Dokumentation generieren und an einer anderen Stelle zugänglich machen. Jetzt ist die gesamte Dokumentation in den Headern nur noch Müll, was es schwieriger macht, die erforderliche Funktionsdeklaration und möglicherweise ihre Überlastung schnell zu erkennen. Ein Kommentar ist das Maximum, der dort hingehen sollte, aber selbst das ist eine schlechte Übung. Wenn Sie die Dokumentation in der Quelle ändern, kompilieren Sie diese Quelle neu und verknüpfen sie erneut. Wenn Sie jedoch Dokumente in die Kopfzeile einfügen, möchten Sie wirklich nichts daran ändern, da dies einen erheblichen Teil der Projektwiederherstellung auslösen wird.

Slava
quelle
1
Dies scheint nichts Wesentliches zu bieten über die in den vorherigen 7 Antworten gemachten und erklärten Punkte
Mücke
1
@gnat aus den vorherigen 7 Antworten ist nur einer für Code gegen Header. Und dieser argumentiert ganz anders.
Slava