Komentarze w kodzie – Czy i w jaki sposób je pisać?

Prawidłowe zastosowanie komentarzy jest kompensowaniem naszych błędów przy tworzeniu kodu. (…) Obecność komentarzy zawsze sygnalizuje nieporadność programisty. Musimy z nich korzystać, ponieważ nie zawsze wiemy jak wyrazić nasze intencje bez ich użycia, ale ich obecność nie jest powodem do świętowania.

Robert C. Martin – Czysty kod

Krótki cytat z jednej najbardziej popularnych książek traktujących o praktykach tworzenia dobrego oprogramowania, w dużym stopniu odzwierciedla problem jakim jest przeładowanie kodu komentarzami. Wykorzystujemy je aby uzasadnić pewnego rodzaju lenistwo, brak czasu, albo po prostu chęć pisania dużej ilości kodu, która w ostateczności okazuje się złudnym sukcesem.

// Checking if the employee should get the bonus
if ($employee->age > 65 && $employee->status === 'active') {}Code language: PHP (php)
if ($employee->isEligibleForBonus()) {}Code language: PHP (php)

Analizując powyższy przykład, możemy zauważyć, że kod wyglada zdecydowanie schludniej jeśli zamiast niejasnego warunku wykorzystamy czytelną funkcję, której sama nazwa zniweluje potrzebę tłumaczenia o co chodzi.


Błędne Komentarze

Paplanina

Nie wyjaśniaj rzeczy, które są już jasne.

Niepoprawnie
/**
 * @var Product Product object;
 */
private Product $product;

/**
 * Function returns the price that is loaded from the product object bla bla bla.
 */
public function getProductPrice() {
    return $this->product->getPrice();
}Code language: PHP (php)
Poprawnie
private Product $product;

public function getProductPrice(): int {
    return $this->product->getPrice();
}Code language: PHP (php)

Doc Blocks

Nie umieszczaj niepotrzebnych informacji w komentarzach blokowych.

Poniższy przykład kalkuluje finalną cenę, która jest wynikiem mnożenia buforu oraz wskaźnika ryzyka. Ale co dokładnie jest źle?

Niepoprawnie
/**
 * Function returns the final price.
 * @param int $a Total price.
 * @param int $b Buffer miltiplier.
 * @param int $c Risk miltiplier.
 * @return int Final price.
 */
public function getPrice($a, $b, $c) {
    return $a * $b * $c;
}Code language: PHP (php)

1. Należy wyjaśnić znaczenie argumentów funkcji, ponieważ są domyślnie niezrozumiałe.
2. Nazwa funkcji informuje o tym, że zwracana jest *jakaś* cena, a dokładne wyjaśnienie czym ona jest znajduje się w komentarzu.
3. Informujemy o typach komentarzu blokowym mając możliwość wykorzystania typów argumentów.

Poprawnie
public function getFinalPrice(int $totalPrice, int $bufferMultiplier, int $riskMultiplier): int {
  return $totalPrice * $bufferMultiplier * $riskMultiplier;
}Code language: PHP (php)

1. Poprawne nazewnictwo argumentów jednoznacznie wyjaśniło ich znaczenie.
2. Dokładna nazwa funkcji zniwelowała potrzebę wyjaśnienia działania poprzez komentarz.
3. Wykorzystanie typów również wyeliminowało potrzebę pozostawienia komentarza.

Punkt 3 zależy od projektu, ale wymaganie te musi być spełnione jeśli mamy możliwość pracy z językiem wspierającym typy i nie przejmujemy się systemami automatycznie generującymi dokumentacje.

Author

Nie informuj o autorze w komentarzu blokowym.

Niepoprawnie
/**
 * @author PH
 */
class Product {
    /**
    * @author PH
    */
    public function getPrice() {}

    /**
    * @author PH
    */
    public function getName() {}
}Code language: PHP (php)
Poprawnie
class Product {
    public function getPrice() {}

    public function getName() {}
}Code language: PHP (php)

Jak w takim wypadku poznać autora?

1. Wykorzystaj GitLens – https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens
2. Wykorzystaj git blame – https://gitbetter.substack.com/p/how-to-use-git-blame-effectively.
3. Wykorzystaj github.com / bitbucket.com aby sprawdzić kto edytował plik.

Notatki

Nie pozostawiaj w kodzie niepotrzebnych adnotacji.

// Done by Andrew
$test = '';Code language: PHP (php)

Kod

Nie pozostawiaj niepotrzebnego kodu.

// public function getPrice($a, $b, $c) {
//     return $a * $b * $c;
// }Code language: JSON / JSON with Comments (json)

Komentarze akceptowalne

TODO

Czasami dobrym pomysłem jest umieszczenie komentarzy @todo w celu poinformowania o zamierzeniach, albo ważnych elementach, które zostaną zmienione w przyszłości.

/**
 * @todo Remove when XY will be ready.
 */Code language: PHP (php)

Konsekwencje

Jeśli kod tego wymaga, umieść informacje o konsekwencjach w celu ostrzeżenia innego dewelopera.

/**
 * This function will burn your machine.
 */
public function importData(): void {}Code language: PHP (php)

Wyjaśnienia

Jeśli sytuacja tego wymaga – np. przez brak budżetu – umieść komentarz wyjaśniający istnienie danego rozwiązania.

/**
 * Function fixes the problem with FacetWP and Postfinance plugin.
 *
 * Symptoms:    The FacetWP plugin doesn’t work correctly when the Access plugin is also active. For example, if you add a custom
 *              search and try to filter by taxonomy, the FacetWP filter is ignored and a full list of posts is rendered. The issue
 *              is actually caused by the FacetWP plugin, which is running the init filter before everything else.
 *
 *              If you use FacetWP while Access is active basically all FacetWP’s AJAX-based features like search results and pagination will fail.
 *
 * Workaround:  FacetWP modifies the Main Query with additional parameters and runs another WP_Query instance to show search results.
 *              Here is a short explanation of what happens:
 *
 *              - When Toolset Access tries to check/set permissions for the Custom Post Types, it runs the toolset_access_get_current_page_id
 *                function that, in turn, runs the url_to_postid WordPress core function.
 *              - That url_to_postid function runs another WP_Query that replaces the result from the FacetWP’s query and completely breaks the
 *                results from FacetWP.
 *
 *              This happens because of the late priority of Access and the early priority of FacetWP.
 *
 * Fix:         Theme tells the plugin that the payment page is the one with `woo_postfinancecw` slug.
 *
 * @filter woocommerce_postfinancecw_is_plugin_page
 * @see https://toolset.com/errata/compatibility-issue-between-facetwp-and-access-plugins/
 */
public function fixFilters(): bool
{
  global $wp;
  return 'woo_postfinancecw' === $wp->request;
}Code language: PHP (php)

Nie znaczy to, że powinieneś umieszczać takie komentarze w każdym jednym miejscu w kodzie, które wydaje się skomplikowane. Zawsze powinieneś podchodzić do tego tematu ostrożnie wcześnie potwierdzając, że nie zostaje Ci nic innego.


Kilka reguł wystarczy, aby znacznie odchodzić kod. Najważniejsze w tym wszystkim jest to, aby rozumnie podchodzić do wykorzystania komentarzy.

Za każdym razem gdy napisałeś komentarz, przeczytaj go jeszcze raz krok po kroku czytając również kod. W wielu przypadkach w tym tekście wyłonią się od razu nazwy funkcji, na które z pewnością można rozbić skomentowaną funkcję.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.

Nasza pasja do technologii nie kończy się na dostarczaniu wnikliwych treści poprzez ten blog. Zapraszamy po więcej tajników specjalistycznej wiedzy dla entuzjastów takich jak Ty.

Tematy

animacje animate Attribute inheritance Block Theme Branża IT bug Code Comments CSS CSS Flexbox developer tools Doc Blocks dostępność www Edge Edge computing Editor Flex Gap FSE Full Site Editing GIT GIT Submodules Gutenberg HTTP HTTP/2 HTTP/3 IT JS Memcached Optimization plik SVG Praca praca w IT Rozmowy o WordPress strony www SVG Text-overflow theme.json v-model Vue.js wcag web accessibility Web development webkit line clamp Wordpress wp postmeta api wp transient