нужны ли комментарии в коде
Почему [не]нужно комментировать код
В последнее время, набирает популярность мысль, что комментарии в коде — дело не обязательное, и даже вредное. Буквально вчера вечером, общаясь со знакомым молодым программистом, попросившим посмотреть его код, я обнаружил, что комменты отсутствовали вовсе, даже привычные описания методов. На мой удивленный смайлик, был ответ: “Комментарии — первый признак плохого кода”. И черт бы с ним, с начинающим программистом, но я периодически читаю что-то похожее в блогах, и слышу от коллег. Может программирование в очередной раз сделало шаг вперед, а я, среди отстающих? Под катом, немного размышлений, о том, когда и почему стоит или не стоит комментировать свой код.
Итак, есть два основных утверждения против комментов в коде:
Утверждение 1: “Код — сам себе лучшая документация”.
Или более радикальное “Комментарии — первый признак плохого кода”.
В принципе, мысль верная, код должен быть чистым. А чистый код в комментариях не нуждается, он и так понятен. Если у вас возникло желание, объяснить посредством комментария, что означает данная переменная — может лучше переименовать ее так, что бы это стало понятно из названия? Если вам кажется что алгоритм метода немного запутан, может вместо того, что бы писать комментарий, стоит переписать алгоритм, сделав его более понятным и логичным?
К сожалению, в реальной жизни, не всегда получается выдавать красивый и логичный код. Иногда не хватает времени на качественный рефакторинг, и просто пишешь как можешь. Иногда сама бизнес-логика настолько запутана, что без 100 грамм ее не реализуешь. А когда реализуешь, хочется забыть об этой задаче и, на всякий случай, принять душ, раз пять. А иногда, то, что вам кажется красивым и логичным, может вызвать затруднения у ваших коллег.
Так может ли код быть самому себе лучшей документацией? Конечно может, но для уверенности, не бойтесь вставить лишнюю строчку комментария, или хотя бы сделать отсылку на используемый паттерн. Возможно, в будущем, это сэкономит кому-то немного времени.
Утверждение 2: “Комментарии могут устареть”.
Имеется в виду, что комментарии, могут в какой-то момент перестать соответствовать коду. Например, вы написали некий метод, в теле которого оставили немало комментариев, ибо, согласно предыдущему абзацу, хотите сэкономить время своим коллегам. Через пол года ваш коллега, изменил метод, но впопыхах, или по неосмотрительности, забыл поправить комментарии. А еще через пол года, ваш другой коллега, потерял немало времени, ибо был введен в заблуждение неактуальными комментариями.
Проблема не надуманна, я, например, не раз встречал комменты, которые не соответствуют коду… да чего там… я и сам, бывало, забывал переписывать комментарии. Проблема есть, но не думаю, что исключить комментарии вообще — лучшее решение. Просто надо быть внимательным, и не забывать исправлять комментарии при исправлении кода.
Почему?
Поймите меня правильно, я не агитирую за комментирование каждой строчки. Более того, я и сам считаю комментарии в стиле:
признаком плохого кода. Комментарии не должны дублировать код! Они должны дополнять его!
Мне нравится когда комментарии отвечают на вопрос “Почему?”, а не “Как?”. Такие комментарии, действительно не раз сэкономили бы мне время. Бывает, смотришь на чужой код, и в голове мысль “Почему так? Можно же проще!”, а через пол часа понимаешь, что да, именно так. Проще не получится. Программируя, мы часто натыкаемся на различные подводные камни, которые тем или иным образом влияют на наш код. Если вы выбираете не самое очевидное и простое решение — не поленитесь описать почему вы так поступили.
Комментарии в коде — полезные, бессмысленные, вредные?
Как-то проглядывая код некоторых старых модулей, вновь подумал о роли комментариев. Вопрос хоть и тривиальный и обсужденный миллионы раз в книгах, блогах, статьях и форумах, а все-таки подчас задевает за живое. При этом, о пользе комментариев пишут гораздо чаще, чем о их вреде.
Поэтому я выскажу несколько немного провокационных утверждений, затем попробую подкрепить их примерами. Посмотрим что получится. Написанное относится как к (Java) Doc, так и к обычным комментариям в коде.
1. Комментарий может быть полезным, бессмысленным или вредным.
2. Если комментарий не несет явно видимой пользы, то он скорее всего вреден.
3. Комментарии бесполезны / вредны чаще, чем кажется. Отсутствие комментария лучше, чем бесполезный комментарий.
4. Перед тем, как написать комментарий — подумайте дважды, а может не стоит? 🙂 (5. После того, как вы решили, что комментарий все-таки не нужен, посмотрите трижды — а код точно кристалльно понятен?:))
Про полезные комментарии все ясно. Когда:
— достаточно прочитать 6 строк комментария вместо 80 строк кода метода с бизнес-логикой
— в комментарии дается ссылка на реализуемый малоизвестный алгоритм или структуру данных (например — «для поиска подстроки используется алгоритм Ахо — Корасик», ссылка на википедию или спец. сайт)
— комментарий поясняет, почему автор использует не тот подход, который читающий код скорее всего ожидает тут увидеть (например, написанный руками SQL запрос вместо работы через ORM фреймворк, или почему для поиска в XML используется regexp, а не XPath)
— в комментарии дан короткий ясный пример использования (особенно, если это какой-нибудь custom Ant task или что-то подобное),
то это почти наверняка полезный, а подчас необходимый комментарий.
А теперь посмотрим на некоторый другой часто встречающийся пример.
Такой комментарий обычно создается IDE по умолчанию при генерации геттеров-сеттеров для поля объекта (в свой очередь, если бы в Java были свойства, и необходимые синтетические методы генерились компилятором прозрачно для программиста, этой проблемы бы тоже не было :)).
Комментарий, очевидно, не нужен. Ничего нетривиального в коде нет, комментарий по сути дублирует код. Кроме того — комментарий здесь занимает три строки в редакторе кода. Т.е. ровно столько же, сколько и сам код. Мало того что сам код, по сути, синтетический, + из-за Java Code Conventions растягивается три строчки ради удобочитаемости, так еще и комментарий отъедает место.
Java и так маловыразительный язык (с точки зрения среднего количества полезных действия на строку кода) по сравнению с, например, Ruby или Groovy, так зачем тратить экранное место под лишние комментарии.
Тут, конечно, есть тонкий момент. Если код с подобными комментариями — это часть public API какой нибудь generic библиотеки, и никто из пользующихся ей программистов почти никогда не смотрит ее исходники, а смотрит Javadoc — тогда это еще нормально. Но если этот код находится в каком нибудь модуле, разработываемом нами, и исходники этого класса смотрят чаще, чем документацию к нему (что почти всегда верно) — тогда это ИМХО, тот случай, когда правило «любой элемент API должен иметь комментарий» должно применяться с большой осторожностью.
Рассмотренный пример часто дополнительно ухудшается тем, что в комментарий запихиваются теги param, return, которые часто полезной информации не несут, а вот место съедают. Например:
/**
*
* Some description.
* param paramName1 paramName1
* param paramName2 paramName2
* param paramName3 paramName3
* return the name of user
*/
public String getUserName(String paramName1, int paramName2, int paramName2) <
/* какой то простой прямолинейный код*/
>
(Забавно, что часто в коде есть такие бессмысленные комментарии, а в реально сложных частях комментариев мало :))
И напоследок еще пример.
// Временный хак, т.к. возможность сделать нормально сейчас не поддерживается,
// а сделать надо срочно. По совету [senior developer name], хакнул так.
// 21/04/2004, [developer name].
В некоторых примерах я частично утрирую, но общая идея от этого не меняется.
Updated:
По просьбам в комментах, даю ссылку на пару книг, которые полезно прочитать любому программисту, чтобы не писать таких комментариев (и не делать многих других ошибок)
Неужели комментировать код — это плохо?
Sep 3, 2018 · 4 min read
Что такое комментарий?
Комментарий — это строка в исходном коде, которую могут прочесть разработчики, но которая игнорируется компиляторами и интерпретаторами.
Какой в нем смысл?
Как правило, «прочесть» код достаточно трудно. А поясняющий текст помогает разработчикам «объяснить» написанное тому, кто займется поддержкой кода в дальнейшем.
Нужны доказательства? Возьмем вот этот код без комментариев:
Этот блок кода выполняет несколько функций. Результат: программисты не могут быстро понять, что же именно делает данный код.
А теперь снабдим тот же код комментариями.
Разве читабельность кода не возросла? Все потому, что комментарии описывают то, что делает код, в то время, как сам код показывает, как это делается.
Мы же, разработчики, привыкли мыслить критериями «что», забывая про «как».
Так, получается, что комментарии объясняют наш код?
Звучит не плохо …
Так и есть. Но пояснять код можно разными способами. И комментирование является самым худшим из них.
Почему же комментирование стало «самым худшим»?
Причин для этого сразу несколько. Для начала, нет никакой гарантии того, что кто-то прочтет ваши комментарии. На практике, мало кто из разработчиков обращает на них внимание. Посмотрите на этот скрин Webstorm. В изначальной цветовой гамме комментарии выделяются серым и совершенно непримечательным цветом:
Так почему бы не завести блог с названием «Пожалуйста, читайте комментарии»?
Хороший вопрос! Потому что нельзя верить комментариям, которые вы читаете.
Вашим источником истины будет служить исполняемый код, который вы сами пишите. Мы знаем, что код истинен, т.к. действительно выполняем его. Комментарии — это альтернативный источник истины, но гарантия его истинности как таковой у нас отсутствует.
Как и в любой другой системе с несколькими источниками истины, разработчик может обновить один код, но забыть о другом. Можете ли вы, положа руку на сердце, сказать, что при корректировке кода вы действительно вчитываетесь во все комментарии и следите за их корректностью?
Конечно же, нет, это часто забывается.
Вот именно. Так что делайте так, чтобы в ваших системах присутствовал лишь один источник истины.
Хорошо, признаю, комментарии — это не самое правильное решение. Но ничто не идеально в этом мире. Так вы говорите, что есть вариант получше?
Да. Покажите мне ваш комментарий, и я предложу вариант получше.
А как насчет комментариев с описанием переменных? Вы говорите, что лучше не прибегать к ним для создания пояснений по переменным?
Описание того, что делают переменные, — штука крайне важная. Поэтому мы присваиваем переменным имена. Если назначить переменной осмысленное имя, то необходимость в комментариях отпадет. А еще лучше в каждых местах использования переменной пояснять в коде ее назначение. Тогда мейнтейнеру не придется отрываться от чтения кода, для поиска конкретного куска с объяснением переменной. Посмотрите, насколько лучше выглядит второй код.
Такой принцип применим и к функциям, не так ли?
Да. Присвойте функциям и параметрам имена на основании их назначения. Как только это сделано, необходимость в комментировании стиля заголовка функции отпадет сразу.
А что насчет предыдущего кода? Там комментарии описывали блоки кода, совместно обеспечивающие его функциональность? Одно именование нам явно не поможет, разве нет?
Нет, оно как раз нам поможет. Несколько строк кода с совместным выполнением определенного действия можно вывести в правильно поименованную функцию. Взгляните сюда:
Видите, как этот код выведен в функцию, которая описывает свое назначение? То же распространяется и на статичный код. К нему не требуется дальнейшего пояснения; код делает то, что написано.
Еще один плюс от использования функции в данном примере заключается в том, что все лишние детали скрыты. Мейнтейнеру не придется беспокоиться о том, как работают функции, не относящиеся к отдельно взятому изменению в коде. И так код становится удобнее для понимания.
Кроме того, мейнтейнер не проигнорирует имя функции, тогда как про комментарий он может и забыть. Имя функции уже является составляющей кода. Поэтому при прочтении всего кода прочтется и имя, и вызов функции.
А вдруг мне придется хорошенько потрудиться над оптимизацией какого-то кода. Можно ли тогда обратиться к комментариям?
Стоп… что?
Мы — разработчики программных продуктов. И у всех разработчиков есть инструменты. Комментарии — это те же самые инструменты, что и функции с именами переменных. Но ни одно средство не решает все проблемы сразу. И одного инструмента всегда мало. Если изменение структуры кода не улучшает его читабельность, то стоит вспомнить про комментарии.
Так комментарии — это хорошо?
Нет, комментарии — отстой! Большая часть комментариев, которые я встречал на практике, — никуда не годится. В основном, комментарии используют, чтобы извиниться за:
· неправильное именование переменных или функций.
· сложность или длину кода.
Утверждение о том, что комментарии — это плохо, не является истиной в последней инстанции. Скорее, это сугубо практическое наблюдение. Но и для комментариев есть редкие случаи подходящего использования.
Лучшие практики написания комментариев к коду
Известный профессор МТИ Гарольд Абельсон сказал: «Программы нужно писать для того, чтобы их читали люди, и лишь случайно — чтобы их исполняли машины». Хотя он намеренно преуменьшил важность исполнения кода, однако подчёркивает, что у программ две важные аудитории. Компиляторы и интерпретаторы игнорируют комментарии и с одинаковой лёгкостью воспринимают все синтаксически корректные программы. У людей всё иначе. Одни программы нам воспринимать легче, чем другие, и мы ищем комментарии, которые помогут нам разобраться.
Есть множество источников информации, помогающих программистам писать более качественный код — книги, сайты, статические анализаторы. Но гораздо меньше источников посвящено повышению качества комментариев. Легко измерить их количество в программе, но качество оценить сложно, и два этих параметра не обязательно взаимосвязаны. Плохой комментарий хуже отсутствия комментария. Вот несколько правил, которые помогут вам найти золотую середину.
Как писал Питер Фогель:
Первое правило: комментарии не должны дублировать код
Многие начинающие программисты пишут слишком много комментариев, потому что их к этому приучили. Я видел, как старшекурсники на факультете информатики добавляют комментарии к каждой закрывающей скобке, чтобы показать закрытие блока:
Я слышал о преподавателях, которые требуют от студентов комментировать каждую строку кода. Для совсем новичков это может быть оправдано, однако такие комментарии как боковые колёсики на детском велосипеде, которые по мере роста надо снять.
Неинформативные комментарии вредны, потому что:
Комментарий не добавляет полезной информации и требует усилий по поддержке.
Требования комментировать каждую строку справедливо высмеяли на Reddit:
Второе правило: хорошие комментарии не оправдывают непонятный код
Ещё один способ некорректного использования комментариев — предоставление информации, которая должна содержаться в коде. Например, когда кто-то назвал переменную одной буквой и добавил комментарий с объяснением:
Комментарий был бы не нужен, если дать переменной правильное название:
Как написали Керниган и Плогер в книге «The Elements of Programming Style»: «Не комментируйте плохой код, а переписывайте его».
Третье правило: если не можете написать понятный комментарий, то проблема может быть в коде
Самый известный комментарий в исходном коде Unix звучит так: «Вряд ли вы это поймёте». Его вставили перед запутанным кодом переключения контекста. Дэннис Ричи позднее объяснил, что это был не наглый вызов, а высказывание в духе «На экзамене такого не будет». Но похоже, что он сам и его соавтор Кен Томпсон сами не поняли свой код, и позднее переписали его. Всё это напоминает о законе Кернигана:
Отладка вдвое труднее первоначального написания кода. Поэтому если вы пишете код как можно умнее, то вы по определению не настолько умны, чтобы его отладить.
Предупреждение читателям, чтобы они держались подальше от вашего кода, сродни включению аварийных огней: признание в том, что вы делаете что-то незаконное. Лучше перепишите код так, чтобы вы сами понимали его достаточно, чтобы объяснить другим. Или ещё лучше, чтобы его вообще не требовалось объяснять.
Четвёртое правило: комментарии должны исключать путаницу, а не вносить её
Ни одно обсуждение плохих комментариев нельзя считать полным без этой истории из «Hackers: Heroes of the Computer Revolution» Стивена Леви:
[Питер Самсон] особенно усложнял ситуацию тем, что отказывался добавлять в свой исходный код комментарии с пояснением, что он делает в каждом конкретном случае. Одна из распространённых программ, написанных Самсоном, состояла из сотен инструкций на ассемблере с единственным комментарием после инструкции под номером 1750. Комментарий был такой: RIPJSB, и люди ломали головы над тем, что это означает, пока кто-то не догадался, что в 1750-м году умер Бах, и что Самсон написал аббревиатуру фразы “Rest In Peace Johann Sebastian Bach”.
Хотя я ценю хороший хак, но это не пример для подражания. Если ваш комментарий вносит путаницу, а не устраняет, то удалите его.
Пятое правило: объясняйте в комментариях не идиоматический код
Лучше комментировать код, который кто-нибудь может счесть ненужным или избыточным, вроде этого кода из App Inventor (источника всех моих положительных примеров):
Без комментария кто-нибудь может «упростить» код или счесть его таинственным, но необходимым заклинанием. Сэкономьте время и нервы будущих читателей и напишите, для чего нужен этот код. Необходимо оценивать, нуждается ли код в объяснении. Когда я изучал Kotlin, я столкнулся в руководстве по Android с подобным кодом:
Я рекомендую не добавлять комментарии к распространённым идиомам, если только вы не пишете руководство для новичков.
Шестое правило: добавляйте ссылки на исходный код, который вы скопировали.
Если вы такой же, как и большинство программистов, то иногда вы используете найденный в сети код. Добавляйте ссылку на исходник, чтобы будущие читатели имели полный контекст, например:
Если перейти по ссылке, то вы обнаружите, что:
Любой, кто захочет разобраться в коде, вынужден будет искать эту формулу. А если бы вставили ссылку, то можно было бы гораздо быстрее найти источник.
Некоторые программисты могут не захотеть указывать, что они не сами написали код, но повторное использование кода может быть разумным шагом, экономящим время и дающим вам преимущество в виде большего количества проверяющих. Конечно, никогда не вставляйте код, который не понимаете. Люди копируют со StackOverflow много кода, который попадает под лицензирование Creative Commons, требующее указания авторства. Для этого достаточно указать ссылку на первоисточник.
Вы также можете ссылаться на оказавшиеся полезными руководства в качестве благодарности их авторам и ради экономии времени читателей:
Седьмое правило: добавляйте ссылки на внешние примеры в тех случаях, когда это полезнее всего
Конечно, не все ссылки ведут на Stack Overflow.
Ссылки на стандарты и другую документацию помогут читателям понять проблему, которую решает ваш код. Хотя эта информация может храниться в проектной документации, однако удачно размещённый комментарий станет своевременным указателем. В приведённом примере ссылка подсказывает, что RFC 4180 обновили на RFC 7111, это полезная информация.
Восьмое правило: исправляя баги, добавляйте комментарии
Комментарии следует добавлять не только при первичном написании кода, но и при его изменении, особенно при исправлении багов. Взгляните:
Комментарий не только помогает понять код в конкретных методах, но и определить, нужен ли ещё этот код и как его тестировать. Также комментарий может ссылаться на систему отслеживания ошибок:
Конечно, можно с помощью git blame найти коммит, в котором была добавлена или изменена строка. Однако пояснения к коммитам обычно краткие, и самые важные изменения (например, исправление бага №1425) могут не содержаться в последнем коммите (который, скажем, переместил метод из одного файла в другой).
Девятое правило: помечайте комментариями незаконченные реализации
Иногда необходимо проверять код, даже несмотря на его ограничения. Хотя может быть заманчиво не рассказывать о недостатках своего кода, лучше сделать это явно, например, в комментарии TODO:
Стандартный формат для таких комментариев помогает оценить и адресовать технический долг. Ещё лучше, если добавите задачу в систему отслеживания ошибок и вставите ссылку в комментарий.
Нужны ли комментарии в коде
Бытует мнение, что писать комментарии к коду не нужно. Пошло оно, скорее всего, от высказывания одного из отцов программирования — Брайана Кернигана: «Don’t comment bad code, rewrite it». Как всегда, находятся фанатики, которые странно воспринимают авторитетные высказывания и никогда не пишут комментарии принципиально. Это неправильно.
Прежде всего, следует отметить, что документацию к классам и методам надо стараться писать всегда. Она рассказывает, для чего вообще нужен класс или метод и как его использовать.
Что касается непосредственно комментариев в коде, в большинстве случаев они действительно не нужны. Определённо не стоит комментировать каждую строчку метода, описывая словами, какую переменную мы присваиваем на этот раз.
Но есть и случаи, когда комментарии необходимы, а именно кода код делает что-то неочевидное и без комментария не ясно почему и зачем. Именно о таком коде говорит Керниган. Если такой код можно переписать, стоит этим заняться вместо закрепления нелогичности комментариями.
Бывает, что переписать нелогичный код нельзя. Например, при разработке под Android частенько приходится делать совершенно нелогичные на первый взгляд штуки для того, чтобы починить приложение под одной конкретной моделью телефона, которая почему-то работает не так, как описано в официальной документации. В этом случае комментарии в коде оправданы полностью. Без них ваши же коллеги просто удалят «ненужные» строчки, удостоверившись, что на их телефонах всё и без них работает как надо.
Комментарии RSS по email OK
Код методов не нуждается в комментариях, а вот документировать методы всё-таки надо.
@klay ты еще мои однострочники не видел 😉
@Alexey, да враки это все. За комментариями к методу также стоит следить как и за самим кодом. Написал php-doc сгенерь документацию и посмотри результат. Намного проще за комментариями следить, если проект на симфони или это джава спринг, там аннотации рекомендуется юзать, сразу будешь обращать внимание на комментарии и важность. И не должна лень перебаривать желание написать комментарий к методу. А то получается, что это из разряда — в документации не напишу пример, если хотите пример, откройте тесты и посмотрите скрипт тестирования. Бред же ж.
@klay, ага, однострочники, то-то в капистрано магия какая-то 😀
@Костя, ваши рассуждения что должно быть так и нужно перебарывать лень верны, в случае если вы один работаете на проекте и вы не поколебимы ни от каких обстоятельств. В реальной жизни на проектах, где работает много людей это не работает. Проще правила менять чтобы им было удобно следовать, и их можно было проверить автоматически. В Совершенном коде Стива Макконнела например все хорошо расписано и систематезировано, стоит пользоваться опытом других людей.
@Alexey а я и не говорил, что сижу один на проекте. У меня тимлидил, я занимался код ревью, я делал проект с другими ребятами. Скажу так — если захотеть, то можно все.
Ох, что-то я с ошибками пишу) В общем я тимлидил и есть опыт выстраивания гайдов по проекту 🙂
Проще правила менять чтобы им было удобно следовать, и их можно было проверить автоматически.
От одной крайности в другую не уходите. Слишком мягкие правила == отсутствие правил. Не бывает самодокументируемого кода в больших системах в «реальной жизни». Просто потому, что а) публичный API состоит из большого числа методов б) работать приходится с более чем одним API одновременно.
Под API я понимаю, в том числе публичный интерфейс классов. А там могут быть например самодокументируемые методы с отличными названиями, но зависящие от контекста, когда в двух и более классах названия совпадают. Посидите над достаточно крупной системой где кто-то решил что, «проще правила менять чтобы им было удобно следовать», день-другой и я уверен, PhpDoc захочется писать вообще над каждым даже самым очевидным методом.
@Костя, все можно, я согласен с вами. В любом случае важен здравый смысл конкретных людей, и правила не панацея. Часто бывает качество кода зависит от личностных качеств отдельных людей, и как только они отпускают свой контроль, оно падает. Я лишь имел в виду, что важно учитывать привычки и склонности людей, и формировать соглашения и правила исходя из этого. Ведь по течению справляться проще, чем против)