Как стать автором
Обновить

Почему комментарии в коде — базовый инструмент, упрощающий поддержку и развитие проекта

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров2.9K
Всего голосов 10: ↑7 и ↓3+6
Комментарии67

Комментарии 67

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

во многих компаниях предпочитают "выразительный код" чем требовать коментирование

Потому что это работает. Вот такой вот сюрприз. Очень наивно думать, что у вас есть некая серебряная пуля (комментарии), а вокруг одни идиоты, которые не додумались.

Нет это не работает как серебряная пуля.
Оно является киллер-фичей только в комплексе. Когда определен четкий стиль кода и правила неймспейсов, раскатаны все автоматизации с проверками/форматированиями и нормально построен процесс внесения изменений. И только тогда как вишенка "выразительный код" кристализирует весь техпроцесс.

Если просто "выразительный код" то в 90% случаев получаются сложноподдерживаемые макароны.
Код "выразителен" но в моменте, а в дальнейшем проше скопипастить такой "выразительный код" чем писать с нуля.
Я такого видел не перечесть.
Выбирая между "выразительностью" коментариями, я выбираю коментарии. Если именно или/или.
Коментарии устаревают но можно хотя бы требовать держать их актуальными.
Бесконтрольные мутации же "выразительного кода" приводят к письменым формулам вызова ктклху.

В целом зависит от цели разработки и команды. Но если классика с "здесь, сейчас, плевать на будушее" с командой людей которым в целом еще больше похер,то лучше обмазывать коментариями (и писать на языке в котором сложно усложнить)

Бесконтрольные мутации же "выразительного кода" приводят к письменым формулам вызова ктклху

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

Оно является киллер-фичей

Еще раз: разработка ПО - дело прагматичное. Если что-то работает, то это применяют. Если что-то не работает, то это оставляют за бортом. Take the best, skip the rest. Но тут являются свидетели всяких тайных практик и заявляют, что только у них есть великое тайное знание, всякие киллер-фичи, а все остальные блуждают во тьме невежества. Заметьте, я снова не про комментарии говорю, а про общую картину мира "все дураки, я один Дартаньян".

Какой вариант кода лучше?

// Let's make my wife happy
var i = 0;
while (blah blah blah) ...

или:

MakeMyWifeHappy();

Первый вариант лучше.

Хотя бы видно, что он делает.

Во втором варианте можно только догадываться.

Основная проблема комментариев в коде в том, что они врут. Если они не врут сейчас, то они будут врать в будущем. Код врать не может, он делает ровно то, что в нем написано. А вот комментарий - это свободный текст, пиши, что хочешь.

Сегодня этот свободный текст рядом с функцией действительно описывает, что эта функция делает. Завтра разработчик поменял поведение функции, а на комментарий не обратил внимание. Появилось два источника правды: коммент и сам код. Иными словами, коммент начал врать. Есть ли у вас инструмент, не допускающий возникновения противоречий между кодом и комментариями к этому коду?

Аналогично обстоят дела с внешней документацией в виде вики-странички или объясняющего видосика. Как поддерживается связь между реальным кодом и тем, что написано в документации? Кто отвечает за то, чтобы обновлять эту документацию? Как он понимает, что документацию надо обновить?

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

Дада. И еще - комментарии, описывающие технический долг, кстати, можно снабжать ссылочкой на задачку по устранению этого технического долга.

Я обычно техдолг описываю сразу в //TODO: ...

По коментам согласен. Они могут быть полезны, но в современных реалиях это отдельные, особенные, исключительные случаи. Ну не считая хмл документации в секциях ///, их желательно иметь и актуализировать, тем паче при разработке либ.

Кроме коментов есть еще одна олд-скул фича в сишарпе, которая сегодня к использованию не рекомендуется. Регионы. 20 лет назад они считались хорошим тоном и маст хэв, а сегодня это код смелл.

Согласен по комментам, но добавлю еще один кейс где комменты полезны. Когда вы имеете дело с древнейшим легаси кодом, который нормально переделывать вот прям щас времени нет, но вы потратили время и хотя бы поняли что этот конкретный говно-кусок делает, вот хотя бы написать коммент про то, что вы только что поняли, это лучше чем ничего))

У легаси кода своя атмосфера ) Все течет, все меняется, и не просто быстро, а с ускорением похоже. То что 20 лет назад казалось верхом инженерной мысли и чудом смекалки - сегодня оказывается неуклюжим антипаттерном, который уже сто лет как стоило бы отрефакторить, да все времени нет.

Завтра разработчик поменял поведение функции, а на комментарий не обратил внимание.

Или: описал нужное поведение в комментарии правильно (скопировав из ТЗ), а поведение изменил неправильно.

Появилось два источника правды: коммент и сам код.

Нет. Если есть противоречие - это означает, что где-то накосячили. Правду надо найти в другом месте и привести к ней и то и то.

Есть ли у вас инструмент, не допускающий возникновения противоречий между кодом и комментариями к этому коду?

Code Review

Кроме того, аргумент 1-в-1 совпадает с наличием теста. Код поправили, а тест нет. Где источник правды - то, как тест говорит делать или то, что в коде?

Однако никто же не говорит на основании такого аргумента, что тесты не нужны.

Насчет код-ревью. Я бы сказал, что надеяться на него стоит только когда все остальные средства уже перебрали. Процесс код ревью - это дополнительный человеческий фактор. Это в самом прямом смысле ручная проверка.

Это в самом прямом смысле ручная проверка.

Разумеется. Это - высокоуровневая проверка того, что то, что мы накодили, соответствует тому, что хочется, и прочим (трудно/не)формализуемым желаниям. А текст комментария, соответственно - почти эквивалентен высокоуровневому тесту.

Сейчас, наверное, если напрячься, можно какой-нибудь ИИ для черновой проверки соответствия этому 'тесту' прикрутить.

Но вы же согласны с тем, что когда возможно, ручные проверки лучше заменять машинными? Плоть человеческая слаба, внимание рассеяно. Сегодня код-ревью у нас хорошее, завтра мы его делаем перед дэдлайном. Вы готовы поручиться за железную волю и приверженность принципам качественного кода в вашей команде в любой момент времени?

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

Но вы же согласны с тем, что когда возможно, ручные проверки лучше заменять машинными?

Да. Но это не повод отказываться от ручных проверок там, где машинные невозможны. А отказ от комментариев - это оно (такой отказ) и есть.

Да как же так? Я же привел альтернативу: отказаться от большинства комментариев, но делать следующее:

  • полагаться на нормальную спецификацию типов параметров, исключений и возвращаемых значений,

  • хорошо названные функции, отвечающие давно всем понятным принципам хорошего кода

  • автоматизированные юнит и интеграционные тесты.

Все это хорошо, но искать, что вот эти все типы и значения (латиницей, ага) соответствуют чему-то в предметной области и почему мы вообще все это делаем - без комментариев умрешь. А когда комментарии есть - можно поиском найти какое-нибудь "заполнение накладной на поставку".

Это, кстати, интересный аргумент и реальная проблема, относящаяся к вопросам поддержания глоссария. Разработчики не знают английского в достаточном объеме, а мы не хотим повышать когнитивную нагрузку. Пока я не очень понимаю, каким методом можно было бы быстро это решить.

В немецкоязычных проектах со швейцарскими коллегами мы в какой-то момент начали использовать немецкие названия и немецкие для сущностей предметной области в именах переменных и функций, чтобы у нас был воспетый в DDD Ubiquitous Language.

В русском или китайском коде это бы выглядело еще более странно.

Проблема еще в том что например я видел довольно много разрабов, которые почему-то и сами комменты любят на английском писать. Камон, ребят, комменты нужны как раз чтобы недвусмысленно въехать разрабу в то, о чем идет речь, и как можно быстрее (не тратить драгоценные секунды на перевод текста обратно на русский у себя в голове).

Код поправили, а тест нет.

А это закон какой-то, что изменение кода обязательно ведет к изменению тестов?

А это закон какой-то, что изменение кода обязательно ведет к изменению тестов?

Тот же аргумент работает и про комментарий. Вполне возможен вариант, что если код поправили, а он перестал соответствовать комментарию - то это мы поправили неправильно. А комментарий позволил нам это понять.

Кроме того, аргумент 1-в-1 совпадает с наличием теста. Код поправили, а тест нет. Где источник правды - то, как тест говорит делать или то, что в коде?

тест отличается от комментария одной важной характеристикой. Если тест не соответствует коду - он падает и требует к себе немедленного внимания. С упавшим тестом вы не сможете сделать билд. Удаление теста тоже очень хорошо видный процесс, какой-нибудь инструмент как минимум закричит. С продолбанным устаревшим комментарием вы сможете сделать билд и никто ничего не заметит. А комментарий к коду будет врать о том, что делает код.

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

Если на Code Review происходящее вдумчиво читают (ну да, лениво) - то до билда ничего даже не дойдет. Изменения не примут.

Пока что все разработчики без исключения - люди. Люди имеют свойство ошибаться, быть невнимательными (особенно в спешке, исправляя супер-срочный баг). Чем больше автоматических проверок, которые не зависят от человеческой внимательности, стоят на пути бага до продакшна - тем лучше, и наоборот.

Чем больше автоматических проверок, которые не зависят от человеческой внимательности, стоят на пути бага до продакшна - тем лучше, и наоборот.

Правильно. Но если автоматическая проверка невозможна - нужно использовать инструмент ручной проверки. Вот комментарий - такой инструмент и есть.

Как именно комментарий предоставляет инструмент ручной проверки кода? Сам код вне зависимтости от наличия комментариев должен быть настолько простым для чтения, насколько это возможно: понятные имена переменных, методов и классов, минимальное количество ветвлений и циклов, оптимальный размер методов и ограниченная вложенность кода.

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

Как именно комментарий предоставляет инструмент ручной проверки кода?

Так и проверяется - читается комментарий "Поиск подходящей заявки в соответствии с ТЗ номер, правила параграфа...", а код не соответствует этому ТЗ (ТЗ тоже читается и выясняется, что там правил добавили с прошлой версии) - то код отправляется на доработку.

Комментарий, кстати, может и не прямо к функции, а к соответствующему автоматизированному тесту.

Поиск подходящей заявки в соответствии с ТЗ номер, правила параграфа...

Всё это должно быть описано в задаче в жире (или другой системе). Пулл-реквест привязан к задаче, которая является источником правды для кода. Комментарий в коде с дублирующим текстом излишний, вся информация будет в системе контроля версий (как минимум, номер задачи в commit message).

Номер задачи - обычно там что-то довольно обширное. Комментарий что вот эта функция реализует вот конкретно эти пункты из ТЗ - сильно помогает при разборе полетов и модификации кода лет так через 10 после написания кода.

Когда на третию-четвертую линию поддержки приходит запрос 'а почему у нас система делает <что-то по мнению пользователя неправильное>" - и потом приходится сообщать "Вот тогда-то утвердили такое поведение, вот тут (тыкаешь пальцем в конкретный параграф) написано, что так и должно быть."

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

Если в задаче что-то слишком обширное, возможно следует заняться декомпозицией, чтобы привязанный к ПР/коммиту тикет был достаточно конкретным.

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

Допускаю, что в каких-то специфических ЯП, например в VBA, подход может быть оправдан, так как в них проблематично использовать систему контроля версий. Но во всех мейнстримных языках можно использовать git, где будет сохранено достаточно информации о том, с чем было связано каждое изменение конкретного файла и даже конкретной строки.

Да при чем тут Version Control с соседями. Они отлично помогают, но аргумент не про них.

Вот есть задача в жире (кстати, в какой жире? За 10 лет оно и умереть может - смотри что недавно произошло. После этого все подобные ссылки немного умирают) вида "Реализация сценария..."

В этой таске - 3-4 документа от разных лиц ну даже пусть короткие.

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

В результате ревьюверу, чтобы понять, что функция делает то, что надо - надо по всему этому прыгать и читать.

Гораздо проще, когда рядом с кодом сразу ссылка есть - что смотреть и на основании чего конкретно (а не "ищи где-то тут") оно тут написано.

И еще хуже - когда не ревьюверу надо, а как-нибудь гораздо позднее разбираемся, что тут у нас наделано и почему.

Я, кроме того, немного не понимаю аргументации. Ну вот ты прямо сейчас, поглядывая в документ с бизнес требованиями, пишешь или правишь какой-то код. Да потом еще пару раз перечитываешь и то и то, убеждаясь в том, что код требованиям соответствует. В чем проблем прямо рядом написать ссылку на конкретное место документа требований, которое ты смотришь?

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

Но нет, видимо, надо дождаться момента коммита(ов), вспомнить, какое изменение по какому поводу было, закоммитить все это по отдельности, сославшись на задачу(и). (А если достаточно подробного деления нет?). Потом, в зависимости от политики разработки, еще добиться, чтобы каждый коммит собирался и тестировался. А потом, при мерже в основную ветку, всему этому squash сделают.

И ради чего? Чтобы комментариев в коде не видеть?

Комментарий в коде с дублирующим текстом излишний, вся информация будет в системе контроля версий

Это не совсем так. В джире может быть написано сделайте красиво ограничьте размер элемента так, чтобы он не вылезал за пределы окна. В реальном же коде ничего такого не будет. А будет ахапка размеров, которые нетривиальным путём обрабатываются. А в комментарии будет написано совсем не про то, что мы не хотим вылезти за пределы окна, а о том, что в окне лежит ахапка элементов, нужно взять их размеры, определённым образом обсчитать, и потом что-то сравнить. То есть, уровень описания проблемы в джире и уровень описания проблемы в коде будет сильно разный. И никакого дублирования не будет.
(А ещё, очень не удобно по каждой строчке кода идти в гит, смотреть к какой задаче он (код) привязан, и что там написано. Банально быстрее посмотреть оставленный небольшой коммент рядом с кодом, о том зачем всё это и почему.)

Так и проверяется - читается комментарий "Поиск подходящей заявки в соответствии с ТЗ номер, правила параграфа..."

А что, если ТЗ отсутствует, как класс - что сплошь и рядом встречается в эджайл разработке? У меня, например, так и есть, ТЗ - это тикет на реализацию конкретной фичи и ссылаться больше не на что.

Кроме того, код может попросту фиксить некий баг, влияющий на сразу на множество описанного в ТЗ функционала. Например, критические данные читаются со слэйва, который может время от времени лагать, искажая самые разные результаты. На какой пункт ТЗ ссылаться?

Ссылаемся тот кусок того документа(учитываем, что документ -- понятие растяжимое), на основании данный кусок кода написан. Чтобы потом, через несколько лет, не приходилось гадать, надо оно нам тут или не надо, почему существует итд итп.

Нет, если у нас починка бага в полторы строчки - то ссылаться, разумеется, в комментариях никуда не надо - это как раз случай для описания в коммите "Исправление дефекта номер..."

Ссылаемся тот кусок того документа(учитываем, что документ -- понятие растяжимое), на основании данный кусок кода написан.

Так это как раз тикет и есть. Я о том, что ссылка на тикет фактически абсолютно универсальна - ибо при правильной организации работы изменения кода должны делаться только на основании тикета. Который уже, в свою очередь, может ссылаться и на пункты ТЗ - буде таковое в принципе существует.

Так это как раз тикет и есть

Если вся разработка нарезана на задачи-кусочки по нескольку параграфов и кроме них ничего нет- то, понятное дело, ссылаемся на тикеты. Которые в данном случае и представляются из себя "ТЗ".

...Вот только через достаточное количество лет группа поддержки этого продукта будет необычайно тормозить и ругаться, собирая по крупицам знание 'а чего делать-то хотели и почему?'.

Это как код системы вручную по diff-ам восстанавливать. Или как у законодателей - актуальные текущий тексты законов по пачке "Изменения и дополнения к.... внести изменения, дополнив пункты...". Жуть и ужас.

Если вся разработка нарезана на задачи-кусочки по нескольку параграфов

Она и должна быть так нарезана - независимо от наличия или отсутствия глобального ТЗ.

Вот только через достаточное количество лет группа поддержки этого продукта будет необычайно тормозить и ругаться, собирая по крупицам знание 'а чего делать-то хотели и почему?'.

Если тикеты пишутся в стиле "сделай мне хорошо" - то несомненно. А если включают в себя описание проблемы и её контекста (как и должно быть) - то все всё поймут.

Если тикеты пишутся в стиле "сделай мне хорошо" - то несомненно. А если включают в себя описание проблемы и её контекста (как и должно быть) - то все всё поймут.

Да как же. Они пишутся в виде "сделать, чтобы было вот так:" (что слегка логично - разработчику, чтобы сделать, большего и не нужно)

Но...потом (несколько лет спустя) происходит следующее:

Служба эксплуатации заказчика (т.е. пользователи системы - они регулярно не знают, как оно должно работать): У вас система делает А, но нам кажется, что должно быть B. Почему так и нельзя ли починить?

Я: Копаюсь в коде, который в первый раз вижу и который написан раньше, чем все текущие сотрудники проекта начали тут работать (т.е. спросить некого). Нахожу всю цепочку бизнес-логики, которые приводят к A.

(наученный опытом) смотрю в историю кода, вижу, что B уже было... дважды.. с перерывом в пару лет. После чего исправлялось.

Смотрю в историю коммитов, вижу номера тикетов в системе управления проектом, от которой уже отказались и которая давно недоступна.

Чертыхаясь, нахожу в разных архивах переписку (хорошо то как, что не в месседжерах это происходило) обсуждения, связанные с этим изменениями и сами тикеты. А еще нахожу что заменить A на B уже просили (сравнительно) недавно, но передумали.

Пишу ответ(ы) разным людям: "Поведение A было сделано на основании (прикладывается письмо). Обращаю внимание, что B уже использовалось и было сделано на основании (еще аттачи) и потом было исправлено на текущее. Уточните у ваших бизнес-аналитиков, точно ли оно является дефектом. Прошлая переписка по этому вопросу (еще аттачи) с этим не согласна". (Да, я знаю, что концелярит)

Все эти поиски - это долго. Потому и говорю, что прямо в комментариях лучше бы писать указатели, позволяющие найти ответ на вопрос 'а почему так?' максимально быстро, не прыгая по уровням ссылочности.

Вот прям апокалипсис какой-то 😁 Не осталось ни одного человека, который что-то понимает в этом коде, трэкер задач снесли, посмотреть некуда... репо хоть оставили? Или его изначально не было, код меняли руками прямо на продакшн сервере? И всю эту радость нужно теперь раскапывать в одно лицо? Но при этом есть подробное ТЗ, на которое комменты могли бы ссылаться, и штат аналитиков, которым можно задавать вопросы? Честно говоря, ситуация выглядит высосанной из пальца. А если такое и возможно, я бы просто не подписался на такую работу - можно и получше места найти.

Да где апокалипсис. Обычное такое legacy.

Практически любой код там будет, постепенно превращаясь в черный ящик, когда никто ни знает, что именно и почему оно делает.

Вопрос только в том, насколько этот момент получится отдалить и не перестанут ли его использовать до этого момента. И да, чем дальше - тем больше такого будет. Все что до настоящего момента написано - это много. Долго выводится из эксплуатации и заменяться будет.

Но вот нездоровая направленность индустрии именно на разработку нового, игнорируя стадию эксплуатации - огорчает.

А стоит ли такие исследования проводить, хочется уточнить? Разве нет тестирования и приемки, которые фиксирует необходимое состояние? В этом случае должно быть достаточно аргумента "by design". С другой стороны, сам по себе вопрос намекает, что возникли новые требования и с ними нужно работать.

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

А стоит ли такие исследования проводить, хочется уточнить? Разве нет тестирования и приемки, которые фиксирует необходимое состояние?

Есть. Вот только как среди тысяч закрытых задач и и текстов найти те, которая относится к нужной бизнес-логике? Тут же как - это логику вынесли в систему и после этого благополучно забыли, что она есть. Работает и работает.

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

Им всем контекст нужен, чтобы решить и вспомнить, почему оно такое какое есть.

Условно говоря, если в коде есть логика "По нечетным числам 13-го месяца високосного года не обслуживаем клиентов со второй буквой фамилии 'ъ'" - то это, скорее всего, как раз бизнес и аналитики так решили. Когда-то давно. И на то были причины. Но только тех причин текущие аналитики уже немного не помнят. И приходится контекст какой-то поднимать, чтобы все нашли в своих архивах, почему так. И потом уже решали - это надо менять или нет.

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

Запрос будет "у нас клиент не обслужился, нам кажется, что это неправильно". От службы эксплуатации бизнеса. Которая тоже не помнит, что и не должен.

Вы не поверите. Буквально в этом году наблюдал армагеддец. Проект закрыли, разработчики нашли другую работу. И менеджеры нашли. И тестировщики. Остался только репозитарий, джира и серверы, которые поддерживают сборку. И вот буквально неделю назад серверы погасили и передали куда-то ещё. Вопрос: если через месяцок проект решат откопать, сколько человек смогут вспомнить, как была устроена сборочная система на сервере и в итоге соберут проект из исходников? Если что, проекту было лет 15.

Проект закрыли

Мне всё же кажется, что этот пример сильно out of scope. Мы не обсуждаем способы реанимации покойников разной степени разложения, речь о наиболее эффективном способе передачи знаний в комментариях к живым долгосрочным проектам. Это важно, ибо изменения могут понадобиться через много лет, когда никто уже не помнит нюансов работы данного кода.

А в отношении описываемого случая позволю себе нескромно процитировать самого себя:

если такое и возможно, я бы просто не подписался на такую работу - можно и получше места найти

Окей, не будем про покойников. Просто приведу небольшой пример.
Есть проект хромиум. Живой? Да. Надо передавать информацию? Да. Потому что пишет его гугл, а используют все, кому не лень. Яндекс, например...
Давай заглянем в код:
https://github.com/chromium/chromium/blob/main/ui/views/window/non_client_view.h#L138

Всё подробно расписано!
И это близко к идеалу. Проект большой, есть документация, разрабатывать может кто угодно (вопросы всё равно задавать некому, т.к. разрабы где-то внутри гугла, и до них не достучаться).
В общем, комментарии должны быть.

В общем, комментарии должны быть

Да я вроде и не возражал. Сам требую, чтобы были. Вопрос в содержании - мне кажется, если требуется подробное описание, логичнее и главное, надёжнее сослаться на тикет(ы).

А что касается Open Source - это вообще отдельная песня, там свои стандарты оформления - не занимаюсь этим, поэтому не лезу и советовать не берусь.

Swagger будет всегда содержать актуальную документацию, как и если использовать, например, файл XML-документации, который будет находиться в той же директории, что и скомпилированный файл DLL или EXE. Имя файла будет соответствовать имени сборки, например MyProject.xml. XML-документация может быть использована для создания HTML-документации при помощи инструментов, таких как DocFX или Sandcastle.

xml
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile> 
</PropertyGroup>

Вот вы приводите тут пример:

 /// <summary>
/// Описание метода.
/// </summary>
/// <param name="parameter">Входной параметр.</param>
/// <returns>Возвращаемые данные.</returns>
/// <exception cref="NotImplementedException">Ошибки.</exception>
public static string GetBase(int parameter)
{
   throw new NotImplementedException();
} 

У меня на код ревью сразу к этому возникнут вопросы:

  • зачем тут нужно описание метода? У вашей функции недостаточно хорошее имя чтобы было понятно, что она делает? Переименуйте чтобы было понятно и удалите коммент. Ваша функция делает сразу миллион вещей и это все не впихнуть в название? Разбейте функцию на куски и удалите коммент.

  • зачем тут нужно описание параметра? У параметра плохое имя и не понятно, что туда передавать? Переименуйте. Тип int недостаточно хорош, и функция будет работать только с некоторыми интами? Используйте выразительные средства вашего ЯП, чтобы сузить тип. Кстати, дайте типу хорошее имя. И удалите коммент.

  • описание возращаемого значения. Абсолютно те же самые значения. Тип значения должен быть вашей документацией. Используйте алиасы, enum'ы, записи и прочие выразительные средства вашего языка программирования. Название функции должно тоже указывать на то, что же она вернет. Коммент удалите, пожалуйста.

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

  • Или может быть, вы кидаете слишком общее исключение? Создайте более частное исключение с понятным именем. Коммент лучше удалить.

Добавлю, что все эти детские ошибки разжевываются где-то в первой четверти "Чистого кода" Мартина и чуть более разреженно в "Рефакторинге" Фаулера. Книги написаны 12 и 25 лет назад соответственно. Видимо, некоторым и этого срока мало.

Реально, даже стыдно как-то это вслух проговаривать, если это не лекция по основам разработки.

Добрый день! Спасибо за дискуссию. Поясним:
п. 1-3. В статье указан простой пример и функция может быть большего размера. Да, я согласен, что имя функции должно отражать, "что я выполняю", но xml-комментарии не только помогают быстрее прочитать назначение, но и быстрее интерпретировать его на родной язык разработчиков. То же самое относится к параметрам и возвращаемым значениям. Так же с легкостью импортируются, например, в swagger или с помощью другого инструмента импорта xml-документации.
п. 4-5. Описывать ошибки — дополнительный способ защиты. Внутри его так же можно описать. Сам эксепшн по сути также создан для того, чтобы уберечь нас от неожиданных событий.

Глоссарий в коде - это и впрямь что-то, имеющее смысл. Некоторая смычка между сущностями кода и терминами предметной области поможет новому разрабу быстрее въехать в код. Бизнес-сущности не меняются так часто, как код, поэтому, наверное, в коде могут быть какие-то ссылки на проектировочные документы, которые ваши бизнес-аналитики и инженеры по требованиям поддерживают в актуальном состоянии.

На мой взгляд, при проектировании систем (не только приложений, но и сред разработки, и языков программирования, и coding conventions на проекте) нужно учитывать, что ими пользуются люди, которые обладают недостатками. Конечно, можно сказать, что если пользователь ввёл некорретный имейл, из-за которого система работает некорректно, то он сам виноват. Но хорошо спроектированное приложение должно быть устойчиво к таким ошибкам и предусматривать логику валидации и подтверждения почты, например.

Так же и с соглашениями по кодстайлу: разработчики это тоже люди, и тоже склонны ошибаться, быть невнимательными, особенно в спешке - а компилятор и кодстайл могут и должны помочь в предотвращении этих проблем.

Возьмём приведенный пример с методом парсинга: SomeValidator.TryParseInt("3"); со списком выбрасываемых исключений в xml-документации. Хорошо, если этот метод был реализован один раз и почти никогда не меняется, но что если вдруг нужно исправить срочный баг? Например, при передаче в тексте числа, выходящего за границы int32, происходит переполнение - и при фиксе бага разработчик добавил там проверку, которая может выбрасывать ArgumentOutOfRangeException. Конечно же, документацию в xml-комментах обновить забыли. Теперь доки не просто бесполезны, а даже вредны - потому что врут.

Альтернатива исключениям в бизнес-логике

Даже если бы не забыли обновить доки - как в этом случае убедиться, что все кто использует этот метод, учли новый тип исключения наряду с уже описанным ранее CustomException?

На днях пришла хорошая новость: в C# появился пропозал о добавлении Type Unions, так что теперь, надеюсь, получится написать метод так:

public static (int or ParseError) TryParseInt(string input)
{ /*...*/ }

Таким образом, уже в самой сигнатуре метода определены варианты того, что можно вернуть. При таком подходе компилятор может проверить, что вызывающий код гарантированно предусматривает вариант для каждого из возможных возвращаемых типов:

var x = result switch
{
    int a => x,
    ParseError err =>
    {
      Console.WriteLine(err.Message);
      throw new Exception("Parse failed: " + err.Message);
    }
};

И при добавлении третьей опции в сигнатуре метода этот switch просто не скомпилируется, так как не хватает третьей ветви.

Комментарии в коде, как часть системы, должны быть устойчивыми к слабостям разработчиков. А дублирование логики кода в комментарии (как в примере - список выбрасываемых исключений) - это уязвимость к человеческим ошибкам, которая может выстрелить при частых изменениях кода и недостаточном процессе код-ревью.

Я считаю, главная цель комментариев - не описывать, что делает тот или иной фрагмент кода, а для чего он предназначен, и почему он реализован именно так. Ответ на первый вопрос ("что") должен давать сам код, через понятные имена методов, классов и переменных. А информацию по другим вопросам ("для чего" и "почему") может быть намного сложнее получить из самого кода, и для них комментарии - хороший источник ответов.

Комментарий это экзоскелет. Здоровому человеку в обычной жизни он не нужен.

  • Он нужен, если человек (или код) нездоров

  • Он нужен, если нагрузка (или когнитивная нагрузка) чрезмерна и это принципиально невозможно устранить. Нечастая ситуация.

  • Во всех остальных (то есть во всех нормальных) случаях он не нужен

  • (ну правда бывает ещё автогенерируемая документация, тут метафора ломается)

  • Он нужен, если нагрузка (или когнитивная нагрузка) чрезмерна и это принципиально невозможно устранить. Нечастая ситуация.

Очень частая ситуация. Системы пишутся не для того чтобы писать, а для того, чтобы эксплуатировать. И вот есть легаси 10 летней выдержки (да даже 5 летней), которое в сумме тысячи человек много-много человеко-лет писали. И есть сейчас программисты поддержки, которых ну максимум десяток. В их мозги все весь этот код и вся это логика просто не влезет. И про починке ошибок или доработках - объяснения что тут в коде что (даже неправильные и слегка устаревшие) - сильно помогают.

Да, это бывает. Главное не путать такую ситуацию с первым пунктом)

А передачи знаний в этой системе совсем нет? Уволили 1000 человек и наняли полностью новую, которой нужно разобраться в проекте с нуля? Разве так бывает?

Уволили 1000 человек и наняли полностью новую, которой нужно разобраться в проекте с нуля?

Тысяча человек в сумме было, а не одномоментно. Но это не означает, что знания всех этих тысяч человек способно поместиться в головы тех, кто сейчас есть или тех, кто был в промежутке. Так что да, очередной новенький очень-очень значительную часть кода (приблизительно весь, что трогает, кроме скелета архитектуры) должен изучать с нуля.

Возможно никто никого не увольнял.

Пример: есть хромиум. Его пишут несколько тысяч человек, и пишут не один десяток лет. А совсем на другом конце мира другие люди должны как-то разобраться в этих гигабайтах кода. И никто никого не увольнял. И да, разобраться нужно с нуля. ( То есть, условный Яндекс, Рамблер, ВК решили написать свой браузер на базе Хромиума, наняли разрабов и... вот она полностью новая команда, которая должна разобраться в проекте с нуля. В очень большом и сложном проекте!)

Опять тёплое с мягким попутали.

Согласен с коллегами зачем нужен комментарий к функции который генерируется IDE? Она же может только то что компилятор видит написать - выкиньте его это все равно что масло-масленное писать.

Комментарий нужен к блоку кода/модулю, чтобы объяснить что происходит.

А то нагородят 100-500 мильонов файлов по файлу на класс и говорят что у нас все ясно и понятно. … а что откуда берётся и что вообще делает -сам черт ногу сломит

Мне кажется классный способ разобраться новому разработчику со старым кодом это писать на него тесты.

Хорошие комментарии это правильная штука и про комментирование основных объектов и их методов это правда, документировать стоит.

Просто по опыту бывает, что код написан непонятно, а комментарии врут. Поэтому считаю, что лучше опираться на хороший и понятный код, чем на систему комментирования, которая скорее так, может служить приятным бонусом к хорошо написанному коду

Вам стоит отделить мухи от котлет. Есть документация кода, есть документация проекта.

Документация кода - это про то, в каких случаях метод кидает какое исключение, какое значение когда возвращает, какие требования к входным параметрам. Плюс на уровне компонента - его цель, как пользоваться, многопоточный ли он и так далее.

Документация проекта - это глоссарий, описание бизнес-процессов, API, архитектуры.

Разница между ними в том, что первое читают только разработчики, второе - очень много кто, и они не хотят лезть в исходники, чтобы это увидеть.

У этих двух вещей различий больше чем общего, общее только название "документация".

Вообще хорошей документацией могут быть тесты:

  • Они помогают увидеть, как пользоваться компонентом можно, как нельзя. Посмотрел тест и пишешь свой код так же

  • Они проверяют, что код работает как описано в тестах. Такая автопроверка документации получается

  • Они заставляют разработчиков писать более понятный код и думать над тем, какие контракты у компонентов и методов

  • Они ещё и качество кода повышают, ловят баги

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий