Useless коментарі до коду: які писати не варто і чому

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Вітання, мене звати Сергій Сохромов і я — проєктний менеджер в AMC Bridge. Позиція PM-а у нашій компанії означає, що я також був Senior-розробником, а відтак з власної практики знаю технічну складову розробки програмного забезпечення. За 15 років в ІТ, я бачив різний код і різні коментарі до коду, тож вважаю цю тему важливою для обговорення.

Розробка програмного забезпечення складається з багатьох кроків та етапів, що повторюються циклічно. На кожному етапі роботу планують, виконують та затверджують різні люди, що робить написання коду важливою, але не єдиною частиною створення якісного продукту. Відтак розуміти код мають не лише ті, хто його пише, а й тимлідери, технічні лідери, архітектори та проєктні менеджери.

Програмісти часто переходять з одного проєкту в інший, також стикаються з кодом, який вже хтось написав до них. І коментарі — це один з механізмів для розуміння та обслуговування коду. Тимлідери, техлідери, архітектори виконують завдання з код рев’ю і за наявності доречного та структурованого коментування в коді можуть набагато швидше та з меншими зусиллями розібратись у функціональності, перевірку якої вони роблять.

Проєктні менеджери зі свого боку відповідають за якість та наповнення фінальних артефактів, до яких належить документація до коду. Її дуже легко створити за допомогою інструментів автоматичної генерації, якщо мати коментарі до коду, що відповідають заданим стандартам.

Саме тому ця стаття буде корисною для більшості учасників розробки програмного забезпечення: розробникам, тестувальникам, технічним лідерам та проєктним менеджерам.

Для чого писати коментарі в коді

Усі, хто стикався з написанням коду і може назвати себе програмістом, з гордістю скаже: гарний код не вимагає пояснень. І я частково можу з цим погодитись, але лише в тій частині, що код і справді потрібно писати хороший.

Якщо ж подивитись правді в очі, дуже часто ми можемо бачити назви змінних на кшталт `tempVar`, назви функцій як-от `myMathFunc` тощо, що не мають жодного змісту. Це означає, що людина поза контекстом, побачивши код, витратить купу часу, щоб зрозуміти, яку функціональну частину цей код виконує. Цей код вимагатиме набагато більше часу на обслуговування. Наприклад, на виправлення функціональних дефектів або рефакторинг.

Але писати хороший код не достатньо. Є довгий перелік галузей ПЗ, що вимагають написання коментарів за замовчуванням, наприклад: публічний API (Application Programming Interface). Це як публічні інтерфейси класів, так і інтерфейс за зразком REST API та інші API, які використовують зовнішні користувачі. Такий API потребує коментарів з описом того, що API робить, які аргументи приймає, які дані повертає, які винятки генерує тощо.

Наприклад, продуктова компанія з власним R&D писатиме коментарі в коді для того, щоб обслуговувати існуючий софт було дешевше. Натомість сервісна компанія зобов’язана надавати документацію до коду, який вона розробляє, тому у цьому випадку коментарі — це мастхев як один із фінальних артефактів.

Види коментування коду

Існує чимало типів коментарів, які використовуються не лише для пояснення коду, але і для виконання певних функцій, як, наприклад, у Bash або HTML. І в цій статті я навмисно не буду заглиблюватись у тонкощі програмування з використанням певних технологій.

Ми розглянемо документаційні та пояснювальні види коментарів.

Щоразу, коли ми бачимо функцію або клас через 2 тижні відпустки або коли повертаємось до виправлення дефектів існуючої частини застосунку, ми сидимо і довго згадуємо, що ж ця функція все ж робить. Як результат, робимо висновок, що вона взагалі не потрібна і її можна видалити.

Документаційні коментарі допомагають такої проблеми уникнути. Такі види коментарів описують те, що робить функція, які аргументи приймає, що повертає, які винятки може викидати. Найчастіше використовується для АPI-класів та набору вільних функцій, що використовуються одним або кількома модулями застосунку.

Приклад документаційного коментаря ви можете побачити нижче (використовується мова програмування C++):

/*
fibonacci calculates Fibonacci series using recursion approach.

arg: n (int) - value to be calculated.

returns (int) Fibonacci series value.
*/
int fibonacci(int n) {
    if (n <= 1)
        return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

Документаційні коментарі завжди варто писати у конкретно заданому форматі, що може розпарсити IDE (Integrated Development Environment) і автоматичний генератор документації.

Пояснювальні коментарі використовуються всередині функціональних блоків і пояснюють, що відбувається в конкретних алгоритмах ПЗ. Приклад пояснювального коментаря дивіться нижче:

int fibonacci(int n) {
    //0 and 1 are seed values and equal to 0 and 1 correspondingly
    if (n <= 1)
        return n;
    //run recursion to compute Fibonacci series for the given `n`
    return fibonacci(n - 1) + fibonacci(n - 2);
}

Які коментарі варто писати, а які ні

Попри те, що коментарі в коді корисні і дають можливість збільшити продуктивність роботи над ПЗ, я все одно поділяю їх на ті, які варто писати і ті, які категорично ні.

🟢 Варто:

  • Copyright-коментарі в шапці файлів вихідного коду. Код завжди комусь належить і потрібно це вказувати.
  • Опис інтерфейсу. Інтерфейс публічного REST API, інтерфейс класу з описом публічних методів, опис глобальних констант, якщо в проєкті такі є, опис функцій. Будь-яка функціональність, яку використовують ваші колеги з команди або колеги з інших груп розробки, повинна документуватись так, щоб було зрозуміло, що роблять конкретні функція або метод.
  • Опис та пояснення алгоритмів. У випадку використання складних математичних підходів або складних механізмів розгалуження в алгоритмах вашого ПЗ, я рекомендую використовувати коментарі для пояснення кроків виконання функції, для пояснення значень за замовчуванням для перемінних та всього іншого, що допоможе розуміти код.
  • Коментарі TODO/FIXME для процесу, що йтиме після розробки — рефакторингу. Завжди бракує часу на те, щоб написати код ідеально. І часто ми робимо просто щоб працювало, та поповнюємо список технічного боргу. Окрім опису завдань у технічному боргу, я рекомендую використовувати визначені вашою командою ключеві слова для опису того, що потрібно зробити на конкретних ділянках коду.

🔴 Не варто:

  • Коментарі без змісту. Наприклад, ви пишете перед ініціалізацією змінної «Variable initialization». Цей коментар не дає жодного додаткового значення, його не варто писати. Краще опишіть значення за замовчуванням, яким ви ініціалізуєте змінну.
class Foo {
public:
    Foo() {
        //init variable !!!USELESS
        int i = 1;
    }
};
  • Дублювання коміт-повідомлень у заголовках програмного коду. Уявімо, ви робите коміт у систему контролю версій з пояснювальним коментарем «Fixed issue #1234. Removed duplicating data during an input geometry initialization» і такий самісінький коментар пишете на початку файлу програмного коду. У більшості компаній вже використовується Git, що може відображати коментарі, зміни та все інше, що стосується вашого коду. Тому не пишіть такі коментарі.
/*
* Copyright (c) Company 2022
*/

//10/7/2022 - John: Fixed issue #1234. Removed duplicating data during an input geometry initialization !!!USELESS

//STL
#include <iostream>
  • Коментарі для інших учасників проєкту. Наприклад, Джон побачив у коді магічне число у функції, яку недавно написала Шелл, і додав коментар «Shelly, do not use the magic numbers.» Є безліч засобів для ручного код рев’ю, використовуйте їх для таких цілей. Або ж просто напишіть у месенджер, що і де потрібно підправити.
double circumference(double radius) {
    //Shelly, do not use the magic numbers. !!!USELESS
    return 2 * 3.14 * radius;
}
  • Коментарі, що пояснюють імена функцій та змінних. Наприклад, змінна називається «mD». Тут краще дати таку назву змінної, що пояснюватиме її призначення, а не додавати коментар, який лише роздуває розмір програмного коду та кількість рядків, які потрібно скролити до потрібного місця.
class Foo {
    //Data of the Foo instance. !!!USELESS
    int mD = 10;
public:
    Foo() {}
};
  • Коментарі-звинувачення щодо інших, теперішніх або колишніх учасників проєкту. Не треба так. Краще додайте нотатку в техборг, виправте проблему самі або попросіть інших.
int fibonacci(int n) {
    //This is dumb approach. The `Divide and Conquer` method is more efficient !!!USELESS
    if (n <= 1)
        return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

Висновки

Все, що відбувається у світі розробки ПЗ, так чи інакше є результатом інтелектуальної діяльності. Тому рішення про те, що погано, а що добре, лягає на кожного/кожну з нас, як ланки виробництва. Кожна думка має значення, і кожна людина повинна покладатись на здоровий глузд при ухваленні рішень.

Пишіть усвідомлені коментарі з розумінням того, що ці коментарі повинні спростити життя людям, які працюватимуть після вас, а також скоротити витрати бізнесу на обслуговування коду.

👍ПодобаєтьсяСподобалось6
До обраногоВ обраному3
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Почему-то в комментариях и в статье можно сделать вывод, что todo — это то, что можно было сделать, но не было времени или просто было лень. Как насчёт того, что нельзя сделать сейчас, но, возможно, можно будет сделать в будущем? Например, у меня в коде есть немало todo, которые связаны с багами либо недоделками разных 3-rd party либ, в том числе баги конкретных версий asp.net, и в todo можно увидеть либо что-то вроде «проверить в следующей версии либы и пофиксить, если можно», либо вообще «при переходе на такую-то версию это код можно удалить, т.к. это костыль на кокретно эту версию, а в новых уже пофикшено». И действительно часть из них постепенно удаляется по мере миграции проекта на новые версии. Есть и такие, которые, возможно, будут жить вечно, потому как либо используемая библиотека больше не развивается, либо у неё сменилась лицензия и её нельзя обновить

Почему-то в комментариях и в статье можно сделать вывод, что todo — это то, что можно было сделать, но не было времени или просто было лень. Как насчёт того, что нельзя сделать сейчас, но, возможно, можно будет сделать в будущем?

Для меня — оба. Но вопрос в том, что в код имеет смысл закладывать то, в осмысленности реализации которого есть хорошая уверенность, даже если это и сильно отложено (на годы). «Хорошая» для меня это >50%.

Коментарі, що пояснюють імена функцій та змінних. Наприклад, змінна називається «mD». Тут краще дати таку назву змінної, що пояснюватиме її призначення, а не додавати коментар, який лише роздуває розмір програмного коду та кількість рядків, які потрібно скролити до потрібного місця.

class Foo {
//Data of the Foo instance. !!!USELESS
int mD = 10;
public:
Foo() {}
};

А от іноді й потрібен коментар.
Простий приклад — змінна типу int duration.
Зрозуміло, що це тривалість, але чого? У назві це не вкажеш або вона буде надто довгою.
Чи, наприклад, у чому воно вимірюється? У секундах/хвилинах?

В цьому випадку краще все ж таки змінити назву. Дуже довга назва? Можна спробувати скоротити. В чому вимірюється? Додати постфікс _sec, _min і т.д, або ж змінити тип на Duration(я хз шо це буде в с++) чи якийсь подібний.

Іноді може й потрібен, але в ідеалі не у цих прикладах.
Тривалість чого — повинно бути зрозуміло з контексту. Якщо контекст не підказує, значить він надто широкий і треба розбити клас/функцію.
У чому вимірюється — я для себе вирішив назавжди цю проблему просто додаванням суфікса. Лишні 2-3 символи durationMs, timeoutSec etc. не зіпсують назву, зате користь важко переоцінити.

У назві це не вкажеш або вона буде надто довгою

Що значить «надто довгою»? У нас раптом автокомпліт в IDE став платний, що умовно animationDurationMillis стало неможливо написати?
Особливо це смішно чути від людини, що пише на Java 😁

animationDurationMillis

Проблема такого многословного ява-спагетти в том, что его долго читать, а не писать. Хочешь — не хочешь, а при чтении кода приходится это все глазами «парсить».

Якраз якщо написати просто duration, то замість того, щоб прочитати цю назву і піти далі, доведеться стрибати по коду очима, намагаючись зрозуміти чи переконатися з контексту, чого саме це duration.

Весь секрет в контексте. Если ты в контексте функции расчета отпуска то просто duration сойдет, так как понятно, что это длительность отпуска. Даже больше — d будет ничем не хуже чем duration. Если же у тебя что-то посложней то duration может быть и маловато.

що умовно animationDurationMillis стало неможливо написати?

И потом, после рефакторинга, когда миллисекунды заменятся на просто секунды, даю 50% что имя у переменной не поменяется. Это в принципе весьма плохая привычка выносить в имя переменной единицы измерений.

Тримати штуку, яка має кілька одиниць виміру, просто в цілочисленній зміні не краще. Але з двох зол вибираємо менше

Простий приклад — змінна типу int duration

Власне, змінити тип змінної на duration, а назву — на власне те, що вимірюється. І назва не кілометрова, і призначення зрозуміле, і логіка duration інкапсульована в типі, з одиницями вимірювання не зафакапиш.

У секундах/хвилинах?

Взял за правило всегда и везде использовать миллисекунды и больше вопросов не возникает.

Код має бути зрозумілим не тільки Вам)

Естественно, я его же не для себя пишу. Но в отрасли есть вот какая проблема. Часто в проекте пишут по всему проекту типа veryLongDickCredentials, loginToVeryLongDick, VeryLongDickUser. Суть проблемы в том, что стороннему наблюдателю что VeryLongDick, что vld несет одинаковое количество информации — ноль! Даже если ему сказать, что vld это сокращение от VeryLongDick это не изменит ситуации. Если он код видит первый раз то ему это ничего не говорит. Соответственно, нет никакой причины писать по проекту VeryLongDick вместо vld.

Если же вернуться конкретно к нашему примеру, то все члены команды находящиеся в контексте проекта понимают, что везде используются миллисекунды.

все члены команды находящиеся в контексте проекта понимают

Посадили 5 обезьян в клетку, поставили посередине лестницу и на вершине лестницы положини бананы.
Каждый раз, когда какая-то обезьяна лезет за бананами их всех обливают холодной водой, что вскоре привело к тому, что обезьяны не давали залезть на лестницу другим обезьянам и били их.
Потом одну обезьяну поменяли на новую, которая про холодную воду ничего не знала, естественно, ей не дали залезть на лестницу и избили ее. Так повторилось несколько раз.
Через некоторое время в клетке не осталось обезьян, которых когда-либо обливали холодной водой, но тем не менее, когда кто-то пытался залезеть на лестницу за бананами — им не давали и избивали просто потому, что тут так принято.

К чему это я? Через некоторое время на этом проекте не останется никого, кто будет знать, из-за чего используются миллисекунды. Конкретно в данном случае это может быть не критично, но если такой же подход использовать для чего-то более сложного, то все такие решения необходимо документировать в code-guide/code-style, иначе будет беда:)

Согласен. Не всегда так получается. Особенно, где code review происходит на отвали.

Взял за правило всегда и везде использовать миллисекунды и больше вопросов не возникает.

И когда надо работать с секундами \ минутами, в результате везде стоит *1000, *60*1000 и т.п., где ошибиться в количестве 0 весьма легко — и хуже всего, это достаточно неочевидные ошибки

Всякие Duration и TimeUnit в Java здорово решают эту проблему.

всегда и везде использовать миллисекунды

Наблюдаю на экране код для таймера с частотой 14.3 МГц с измерением типовых интервалов в единицы микросекунд.

и больше вопросов не возникает.

Включил режим белой зависти.

Опис інтерфейсу. Інтерфейс публічного REST API,

Вибачте, але зараз є Open API та Swagger, для чого потрібні текстові коментарі для REST API?

А як же xml коментарі що метод приймає інт айді та повртае список ордерів? :-)

Возможно имелись в виду ’description’ поля?

Приклад документаційного коментаря ви можете побачити нижче (використовується мова програмування C++):

/*
fibonacci calculates Fibonacci series using recursion approach.

arg: n (int) — value to be calculated.

returns (int) Fibonacci series value.
*/
int fibonacci(int n) {
if (n <= 1)
return n;
return fibonacci(n — 1) + fibonacci(n — 2);
}

Хоча я дуже давно не написав на C++, але все ж таки додам пару копійок.
Коментарі потрібні до тих місць, які неочевидні для того, хто читає код.
arg: n (int) — значення для calculated. — це один із найбездумніших коментарів, тому що будь-кому зрозуміло, для чого потрібен цей аргумент.
ГАРНИМ коментарем було б написати обмеження для цього аргументу. Наприклад, що n має бути позитивним числом чи нулем.

Чи не краще тоді б було змінити сам тип аргументу на unsigned?

Загалом слушне зауваження, проте не вирішує проблеми повністю, адже це O(2^n) реалізація, тож верхня межа там теж має бути дуже близенько. Та й хоч небезпечні варіанти там і виключені, але наявність мінуса поруч з unsigned мене одразу б напружила.
Краще лінійний варіант, DP bottom up. Жодних мінусів. Це єдине, що тут варте коментаря, як на мене. Щось типу // TODO: exponential version. DO NOT USE! you’ve been warned.
Пригадую, що колись навіть реалізував O(1) варіант, коли був знайшов статтю про використання генератрис у комбінаторних задачах. Та то вже радше вправа для leetcode.
І хоч я з автором на одній хвилі, для мене це скоріше приклад як краще не робити.

Якщо це C/C++ — ой не краще.
Якщо ви викличете функцію void foo(unsigned n); з аргументом, який випадково став −1 — в функцію піде, зазвичай, 4294967295. В залежности від дії функції це може призвести до дуже неприємних наслідків.
Ставити ж assert(n>=0); в коді, що викликає, або assert(n<=INT_MAX); в коді, що викликається — це вже буде «defensive programming» і багатьма воно не просто не рекомендується, а ще й забороняється.
Да, це проблема. Я давно кажу, що за замовчуванням всі такі конверсії мають бути контрольованими на вихід за межі діапазону значень з генерацією помилки.

Та й цінність

fibonacci calculates Fibonacci series using recursion approach.

в мене особисто викликає сумніви, а надто в представленій формі, коли побіжний погляд відповідає на всі питання промовистіше за тисячі коментарів.
В самого проєкт, де часто трапляються коментарі штибу
struct A {    /**    * @brief Constructor of A    * @param Reference to B    */    A(B& b); };
Тож загалом я з автором погоджуюсь, бо мені беззмістовні коментарі лише заважають. Проте приклад обраний невдало, як на мене.

Програмісти часто переходять з одного проєкту в інший, також стикаються з кодом, який вже хтось написав до них. І коментарі — це один з механізмів для розуміння та обслуговування коду. Тимлідери, техлідери, архітектори виконують завдання з код рев’ю і за наявності доречного та структурованого коментування в коді можуть набагато швидше та з меншими зусиллями розібратись у функціональності, перевірку якої вони роблять

Це один із найбільших міфів в ІТ-індустрії.
1) Якщо автор чув про Clean Code, дві з характеристик такого коду — читабельність + компактність. Коментарі, а тим більше об’ємні коментарі збільшують обсяг коду, погано впливаючи на його читабельність, оскільки ще й доводиться перемикатися між кодом і коментарем.
2) Найбільше зло від коментарів — якщо змінюють код, мало хто змінює коментарі. Ніколи не можеш бути впевненим, що коментар актуальний та відповідає написаному коду.
3) Найкраще «роз’яснення» коду — це якраз не коментарі, а тести. Тому добре покритий код і документації особливо не потребує.

Clean Code

Це один із найбільших міфів в ІТ-індустрії.

Коментарі, а тим більше об’ємні коментарі збільшують обсяг коду, погано впливаючи на його читабельність, оскільки ще й доводиться перемикатися між кодом і коментарем.

Зазвичай до такого не доходять. А де доходять — там воно дійсно потрібно.

2) Найбільше зло від коментарів — якщо змінюють код, мало хто змінює коментарі. Ніколи не можеш бути впевненим, що коментар актуальний та відповідає написаному коду.

Тут згоден.

3) Найкраще «роз’яснення» коду — це якраз не коментарі, а тести. Тому добре покритий код і документації особливо не потребує.

У світі рожевих поні перекладань даних з бази через HTTP+JSON в веб — да.

Там, де треба пояснити, чому саме для обчислень був вибраний (умовно) RK6 при alpha=0.385 — ні.

Днями використав композицію гіперболічного тангенса та полінома. Якщо саму композицію ще можна через graph калькулятор збагнути, то от коефіцієнти вже дзуськи. Без коментарів макітру можна довго чухати.
Інший приклад з проєкту. Кінцеві автомати. Хай якими пиши їх на таблицях переходів наочними, а вони однаково краще сприймаються графом. Тому все одно робиш стейт діаграми на Конфлюенсі й в коді на них посилаєшся.
Мій досвід про «документування кодом» свідчить, що це залежить від проєкту та домену. А подекуди й мови. Бо в плюсах буває коментую те, що в тому ж Гаскелі коментувати навіть на думку б не спало. Єдине певно з чим погоджусь, що краще взагалі без коментаря, ніж коментар беззмістовний, який не має цінності

Якщо код «не дуже», а це дуже часто так, то коментарі todo/fixme нічого не вирішують окрім чергового нагадування, що код «не дуже». Якщо код «більш менш», то поява todo то є червоний прапор кенсельнути зміну.

імхо, коментарі мають сенс лише для пояснення неочевидного рішення для покриття якогось едж-кейса. в усіх інших випадаках — толкові імена, декомпозиція, тікети в джирі, статична типізація та детальний опис в юніт-тестах.

TODO в коді — то як свічечку поставити за упокой:
> TODO: ***
> 7 years ago

TODO в коді — то як свічечку поставити за упокой:

Якраз тікети легше втратити, особливо коли код кожні кілька років передається до іншої команди (може навіть в іншу країну).

А ці TODO, да, можуть вибухнути і через 20 років, коли дійде черга до цього місця — і тоді краще одразу побачити «тут недосконала реалізація» від першого розробника, ніж вираховувати це після.

На TODO чи FIXME майже ніколи не звертають увагу, іноді код може бути пофіксаний, але TODO залишається або просто воно так висить роками і кожен такий морозиться від того, бо то ж не його скоуп і взагалі. Якщо тікет буде лежать так довго часу, що зміниться команда то краще не заводити тікет)

На TODO чи FIXME майже ніколи не звертають увагу, іноді код може бути пофіксаний, але TODO залишається або просто воно так висить роками і кожен такий морозиться від того, бо то ж не його скоуп і взагалі.

Якщо у вас такі проблеми з TODO мітками, то у вас проблеми з якістю роботи взагалі. Скоріш за все, на чистку/прибирання рудіментів/техборга/etc. не виділяють навіть 5%.

Я надам перевагу варіанту де висіть TODO, устаріле на три роки, але це легко прочитати, ніж коли його взагалі нема і замість того щоб прочитати «TODO inefficient method, uses O(N^3), reconsider it» — вдумуватись знову в код в самісінькі деталі, щоб отримати той же висновок, але втратою робочого тижня.

arg: n (int) — value to be calculated.

Ну так обзовите уже прямо так эту переменную — calculatedValue, и не надо никаких комментариев.

Скорее всего это коммент для чего-нить вроде doxygen. Ну и... честно для меня n куда понятнее, а value to be calculated скорее даже ошибочно, комент ради комента.

Детский сад. В проекте сложнее хелловорлда, целыми параграфами в комментах пишется дока, что делает код с точки зрения бизнеса. И упаси боже кому то уйти в рассинхрон с докой которую ведут отдельные спецы на проекте.

Зараз у коменти понабіжуть люди (вже є декілька) які будуть розповідати що треба писати тільки чистенький-гарненький код якій коментів не потребує. У якомусь пет-проекті у вакуумі воно, напевно, так і є. Але, наприклад, у кривавому ентерпрайзі де кодова база розвивається поколіннями девелоперів, а вимоги можуть змінюватися раптом і на вчора, без коментів буде дуже важко. Також всілякі TODO теж мають право на життя бо нормальний фікс може потребувати більше часу ніж бізнес дозволяє витратити.

В ентерпрайзі часто навіть звичайної доки немає, а коментарі вже пережели 20 рефакторінгів. Якраз там коментарі і нафіг не впали, я там останні 8 років працював і взагалі вважаю що в коді має бути лише код. Бо саме код пишеться для людей, текстом, додатковий текст не допомагає зовсім, особливо оті дурні тудушки. Джири та конфлюенса мало? Коментарі живуть своїм життям і їх ніхто не читає бо все одно без дебагу та колег, що вже знають, ради не даси на великому проєкті.

У кровавому ентерпрайзі, черговий девелопер, при вирішенні задачі хєр заб’є на черговий туду крик розробника, який звільнився 10 років тому. Коментар, який завжди є безконтекстним потоком свідомості, на який і час не треба витрачати.

Вважаю TODO/FIXME коментарі злом. На кожне покращення має бути таска в беклозі. Інакше такі коментарі просто засмічують проект. Я розумію що для розробника, який зробив каку, це таке психологічне розвантаження, що він написав тудушку і значить «зробив все що міг». Але для продукта та команди це тільки шкодить.

По такой логике, в коде вообще не должно быть комментариев а вся документация должна быть в Вики.

По перше документація та TODOшки це зовсім різні речі, зовсім різні процеси.
По друге документація в коді не завжди гарна ідея і в більшості випадків так, документація або її більша частина має бути в Вікі.

Коментарі потрібні в рідкісних випадках для пояснення дуже не очевидних кроків в коді, наприклад багфікс якогось дуже не очевидного бага. Або, наприклад якщо це якась бібліотека в якої юзери — це інші девелопери, там є сенс в коді тримати якийсь док.

По друге документація в коді не завжди гарна ідея і в більшості випадків так, документація або її більша частина має бути в Вікі.

Ну... припустимо я відкриваю код, припустимо виникають деякі питання. Означає це, що мені треба перечитувати wiki? А чи є доступ для Wiki, бо кодова база може нам не належати?

Як на мене Wiki більше для загальних речей. Якщо є щось, що цікаво лише розробникам, та прив’язано до певних рядків, то я не впевнений, що треба робити сторінку у Wiki, бо їх зазвичай важко структурувати, важко шукати, важко взагалі зрозуміти, чи є воно, чи немає...

Сьогодні беклог є, завтра його немає. А код є завжди. Плюс до тасків по TODO/FIXME зазвичай відносяться як до «працює, не чіпай». Тому ніхто і не чіпає. При цьому якщо TODO/FIXME є прямо у коді, то це одразу видно і завжди спонукає це почистити. ПЛЮС, якщо я працюю над участком коду, і бачу TODO/FIXME який я можу виправити бо маю час, то я це просто зроблю. А з красивою тасочкою в джирі я про TODO ніколи і не дізнаюсь.

Коротше ніякого зла немає, і це не моє імхо, це факт. Створити тасочку, додати лінк на неї до TODO, при цьому трохи описавши TODO в коді і, якщо треба, більш детально в тасці — ось це все святе правило.

При цьому якщо TODO/FIXME є прямо у коді, то це одразу видно і завжди спонукає це почистити.

Нажаль роки досвіду з різними великими проектами кажуть мені зовсім про інше. TODO/FIXME ніхто не чіпає, бо боїться щось зламати а в скоуп їхної таски це не входить. І через роки проект наповнюється цими тудушками, які застарівають і єдине що залишається з ними зробити це видалити. Тоді як таска в беклозі це прописаний action item який можна запланувати, взяти в спринт і зробити. У таски є приорітет, є відповідальний, вона проходить процес рев’ю.

Коротше ніякого зла немає, і це не моє імхо, це факт

Це чисто імхо, ніякого факту я тут не бачу. Може на проектах де зовсім немає чого робити, тудушки і працюють, але коли є навантаження,є дедлайни — тудушки цілком програшний варіант.

Якщо у компанії вічний потік, то:
а) є проблеми
б) на таски з припискою todo точно буде всім начхати
І це не імхо, це практика 🙂
А щоб нічого не зламалось, є тести
Ну і так, це лиш моя призма фронтендера. Може десь інакше. Співчуваю.

Якщо у компанії вічний потік, то:

Завжди є робота, компанія розвивається і вас скоріш за все не виженуть на мороз ))

б) на таски з припискою todo точно буде всім начхати

Якщо в них є пріорітет і команда має капасіті на тех депт, то таски будуть зроблені. Або, якщо вони не пріорітетні то може і не треба їх робити.

А щоб нічого не зламалось, є тести

В великих розподілених системах нажаль на 100% сподіватись на тести не можна

Завжди є робота, компанія розвивається і вас скоріш за все не виженуть на мороз

Ну я ж не про те що роботи немає, я про те що має бути час не тільки на кодінг-реліз-кодінг-реліз :)

Якщо в них є пріорітет

Ну от хібащо якщо так) Але мій досвід в одній галерці показав що й приорітет не приорітет коли «замовник хоче» :с

Я згоден з вами якщо казати про щось велике, на таке звичайно потрібні таски й тудушки в коді навіть хз куди ставити. Насправді я більше казав про щось не настільки значуще як ви описуєте. Скоріш про якість архітектурні аспекти реалізації, або просто оптимізації, коли і так працює, і працює норм, але «якщо хтось добереться до цього коду, то заодно по можливості подумай та перепиши». Імхо робити тудушки на умовний перепис апішки мікросервісу на який пов’язано купа всього, і ще й немає тестів, це діч

Ну це теж гарне питання, якщо тудушка це щось маленьке, не складне, то мабуть краще не відкладати це на потім а зробити прям зараз )

Нуу, як ми тільки-но обговорювали, робота іноді і справді кипить))

Цілком згодний про зло. Я зазвичай додаю в коментар айді таски, яку до цього завів як тех борг. Якщо цей борг навряд чи хто буде робити — не варто навіть його заводити. Ще варіант — описати що робить код (якщо підхід чомусь не ок), а не писати, що треба пофіксити — у такому разі таску, при бажанні, можна завести в майбутньому.

Ну... припустимо я читаю код, знахожу щось дивне. Мені треба перечитувати увесь беклог, щоб знайти причину? TODO/FIXME пишуться для тих, кто читає код. А де там беклог та що й ньому є... то часто сакральні знання

fibonacci calculates Fibonacci series using recursion approach.

calculates the n-th element of the Fibonacci series using the recursion approach. fibonacci(0) = 0, fibinacci(1) = 1.

По перше, незрозуіло що таке взагалі обчисленя послідовності Фіббоначчі. Функція обчислює лише елемент послідовності n. По-друге, нумерація елементів потребує уточнення, бо це залежить від автора.

arg: n (int) — value to be calculated.

З цього коментаря мені взагалі нічого не зрозуміло, чому саме значення, яке має бути обчислено, передається у якості параметру? Треба написати, що це номер елементу в послідовності.

//This is dumb approach. The `Divide and Conquer` method is more efficient !!!USELESS

Просто треба перефразувати на щось більш політкоректне:

TODO: The following code is not effective, loop is a better solution.

Ну а взагалі навіть корисні коментарі виглядають у цьому кейзі USELESS, бо це лише вода для галочки. Слово fibonacchi дало мені набагато більше інформації, ніж коментарі, які все лише заплутують.

Існує чимало типів коментарів, які використовуються не лише для пояснення коду, але і для виконання певних функцій, як, наприклад, у Bash або HTML.

Пацаны, автор думает, что bash не настоящий язык программирования!

Лично читал и даже чуть дорабатывал код на bash, где реализовывалась объектная модель и даже с виртуальными функциями.

Выглядело страшно. Работало.

В rc.d з freebsd теж угорають по таким речам — там теж зробили своєрідне успадкування з можливістю перегрузки функцій. Як на мене, виглядає (і працює) досить приємно, явно краще ніж в init.d де зазвичай всі копіпастять template.

дуже часто ми можемо бачити назви змінних на кшталт `tempVar`, назви функцій як-от `myMathFunc`

Треба не коментарі писати до такого коду, а виправляти його під час ревю до того як він замерджений.

Коментарі TODO/FIXME

Краще завести Jira тікет на проблему в коді. Варто заборонити такі коменти без номера тікета. Правду кажучи, залишати коментар після створення тікета далеко не завжди треба

Що функція приймає, що повертає має відображатися в типі функції. А система типів мови — має дозволяти все це описати. Бо всі ці коментарі страждають від того самого, що і myMathFunc — і в коменті і в назві функції можно написати що завгодно, компілятору пофіг. Він ніколи не перевірить, чи співпадає коментар з тим що написали, чи там все вже давно переписали а комент не оновили.

Для складних алгоритмів — посилання на wikipedia, whitepaper, сторінку в confluence і т. ін.

Для бізнес логіки — доменна модель або DSL, щоб код читався вже в термінах бізнес логіки.

А система типів мови — має дозволяти все це описати.

javascript, php, python такого не мають

Для javascript є TS. Там система типів досить потужна та дозволяє всякі вибрики описувати.
Для php та python нічого настільки продвинутого здається немає.
Але коментарі тут — не дуже рішають. Їх крмпілятор не читає. Єдина надія на щільне покриття тестами (яке майже ніде не буває повним). Саме тому я мігрував з мов з динамічною типізацією на статичну. Бо задовдався коли після якогось простого рефакторингу баги у рідко вживаних гілках можуть вилазити у проді через тижні.

Все правильно. Якщо коментарі тільки дублюють код — вони сміття, яке ще й потребує підтримки і яке часто перестає відповідати коду.
Терпіти не можу, коли в проекті тобі починають розповідати, що на всі методи повинен бути джавадок, бо в нас «конвеншни», «так треба» і т.п.

кожна людина повинна покладатись на здоровий глузд при ухваленні рішень

Це те, чого часто не вистачає.
Код треба писати так, щоб коментарі були не потрібні. І лише коли вже без них ніяк, то можна додати пояснення до деталей алгоритму чи пов’язаного неявного бізнес-обмеження/вимоги.

Вот интересно, кто читает эти джавадок?

це корисно коли генерується API swagger-ом: користувачі апі не мають доступу до коду.
в простих випадках REST/CRUD це може і зайве, але в великих легасі проектах з мішаниною підходів до апі — це дуже бажано, особливо коли вендори/аутсорсери часто зміюються

Якщо вже пишете TODO в коді то залишайте посилання на задачу де збираєтесь це виправити, а ще краще ім’я фахівця (своє або посилання на Git-профіль), який відповідальний за виправлення

Залишати ім’я фахівця — погана практика. Вона працює лише доти, поки цей фахівець не піде з компанії чи змінить команду.

Якщо вже без TODO не обійтись, то краще залишати посилання на задачу, а ім’я фахівця можна завжди витягти з історії змін файлу

а я прихильник думки що коментарі не потрібні взагалі — приклад тут www.youtube.com/...​ab_channel=InfallibleCode

Не очікував зустріти однодумця в цьому жорстокому світі любителів надлишкових коментарів.

Нас таких багато, насправді. Бо колі і справді багато досвіду розумієш що код і є читабельна для людини інструкція або задекларована логіка для компьютера. Навіщо засмічювати коментарями іще додатково? Окрім згаданих вище дуже хитрих багів чи костилів котрі хавжди хочеться виправити або видалити.

Конечно никому не упали всратые комментарии что метод возвращает инт, а принимает лист.

За це взагалі трба одразу по рукам бити. Мене вразило коли одна команда любила такий мотлох і ніяк не можна було їх переконати, аргументів також не надали, просто їм так удобно і подобається :-)

Підписатись на коментарі