Czy lepiej dokumentować funkcje w pliku nagłówkowym lub źródłowym?

86

Czy w językach, w których rozróżnia się pliki „źródłowe” i „nagłówkowe” (głównie C i C ++), lepiej udokumentować funkcje w pliku nagłówkowym:

( sprowadzony z 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);

lub w pliku źródłowym?

(splądrowany z 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)
{
...

Zauważ, że niektóre rzeczy są zdefiniowane tylko w nagłówku, takie jak struktury, makra i static inlinefunkcje. Mówię tylko o rzeczach zadeklarowanych w pliku nagłówkowym i zdefiniowanych w pliku źródłowym.

Oto kilka argumentów, o których mogę myśleć. Skłaniam się ku dokumentacji w pliku źródłowym, więc moje argumenty „Pro-header” mogą być nieco słabe.

Pro-nagłówek:

  • Użytkownik nie potrzebuje kodu źródłowego, aby zobaczyć dokumentację.
    • Źródło może być niewygodne lub nawet niemożliwe do zdobycia.
    • Dzięki temu interfejs i implementacja są bardziej oddalone.

Pro-source:

  • To sprawia, że ​​nagłówek jest znacznie krótszy, dając czytelnikowi widok z lotu ptaka na moduł jako całość.
  • Paruje dokumentację funkcji z jej implementacją, dzięki czemu łatwiej jest zobaczyć, że funkcja robi to, co mówi.

Odpowiadając, należy uważać na argumenty oparte na tym, co mogą zrobić narzędzia i „nowoczesne IDE”. Przykłady:

  • Pro-header: Składanie kodu może ułatwić nawigację w skomentowanych nagłówkach, ukrywając komentarze.
  • Pro-source: Cscope „s Find this global definitioncecha powoduje przejście do pliku źródłowego (gdzie definicja jest) raczej niż plik nagłówka (gdzie deklaracja jest).

Nie mówię, nie rób takich argumentów, ale pamiętaj, że nie wszyscy czują się tak dobrze z narzędziami, z których korzystasz, jak ty.

Joey Adams
źródło
To samo pytanie może dotyczyć Pascal / Delphi, w których nie mamy plików źródłowych i nagłówkowych, ale sekcje interfejsu i implementacji.
Jan Doggen,
1
Zobacz także stackoverflow.com/questions/355619/…
cp.engr

Odpowiedzi:

96

Mój widok...

  • Udokumentuj, jak korzystać z funkcji w pliku nagłówkowym, a dokładniej w pobliżu deklaracji.

  • Udokumentuj, jak działa ta funkcja (jeśli nie wynika to z kodu) w pliku źródłowym, a dokładniej, blisko definicji.

Jeśli chodzi o ptasie oko w nagłówku, niekoniecznie potrzebujesz dokumentacji, która się zamyka - możesz dokumentować grupy deklaracji jednocześnie.

Mówiąc ogólnie, osoba dzwoniąca powinna być zainteresowana błędami i wyjątkami (jeśli tylko po to, aby można je było przetłumaczyć, propagując przez warstwy abstrakcji), aby były one udokumentowane w pobliżu odpowiednich deklaracji.

Steve314
źródło
13
+1 - tzn. Udokumentuj interfejs w nagłówku. Krwawe szczegóły jak i dlaczego w źródle.
szybko_niedz.
2
W przypadku nagłówków bibliotek, w których nie ma dostępnego źródła, można dodać warunki przed i po, itp., Aby pomóc w testowaniu. Dodatkowo dodaj wydajność O (n), jeśli ma to sens, aby użytkownicy bibliotek mogli wybierać mądrze.
Patrick Hughes,
Oczywiście czasami deklaracja i definicja są takie same.
Deduplicator,
@Deduplicator - jeśli te same reguły nadal prowadzą do właściwej rzeczy, nawet w specjalnym przypadku, po co powtarzać te reguły dla każdego specjalnego przypadku? Z pewnością deduplikator nie powinien tego chcieć?
Steve314,
1
@Deduplicator - oczywiście jest to przemyślane uzasadnienie nieprzestrzegania twoich rad, ale trzymam się tego.
Steve314,
34

Jeśli zamierzasz użyć narzędzia takiego jak Doxygen (uwaga w pierwszym przykładzie, który naprawdę wygląda jak komentarz Doxygen, ponieważ zaczyna się od /**), to tak naprawdę nie ma znaczenia - Doxygen przejrzy pliki nagłówkowe i źródłowe i znajdzie wszystkie komentarze do wygenerowania dokumentacji.

Byłbym jednak bardziej skłonny do umieszczania komentarzy do dokumentacji w nagłówkach, w których znajdują się deklaracje. Twoi klienci będą mieli do czynienia z nagłówkami, aby połączyć się z twoim oprogramowaniem, nagłówki będą takie, jakie będą w swoich własnych plikach źródłowych i właśnie tam będą szukać, aby zobaczyć, jak wygląda twój interfejs API.

Jeśli na przykład spojrzysz na większość bibliotek Linuksa, twój system zarządzania pakietami Linux często zawiera pakiet, który zawiera tylko pliki binarne biblioteki (dla „normalnych” użytkowników, którzy mają programy, które potrzebują biblioteki) i masz pakiet „dev”, który zawiera nagłówki biblioteki. Kod źródłowy zwykle nie jest dostarczany bezpośrednio w paczce. Byłoby naprawdę kłopotliwe, gdybyś musiał gdzieś zdobyć kod źródłowy biblioteki, aby uzyskać dokumentację API.

Jesper
źródło
2
+1 - pod warunkiem, że nawet jeśli użyjesz Doxygen, nie oznacza to, że nigdy nie będziesz czytać bezpośrednio ze źródła. Adnotacje Doxygen są czasem przydatne jako standardowe wzorce, za którymi można się posługiwać, i jest to przydatne, jeśli znaleziona adnotacja jest zbliżona do opisanego kodu.
Steve314
1
@ Steve314 oczywiście Nie powiedziałem, że nigdy nie będziesz chciał patrzeć na kod źródłowy jakiejś biblioteki - ale nie byłoby to pierwsze miejsce, w którym wyglądałby interfejs API i jak go używać.
Jesper
Radziłbym również, aby wszystko związane z interfejsem API przechowywać w nagłówku (lub przynajmniej w nagłówku lub źródle), ponieważ uniknęłoby to potencjalnej niespójności podczas aktualizacji dokumentacji w jednym miejscu, a nie w drugim.
jopasserat
12

Rozwiązaliśmy ten problem (około 25 lat temu), tworząc grupę # definicji (np. Publicznych, prywatnych itp., Które rozwiązały się jako <nic>), które mogłyby być użyte w pliku źródłowym i zostały przeskanowane przez skrypt awk (okropności !), aby automatycznie wygenerować pliki .h. Oznacza to, że wszystkie komentarze znajdowały się w źródle i zostały skopiowane (w stosownych przypadkach) do wygenerowanego pliku .h. Wiem, że to dość stara szkoła, ale znacznie uprościła tego rodzaju wbudowaną dokumentację.

Peter Rowell
źródło
1
hmm, wiem, że ten styl rzeczy może być przydatny, ale z mojego punktu widzenia zawsze uważałem, że tego rodzaju dokumentacja jest wręcz denerwująca ...
osirisgothra
1
Parafrazując Donalda Rumsfelda (mężczyznę, którego nie lubiłem): „Programujesz za pomocą narzędzi, które masz, a nie za pomocą narzędzi, które chciałbyś mieć”. Każdy język, z którym pracowałem przez ostatnie 40 lat miał przynajmniej jedną dużą brodawkę (jeśli nie więcej). Nasze rozwiązanie a) działało, b) używane narzędzia, które istniały w tym czasie, c) pozwalały nam spędzać czas na uzyskiwaniu kodu generującego przychody za drzwi.
Peter Rowell,
Mimo że prawdopodobnie nie wybrałbym tego, jest to interesujący sposób radzenia sobie z komentarzami w nagłówkach. Czy wygenerowane nagłówki będą miały kontrolę wersji? czy jest to jakiś proces wydawania umożliwiający redystrybucyjne źródło? (ale nieużywane przez programistów)
ideasman42
Och, ostatnio widziałem ten sam wzorzec w projekcie rozpoczętym w ≥ 2000 r. I byli bardzo dumni ze swojego sprytnego wynalazku…
5gon12eder 12.12.15
3
W naszym przypadku żaden z wygenerowanych plików nie podlegał kontroli wersji, ponieważ były one łatwo i bezpośrednio (ponownie) uzyskiwane ze śledzonych plików.
Peter Rowell,
9

Zakładając, że jest to kod w ramach większego projektu (w którym programiści często będą przemieszczać się między źródłem a nagłówkami) i pod warunkiem, że nie jest to biblioteka / oprogramowanie pośrednie, w którym inni mogą nie mieć dostępu do źródła, znalazłem to działa Najlepsza...

  • Nagłówki:
    zwięzłe komentarze linii 1-2, tylko jeśli są potrzebne.
    Czasami pomocne są również komentarze powyżej grupy powiązanych funkcji.
  • Źródło:
    Dokumentacja API bezpośrednio nad funkcją (zwykły tekst lub doksygen, jeśli wolisz) .
  • Zachowaj szczegóły implementacji, istotne tylko dla programisty modyfikującego kod w treści funkcji.

Głównym powodem tego jest trzymanie komentarzy blisko kodu. Zauważyłem, że dokumenty w nagłówkach często nie synchronizują się ze zmianami w kodzie (oczywiście nie powinny, ale zrobiły to w naszym projekcie na najmniej) . Również programiści mogą dodawać dokumentację na górze funkcji, gdy wprowadzają zmiany, nawet jeśli istnieją dokumenty nagłówkowe ... gdzie indziej. Powodowanie podwójnych poprawek lub przydatnych informacji tylko w jednym z dokumentów.

Oczywiście możesz wybrać konwencję i upewnić się, że wszyscy deweloperzy ją przestrzegają, właśnie znalazłem konwencję nadającą się najbardziej naturalnie i sprawia najmniej problemów z utrzymaniem.


Ostatni wszystkim dla dużych projektów - tam nachylenie nie dokonać drobnych korekt w nagłówku kiedy znasz jego zamiar spowodować potencjalnie 100 lub 1000 plików ponownej kompilacji, gdy inni użytkownicy aktualizują kontroli wersji - spowolnienie błędy bisecting też.

ideasman42
źródło
5

W mojej (raczej ograniczonej i stronniczej) opinii jestem zwolennikiem kodu źródłowego. Kiedy robię bity w C ++, zwykle edytuję plik nagłówka raz, a potem tak naprawdę nigdy nie wracam, aby na niego spojrzeć.

Kiedy umieszczam dokumentację w pliku źródłowym, zawsze widzę ją podczas edycji lub odczytu kodów. Myślę, że to przyzwyczajenie.

Ale to tylko ja ...

MattyD
źródło
1
Nie działa zbyt dobrze, jeśli masz tylko skompilowaną bibliotekę i plik nagłówka. W takim przypadku więcej informacji w nagłówku jest dobrą rzeczą, ponieważ jest to jedyna dokumentacja interfejsu, którą masz.
szybko_niedz.
możesz wygenerować dokumentację za pomocą doxygen - pobiera ją również z plików .c. W ten sposób można łatwo dystrybuować dokumentację za pomocą skompilowanych bibliotek. Problem polegałby jednak na tym, że IDE może parsować pliki nagłówkowe i zapewniać dokumentację podczas korzystania z funkcji ... Ale może rozwiązałoby to skrypt wdrażania, który kopiowałby komentarze funkcji z .c do .h ...
Vit Bernatik
5

Komentarze nie są dokumentacją. Dokumentacja funkcji może zwykle zawierać 2K tekstu, ewentualnie ze schematami - patrz na przykład dokumentacja funkcji w zestawie Windows SDK. Nawet jeśli Twój komentarz do dokumentu na to pozwala, kod, który zawiera komentarz, będzie nieczytelny. Jeśli chcesz stworzyć dokumentację, użyj edytora tekstu.

Neil Butterworth
źródło
aktualizacja, w dzisiejszych czasach dużo łatwiej jest udokumentować (z takimi rzeczami jak twórca Qt), aby po prostu udokumentować sposób doksygenacji (lub klonowania), na przykład w qtc nacisnąłeś klawisz / kilka razy przed komentarzem i połowę praca jest zrobiona dla ciebie. Z powodu takich rzeczy wątpię, aby ludzie chcieli przeskoczyć do edytora tekstu, aby tylko udokumentować swój kod. Zrobiłem to, oczywiście, w 2005 roku, ale nigdy tego nie zrobiłbym. Nawet użycie edytora HTML wydaje się teraz dość archaiczne.
osirisgothra
@osirisgothra Doxygen- „dokumentacja” może być łatwa do wykonania i na pewno tworzy wiele szybko napisanych LOC, ale wartość wytworzonej „dokumentacji” pozostaje sporna w zdecydowanej większości przypadków. Komentarze Doxygen nie są ani dobrą dokumentacją (prawie wszystkich istotnych szczegółów brakuje), ani też nie są dobrymi komentarzami (mają tendencję do powtarzania tego, co jest już oczywiste z podpisu). Myślę, że nbt ma rację mówiąc, że prawdziwej dokumentacji najlepiej nie mieszać z kodem, ponieważ szkodzi to czytelności kodu. Zresztą i tak się nie zsynchronizuje, nie ma na to srebrnej kuli.
cmaster
4

Jeśli interesariusze twojego kodu źródłowego (powiedzmy mała biblioteka) składają się z „użytkowników” (innych programistów, którzy będą korzystać z funkcjonalności biblioteki bez angażowania się w jej implementację) i „programistów” (ty i inni programiści, którzy wdrożą bibliotekę) , a następnie wpisz „informacje o użytkownikach” w nagłówku i „notatkę o implementacji” w źródle.

Jeśli chodzi o chęć nie zmieniania plików nagłówkowych bardziej, niż jest to absolutnie konieczne - przypuszczam, że jeśli w waszej bibliotece nie ma „szalonego strumienia zmian”, to „interfejs” i „funkcjonalność” niewiele się zmienią, i żadne jeśli komentarze nagłówka zmieniają się zbyt często. Z drugiej strony komentarze kodu źródłowego będą musiały być synchronizowane („świeże”) z kodem źródłowym.

rwong
źródło
0

Cały sens używania doxygen polega na tym, że generujesz dokumentację i udostępniasz ją gdzie indziej. Teraz cała ta dokumentacja w nagłówkach jest po prostu śmieciem, co utrudnia szybkie wykrycie wymaganej deklaracji funciton i być może jej przeciążenia. Jeden komentarz linijki jest maksymalny, który powinien tam trafić, ale nawet to jest zła praktyka. Ponieważ jeśli zmienisz dokumentację w źródle, ponownie skompilujesz to źródło i połączysz ponownie. Ale jeśli umieścisz dokumenty w nagłówku, tak naprawdę nie chcesz zmieniać tam najmniejszej rzeczy, ponieważ spowoduje to znaczną część przebudowy projektu.

Slava
źródło
1
wydaje się, że nie oferuje to nic istotnego w porównaniu z punktami przedstawionymi i wyjaśnionymi w poprzednich 7 odpowiedziach
gnat
1
@gnat z poprzednich 7 odpowiedzi tylko jedna jest za kodem przeciwko nagłówkom. I ten przedstawia zupełnie inną argumentację.
Slava