Dokumentowanie kodu źródłowego

0

Ja tak w nawiązaniu do podobnego tematu sprzed ponad roku.
Dokumentowanie kodu

To jak to w końcu jest - warto a może nie warto dokumentować kod za pomocą przeznaczonych do tego narzędzi np. JSDoc (JS), Documentation comments (C#), Javadoc (Java)? Nie pogardziłbym ciekawą analizą z punktu widzenia poważnych (nie)komercyjnych projektów i skromnych programików tworzonych w ramach samodzielnej nauki. Czy docs comments pomagają czy bardziej przeszkadzają?

W moim odczuciu takie komentarze dokumentacyjne (tak to się formalnie nazywa?) to pewna pomoc dla obcującego z kodem, ale ja jestem niedzielnym teoretykiem amatorem, dlatego wolę zapytać praktyków z doświadczeniem. Jeśli ktoś chce to może wypowiedzieć się również na temat zwykłych komentarzy, ale wiadomo - ponoć lepiej ich unikać, ponieważ kod ma być samoopisujący się itd. itp.

5

Zwolennicy kodu jako się dokumentującego (dobre nazwy itd) moim zdaniem nie w 100% maja rację, nawet dobra nazwa parametru nie (zawsze) opisuje w pełni semantykę.
Zwłąszcza w funkcjach bibliotecznych, gdzie użytkownik w 95% nie sięga do ciała metody

jednak co do kodu "otwartego" "żywego" w tym sensie, ze aktualnego dla zespołu, w znacznym stopniu mogę się z nimi zgodzić.

0

Myślałem, że rozpocznie się ciekawa dyskusja, a tu na razie cisza :P

1

Nie wiem czy warto czy nie, ale w 99% przypadków jak juz jest taka dokumentacja to nie mówi nic więcej niż wynika z sygnatury funkcji. Chyba jedyna sytuacja kiedy mi to pomaga to jak jakiś śmieszek w pythonie zrobi funkcje która przyjmuje kwargs i nie wiadomo co tam w ogóle można przekazać.

4

To zależy. Przy dobrej jakości kodu w większości przypadków wystarczy odpowiednie nazewnictwo etc. ale czasem warto dodać jakąś dokumentację techiczną w bardziej złozonym przypadku. Należy też dodać że dobre testy też są swojego rodzaju dokumentacją kodu.

4
revenger napisał(a):

To jak to w końcu jest - warto a może nie warto dokumentować kod za pomocą przeznaczonych do tego narzędzi np. JSDoc (JS)

JSDoc --> TypeScript

w sensie, że JSDoc wygląda jakby ktoś bardzo chciał mieć statyczne typowanie i potrzebę opisania każdego parametru funkcji bardziej niż sam JavaScript to umożliwia. Czyli usecase dla TypeScriptu.

2

Kodu dokumentować nie warto (w sensie pisania co każda linijka robi), ale publiczne API jakiejś klasy/modułu już tak - bo często jednak sama nazwa klasy/funkcji nie mówi wszystkiego o tym, co się stanie, ani jakie są jej ograniczenia i wymagania.

2

W takim razie jak nie bezpośrednio kodzie to w czym taką dokumentację zrobić?

Czasami warto bezpośrednio w kodzie. Ale ważniejsza jest na ogół dokumentacja biznesowa, czyli jeśli masz np. kantor walutowy (#PDK) to powinno być biznesowo opisany sposób naliczania prowizji za wymianę, jakiś limit darmowych przelewów/wymian walutowych, jak działa jakaś automatyczna wymiana walut, jakie są rodzaje przelewów etc. I to jest ważna dokumentacja ;)

1

Ja się staram stosować do zasad opisanych w rozdziale 3 "Use comments wisely" w Java by Comparison

3

Jeśli chodzi o komentarze - dawno zauważyłem, że ich nie czytam - nie widzę nawet, że są takie w kodzie. (a czasem mógłbym zaoszczędzić troche czasu, gdybym przeczytał...)
Eksperymenty (wsadzania prowokacyjnych komentarzy do kodu) pokazują, że prawie nikt nie czyta. Mózg programisty, nauczony wieloma rozczarowaniami, się sam uczy komentarze ignorować.

2

Ja dokumentuje niemal każdą linijkę kodu i to bardzo opisowo. Kiedy później np. po roku-dwóch wracam do kodu, pracuje się komfortowo vs sytuacja gdzie mamy ciurkiem kod bez żadnych wyjaśnień, i trzeba wszystko analizować.

W sytuacji kiedy produkuję dziennie po kilka tysięcy linii, nie wyobrażam sobie robienia tego w inny sposób. Wiadomo, że są schematy, nazewnictwo funkcji i zmiennych, znana struktura, etc. jednak komentarze znacznie przyspieszają poprawki w starym kodzie.

Wg. mnie warto trochę się zatrzymać, i poświęcić czas na komentarze - i to nie tylko dla czytania później, ale w trakcie do wyjaśniania samemu sobie co ja robię, taki loopback w umyśle dodatkowo dbający o jakość kodu.

Co więcej, komentując nad linią i robiąc odstęp powyżej komentarza i poniżej linii, kod staje się naturalnie bardziej przejrzysty.

0

@AnyKtokolwiek:
Zapytałem ogólnie czy jest sens tworzyć komentarze dokumentacyjne. Kontekst ogólny, dowolna technologia, po prostu robię projekt i zastanawiam się, czy opisać każdą klasę, metodę, parametr metody, interfejs...

Pierwszy lepszy przykład z Javy, bo dla C# nie potrafiłem znaleźć fajnego odpowiednika.

/**
* Returns an Image object that can then be painted on the screen. 
* The url argument must specify an absolute <a href="#{@link}">{@link URL}</a>. The name
* argument is a specifier that is relative to the url argument. 
* <p>
* This method always returns immediately, whether or not the 
* image exists. When this applet attempts to draw the image on
* the screen, the data will be loaded. The graphics primitives 
* that draw the image will incrementally paint on the screen. 
*
* @param  url  an absolute URL giving the base location of the image
* @param  name the location of the image, relative to the url argument
* @return      the image at the specified URL
* @see         Image
*/
public Image getImage(URL url, String name) {
    try {
        return getImage(new URL(url, name));
    } catch (MalformedURLException e) {
        return null;
    }
}

Bardziej rozbudowany przykład
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/io/Console.java

7

Komentarze są bardzo ważne.

6

Szczerze jeszcze nigdy nie zdarzyło mi się trafić na przydatny komentarz. Szybciej dotrę co się dzieje czytając kod niż komentarz. Opis argumentów metody to co innego, zwłaszcza w publicznej bibliotece wręcz niezbędne; nie za każdym razem zaglądam do dokumentacji, fajnie jak w takim opisie jest przykład użycia jeśli nie jest jasny i skrajne zachowania.
Tak więc jestem za opisywaniem funkcji / metod, ale przeciw komentowaniu każdej linii kodu - dobre nazewnictwo i krótkie funkcje robiące tylko to co sugeruje nazwa wystarczają. Komentarze w kodzie używam tylko jeśli coś jest naprawdę dziwne, jest użyty jakiś workaround albo api z którego się korzysta ma nieoczywiste efekty uboczne.
No i odczywistą dokumentację typu:

 @param  name   name of sth
 @param  age   age
 @return      result

można sobie odpuścić, a niestety bardzo często coś takiego widuję

Komentarze za to się czasami przydają jako zakładki - przykładowo w kodzie obecnego projektu ktoś dodał komentarz "dla Marka" - nie mam pojęcia o co chodzi i jakiego Marka, ale ten komentarz jest o 10 linii od bardzo przydatnego do debugowania miejscu i często go wyszukuję, bo nie pamiętam nazwy klasy, ani metod, za to pamiętam ten komentarz :)

Kiedyś słyszałem że zwolnili chłopa za nieczytelny kod - niestety odmówił komentarza

3

Faktycznie na frontendach JS+HTML bardzo rzadko mam jakieś komentarze bo nie ma co komentować przerzucania danych z lewa w prawo i każdy i tak siadając do takiego kodu ogólnie wie co się w nim dzieje i czego się spodziewać. Jednak w backendach gdzie mamy już głębszą styczność z logiką biznesową to czasem nawet krótki komentarz ręczny jest niezbędny.

Dla mnie podstawą są zwykłe komentarze opisujące co robi dany moduł lub funkcja oczywiście w zależności od jej złożoności. Systemy komentowania zapewne ułatwiają poruszanie się po IDE i samym kodzie ale ogólnej idei biznesowej już ze sobą nie niosą i jak po 8 latach siadamy do kodu nie pamiętając logiki biznesowej to jest klapa.
Także samodokumentujący się kod to wg mnie mrzonka... Chyba, że mówimy o jakiś banałach. W tym co robię większość rzeczy ociera się o specjalistyczną wiedzę i bez odpowiedniego komentarza kodu zwyczajnie nie da się zrozumieć, a samo zrozumienie poszczególnych funkcji i tak daje niewiele.
Przykładowo jeśli masz np. funkcję obliczającą jakąś składkę z zaokrąglaniem do pełnych 5zł to bez odpowiedniego komentarza taką funkcję można potraktować jako błąd. Wg mnie komentarz uzasadniający jej zachowanie jest niezbędny.
Natomiast w miejscach, w których zostały wykonane głębsze nieintuicyjne optymalizacje taki komentarz jest już obowiązkowy.

3

W przypadku biblioteki zewnętrznej, nad którą nie pracuję, dobra dokumentacja to podstawa. Jeśli chodzi o dokumentację kodu, nad którym pracuję, jeszcze chyba nie zdarzyło mi się pracować w projekcie, który posiadałby sensowną dokumentację. Tylko czytanie kodu+RE ;)

Co do kodu który piszę, raczej nie piszę komentarzy (z wyjątkiem sytuacji kiedy mamy coś co trudno wyrazić kodem). Raczej stawiam na małe samodzielne kawałki kodu, które można w miarę łatwo ogarnąć. Nie ma nic gorszego niż kilka tysięcy linii wzajemnie powiązanych zmiennych i wywołań funkcji (no chyba że kilkadziesiąt tysięcy powiązanych zmiennych, wywołań i goto). Wywołanie funkcji/metody powinno być jedynym sposobem wyrażenia zależności miedzy takimi kawałkami kodu. Wtedy jakoś idzie dojść co z czym się wiąże.

5

@revenger:

No co Ty, pogieło CIę? Jak udokumentujesz, to Cię zwolnią i na Twoje miejsce zatrudnią skończoną ilość studentów, bo będzie wiadomo o co chodzi w tym kodzie. Do emerytury daleko, a te młode Cię zaraz wygryzą.

5
katakrowa napisał(a):

Także samodokumentujący się kod to wg mnie mrzonka... Chyba, że mówimy o jakiś banałach. W tym co robię większość rzeczy ociera się o specjalistyczną wiedzę i bez odpowiedniego komentarza kodu zwyczajnie nie da się zrozumieć, a samo zrozumienie poszczególnych funkcji i tak daje niewiele.

Pracowałem przy projektach ze złożoną logiką biznesową i nigdy nie było takiej potrzeby, ewentualnie odniesienie do jiry która dokumentuje dokładnie zachowanie - komentarze w kodzie raczej czegoś takiego i tak nie zastąpią bo mowa o wielu dokumentach z diagramami, odtwarzanie takiej wiedzy z komentarzy w kodzie jest raczej daremne. Zresztą i to jest raczej często zbędne bo gdy jakaś logika jest niejasna to zazwyczaj wystarczy blame i wyciągnięcie jiry z treści commita. Zazwyczaj konkretną logiką zajmuje się konkretna klasa i jej zachowanie jest opisane w opisie klasy, nie ma potrzeby komentować poszczególnych linii kodu.

Przykładowo jeśli masz np. funkcję obliczającą jakąś składkę z zaokrąglaniem do pełnych 5zł to bez odpowiedniego komentarza taką funkcję można potraktować jako błąd. Wg mnie komentarz uzasadniający jej zachowanie jest niezbędny.

W podanym przykładzie funkcja może po prostu zaokrąglać, a "5" byłoby jej argumentem więc nikt nie potraktowałby czegoś takiego jako błąd, a komentarz jest zbędny. Ewentualnie nazwa funkcji może mówić że zaokrągla do pełnych piątek. Jeśli funkcja nazywa się "round" i zaokrągla domyślnie w ten sposób to rzeczywiście wtf, nawet z komentarzem w kodzie. Masz jakiś inny przykład?

** * “It should be noted that no ethically -trained software engineer would ever consent to write a DestroyBaghdad procedure.
Basic professional ethics would instead require him to write a DestroyCity procedure, to which Baghdad could be given as a parameter.” * **

― Nathaniel S. Borenstein

3

Tak przy okazji dzielenie kodu na małe kawałki / klocki zamiast monolitu oczywiście jest jak najbardziej pożądane, tylko nie bardzo zastępuje komentowanie, jak ktoś wyżej napisał.

Otóż nawet jeżeli podzieli się kod na jak najmniejsze logicznie części, to później mamy odwołania do tych części, które też wymagają komentarza.

Samo wyjaśniające się nazewnictwo zmiennych, klas, metod nie jest w stanie zawsze zastąpić komentarzy.

Co więcej komentowanie ułatwia też później zautomatyzowane budowanie dokumentacji API.

3

hacki w kodzie wypadałoby komentować

3

W mojej dotychczasowej praktyce, komentarze w kodzie wielokrotnie potrafiły mnie wprowadzić w błąd, nie przypominam sobie natomiast przypadku, żeby w czymś pomogły. Podobne zdanie mam o pisaniu javadoca do każdej możliwej metody.
Wyjątki:

  • Zewnętrzne API bibliotek - clean code tu nie wystarczy.
  • hacki, lepiej jak ich nie ma, ale jak są, to dobrze jest mieć komentarz dlaczego jakaś niepotrzebna linia się znalazła w repozytorium
  • metody / klasy o nieoczywistych wymaganiach, stałe, dlaczego jakaś stała to 2.76645, albo że 3 linie obliczeń matematycznych biorą się z jakiegoś twierdzenia/wzoru. Patrząc na sam kod, czasami ciężko się domyślić, że chodzi o twierdzenie Pitagorasa...

Ciekawostka w metodzie, gdzie Sonar zgłosił ostrzeżenie o cognitive complexity ponad miarę:
//NOSONAR If we split this method it would to be harder to read

3

Trochę bez sensu pisać komentarze do każdej linijki, wtedy w niczym nie pomogą. W takich przypadkach wywalam regexpem komentarze z całego pliku i staram się dojść do logiki na podstawie samego kodu. Otwieram wersję oryginalną obok i zaglądam tylko aby upewnić się, że komentarz nie dotyczy czegoś ważnego.

Słabe jest też duplikowanie logiki w komentarzu, bo to kod ma opisywać logikę, pisać drugi raz komentarz jest raczej bez sensu, bo wtedy przy zmianie logiki trzeba pamiętać o zmianie obu rzeczy. Pisanie komentarza jako notatkę dla siebie za 6 miesięcy też raczej warto sobie darować.

Opisywanie podejścia, albo historii podejść, albo dlaczego tak a nie inaczej, dla mnie ma duży sens. Bo jeśli ktoś spędził tydzień na researchowaniu problemu i napisał jakąś implementację, a potem przychodzi junior i chce to refactorować bo wie lepiej, to wtedy taki napisany komentarz może juniorowi oszczędzić trochę czasu ;).

0

Ok, z tą każdą linią może trochę przesadziłem.

Wklejam przykładowy kod PHP, jedna z metod:

  /**
   * Sprawdza dzisiejsze premiery i powiadamia użytkowników, musi być uruchomione w trybie CLI.
   */
  public static function checkTodayPremieres() {
    
    // Sprawdzenie trybu CLI, brak trybu CLI = koniec
    if ( !\inopx\http\CLIChecker::isCLI() ) {
      return;
    }
    
    // PDO
    $PDO = \inopx\db\ConnManager::getDefaultConnection()->getInternalHandler();
    
    // Sprawdzamy dzisiejsze premiery
    $stmt = $PDO->prepare("SELECT * FROM k3_product WHERE date_premiere IS NOT NULL AND DATE(date_premiere) = CURRENT_DATE");
    $stmt->execute();
    $allProducts = $stmt->fetchAll( \PDO::FETCH_ASSOC );
    
    // Brak premier - koniec
    if (!$allProducts || empty($allProducts)) {
      return;
    }
    
    // Iteracja po dzisiejszych premierach i powiadamianie klientów
    foreach ($allProducts as &$product) {
      
      $p = new \k3\product\K3ProductEntity( $product );
      $p->afterFetch();
      self::productHasPremiere($p);
      
    }
    
    
  }

Trochę retorycznie: chyba wygodniej czyta się coś takiego, niż napaćkane ciurkiem bez żadnego komentarza?

3

Mnie uczono, że kod ma być samo opisujący.
Komentarze dodaję w ostateczności.

8

@mlody_d i tak jest, co do co robi kod. Komentarze są ok do opisania czemu albo jak. Przykład wyżej od @TomRZ to idealny przykład jak nie pisać komentarzy. np.:

    // Brak premier - koniec
    if (!$allProducts || empty($allProducts)) {
      return;
    }

To dramat. Wystarczyło zrobić metodę czyBrakPremier() i nie trzeba by pisać komentarza. Podobnie:

    // Sprawdzamy dzisiejsze premiery
    $stmt = $PDO->prepare("SELECT * FROM k3_product WHERE date_premiere IS NOT NULL AND DATE(date_premiere) = CURRENT_DATE");
    $stmt->execute();
    $allProducts = $stmt->fetchAll( \PDO::FETCH_ASSOC );

Czemu nie zrobić metody fetchTodayPremieres()? o_o
Analogicznie to całe // Iteracja po dzisiejszych premierach i powiadamianie klientów, czemu nie ma metody notifyClientsAboutTodaysPremiers()?

0

Czemu nie zrobić metody fetchTodayPremieres()? o_o
Analogicznie to całe // Iteracja po dzisiejszych premierach i powiadamianie klientów, czemu nie ma metody notifyClientsAboutTodaysPremiers()?

Oczywiście róbmy osobną metodę dla 3 linijek kodu, i używajmy tą metodę tylko w jednym miejscu. Bardzo rozsądne. LOL

5

@TomRZ:

Oczywiście róbmy osobną metodę dla 3 linijek kodu, i używajmy tą metodę tylko w jednym miejscu. Bardzo rozsądne. LOL

A dlaczego nie? O "S" z SOLID słyszałeś?

A już mniej konfrontacyjnie:


  
  public static function checkTodayPremieresAndNotifyUsers() {

      $premieres = checkTodayPremieres();

      notifyAllUsers($premires)
    }

  }

Nie pisałem w PHP 20 lat, pewnie coś się zmieniło, ale chodzi o oddanie idei. Czy potrzebujesz jakiegokolwiek komentarza do takiej metody?

7

@TomRZ ja rozumiem że ciężko przyjąć krytykę, ale co to pokazałeś jest słabe i tyle. Możesz zamyknąc oczy i twierdzić ze tak nie jest, ale powie ci to w zasadzie każdy programista. Gdybyś kiedykolwiek miał code review albo zespól to być o tym wiedział. Powie ci to dowolna książka z serii Clean Code. Powie ci to Sonar i dowolne narzędzie do statycznej analizy kodu. Nie wierzysz? Sprawdź!
Możesz zrobić ankietę na forum z tym kodem i niech każdy oceni co o tym sądzi :)

I nie, komentarze nie są tu największym problemem. Problem to łamanie SOLIDa, mieszkanie poziomów abstrakcji (jakieś operacje biznesowe obok gołych stringów SQLowych o_O), nazwa metody checkTodayPremieres ktora w rzeczywistości zajmuje się wysyałniem notyfikacji... komentarze po polsku to tylko wisienka na torcie.

edit: żeby było jasne, to nie jest nic osobistego. Nikt nie pisze idealnego kodu i każdy z nas ma pewnie kupę komentarzy od reviewerów pod każdy pull requestem. To jest zupełnie normalne i dzięki temu człowiek się rozwija i z czasem pisze lepiej.

5

Kod samodokumentujacy to podstwa. Z drugiej strony nie wyobrażam sobie braku komentarzy dla rzeczy nieoczywistych. Przykładem dla mnie jest chociażby hak matematyczny użyty w quake do liczenia paroboli chyba. Zamiast coś liczyć matematycznie co obciążało CPU to wprowadzili jakiś współczynnik, który to robił z bardzo dużą dokładnością. Ponieważ nawet teraz nie jestem w stanie sobie przypomnieć co i jak to było to tym bardziej ani nie zrozumiałbym wagi tego haka, ani nie pamiętałbym jak działa i dlaczego.

2
TomRZ napisał(a):

Czemu nie zrobić metody fetchTodayPremieres()? o_o

Analogicznie to całe // Iteracja po dzisiejszych premierach i powiadamianie klientów, czemu nie ma metody notifyClientsAboutTodaysPremiers()?

Oczywiście róbmy osobną metodę dla 3 linijek kodu, i używajmy tą metodę tylko w jednym miejscu. Bardzo rozsądne. LOL

:D metody się tworzy głównie dla czytelności a nie z przymusu żeby móc użyć kodu w dwóch miejscach. Co więcej - im mniej użyć metod tym lepiej (poza utilsami)
Zaskoczę Cię też że np uncle bob sugeruje żeby żadna funkcja / metoda NIGDY nie była dłuższa niż 3 linijki i tak - jest to możliwe.

W Twoim kodzie mimo komentarzy nie mam pojęcia co się dzieje:

    // Iteracja po dzisiejszych premierach i powiadamianie klientów
    foreach ($allProducts as &$product) {

      $p = new \k3\product\K3ProductEntity( $product );
      $p->afterFetch();
      self::productHasPremiere($p);

która z tych trzech linijek niby "powiadamia klientów"?

0 użytkowników online, w tym zalogowanych: 0, gości: 0