Использование коментариев в исходном коде.
От: mrTwister Россия  
Дата: 05.12.10 12:09
Оценка: 33 (10) +10
Здравствуйте, коллеги.

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

Коментарии в коде могут решать разные задачи. В частности коментарии могут повышать читаемость кода. Но зачем повышать читаемость кода с помощью коментариев, если сам код можно структурировать таким образом, чтобы он читался легко, как книга? Для ответа на этот вопрос давайте определимся, для чего нам нужна читаемость. Итак, читаемость нам нужна, чтобы было легко понять:
1) Какую задачу решает код.
2) Каким образом код решает поставленную задачу.
3) Для чего потребовалось решать поставленную задачу. То есть почему этот код необходим.

Самый простой и понятный в этом списке — это пункт "2". Действительно, приложив определенные усилия и использовав специальные общеизвестные приемы, можно добиться того, что способ решения поставленной задачи станет очевидным из самого кода. В этом случае коментарии, описывающие способ решения задачи станут излишними, так как они будут дублировать информацию, которая и так уже содержится в коде. Don't repeat yourself (c)

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

А вот с пунктом "3 — почему этот код необходим" ситуация становится совсем сложной. Тут проблема в том, что в коде такой информации обычно нет вообще, а следовательно, мы не можем структурировать код таким образом, чтобы эта информация стала легкодоступной. Невозможно сделать легкодоступным то, чего нет. Эта информация обычно содержится только в голове у программиста в тот момент, когда он пишет данный код. Это его контекст. Часто для формирования такого контекста надо учитывать множество разрозненных деталей всей системы, особенности того, как они друг с другом взаиможействуют, исторические аспектры разработки системы, особенности работы некоторых, в том числе, сторонних и унаследованных компонент, политические вопросы и так далее. Это все это может быть необходимым читателю, чтобы он мог понять, зачем этот код вообще нужен. Ведь сам код можт быть каким угодно простым, легкочитаемым, из кода может быть очевидно что и как он делает, но вот на кой черт он вообще нужен может быть и не понятно. Вот именно это и должно документироваться в довесок к коду, в том числе с помощью коментариев. Опять таки это справедливо только тогда, когда данную информацию невозможно адкватно выразить с помощью имени абстракции.

Я не согласен с фразой, что лучшая документация — это код. Выше были показаны ситуации, когда одного кода не достаточно. Приведу конкретный пример из своей практики.

Разрабатываются параллельно два проекта, основанные на общей кодовой базе. Оба проекта подлежат локализации на целую группу языков. В ходе разработки достаточно регулярно происходят ситуации, когда часть кода переходит из проектно-специфичной кодовой базы в общую кодовую базу и обратно. Тоже самое касается и ресурсов, используемых переезжаемым кодом — они также вместе с ним переезжают. Для того, чтобы облегчить перенос ресурсов, код не должен ничего знать об источнике этих ресурсов. Ресурсы из общей кодовой базы и проектной кодовой базы должны получаться из одного места. Для этого был введен следующий интерфейс (упрощенно):
public interface IResourceProvider
{
    string GetResource(string resourceIdentifier);
}

Интерфейст тривиален. Его реализация тривиальна. Но тем не менее, читателю, который находится вне контекста совершенно не понятно, зачем этот интерфейс вообще понадобился и почему нельзя было сделать проще, а именно напрямую обращаться к автоматически сгенерированному ResourceManager'у.

Также бывает, что комнтарии весьма уместны в случаях, когда выразительных способностей используемого языка программирования не хватает, чтобы явно в коде описать намерения программиста. Например, коментариями можно уточнить контракт некоторого интерфейса. Пример: в .NET есть интерфейс "IDisposable", с единственным методом "Dispose", осуществляющим очистку ресурсов. Контракт этого интерфейса предполагает, что метод "Dispose" может быть вызван любое количество раз и это не должно приводить к ошибкам, например к повторному освобождению уже освобожденных ресурсов. Подобный факт не может быть выражен непосредственно самим кодом, по-этому единственный способ — это документация (или коментарии, как частный случай документации). Можно мне возразить: а как же ассерты и юнит-тесты, ведь с их помощью тоже можно специфицировать контракт! Можно, но не контракт интерфейса, а контракт конкретной его реализации.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
лэт ми спик фром май харт
Re: Использование коментариев в исходном коде.
От: k.o. Россия  
Дата: 05.12.10 17:14
Оценка: -3
Здравствуйте, mrTwister, Вы писали:

T>Здравствуйте, коллеги.


T>Коментарии в коде могут решать разные задачи. В частности коментарии могут повышать читаемость кода. Но зачем повышать читаемость кода с помощью коментариев, если сам код можно структурировать таким образом, чтобы он читался легко, как книга? Для ответа на этот вопрос давайте определимся, для чего нам нужна читаемость. Итак, читаемость нам нужна, чтобы было легко понять:

T>1) Какую задачу решает код.
T>2) Каким образом код решает поставленную задачу.
T>3) Для чего потребовалось решать поставленную задачу. То есть почему этот код необходим.

Обычно, пункт 3, описывается в issue-tracker'е. Коментарии для этого, мягко говоря, не самое подходящее место.
Re: Использование коментариев в исходном коде.
От: 0x7be СССР  
Дата: 05.12.10 17:50
Оценка: 7 (3) +2
Здравствуйте, mrTwister, Вы писали:

T>Здравствуйте, коллеги.


T>В этой теме я предлагаю вновь обсудить использование коментариев в исходном коде.

T>...
Написаны в целом очень разумные мысли.

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

Вот мы говорим: "читаемость". Она тоже не есть самоцель, а лишь средство достижения других целей. В конечном итоге — успеха проекта. Мы хотим, что бы код был понятен просто и легко, что бы человек, его читающий, понял его быстро и понял его правильно. Что бы не на понимание не неделю, а день и потом не делал при его использовании/поддержке ошибок, на исправление которых потратится ещё время. Комментарий — это дополнительный кусочек кода, который надо поддерживать в актуальном состоянии, а это затраты. Продумать/отрефакторить код, что бы он стал самоочевидным, тоже стоит времени, причем очень разного в зависимости от семантического разрыва между уровнем кода и уровнем сообщения (ты как раз об этом писал). И так далее.

Собственно к чему я это все: внесение комментария в код должно быть обосновано, равно как и любое другое решение при разработке программы, с точки зрения соответствия главной цели. Нельзя писать комментарии просто так, про запас. Нельзя целиком от них отказываться лишь потому, что это модно. Все правила вида "всегда/никогда (не)делайте Х" — это некоторое обобщение конкретного опыта достижения этой цели, полученные конкретными людьми в своих конкретных условиях, и относиться к ним надо соответственно.
Re: Использование коментариев в исходном коде.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.12.10 02:22
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Также бывает, что комнтарии весьма уместны в случаях, когда выразительных способностей используемого языка программирования не хватает, чтобы явно в коде описать намерения программиста. Например, коментариями можно уточнить контракт некоторого интерфейса. Пример: в .NET есть интерфейс "IDisposable", с единственным методом "Dispose", осуществляющим очистку ресурсов. Контракт этого интерфейса предполагает, что метод "Dispose" может быть вызван любое количество раз и это не должно приводить к ошибкам, например к повторному освобождению уже освобожденных ресурсов. Подобный факт не может быть выражен непосредственно самим кодом, по-этому единственный способ — это документация (или коментарии, как частный случай документации). Можно мне возразить: а как же ассерты и юнит-тесты, ведь с их помощью тоже можно специфицировать контракт! Можно, но не контракт интерфейса, а контракт конкретной его реализации.


Контракт это интерфейс + семантика. Семантика описывается и кодом и документацией.
Re: Использование коментариев в исходном коде.
От: Klatu  
Дата: 06.12.10 06:32
Оценка: +3
Здравствуйте, mrTwister, Вы писали:

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

PS но вот за что совершенно точно надо безжалостно пороть программистов — за комментарии типа
// this function opens file
void OpenFile(string name)
{
...
}

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: To Undying
От: k.o. Россия  
Дата: 06.12.10 14:52
Оценка:
А не мог бы ты своё несогласие, в более развёрнутом виде выразить?
Re[3]: To Undying
От: March_rabbit  
Дата: 06.12.10 17:26
Оценка: +3
Здравствуйте, k.o., Вы писали:

KO>А не мог бы ты своё несогласие, в более развёрнутом виде выразить?

в смысле, за назначением каждой строки программы мне надо будет лазить в сторонний ресурс? Вот спасибо, добрый фей. Мало у меня вопросов возникает, когда исправляю чужую библиотеку.....
Re[4]: To Undying
От: k.o. Россия  
Дата: 06.12.10 17:40
Оценка:
Здравствуйте, March_rabbit, Вы писали:

M_>Здравствуйте, k.o., Вы писали:


KO>>А не мог бы ты своё несогласие, в более развёрнутом виде выразить?

M_>в смысле, за назначением каждой строки программы мне надо будет лазить в сторонний ресурс? Вот спасибо, добрый фей. Мало у меня вопросов возникает, когда исправляю чужую библиотеку.....

Во-первых, это далеко не всегда нужно знать для каждой строки программы, во-вторых если смотреть на результат blame/annotate, то нужная информация, скорее всего, будет в коментарии к коммиту, ну и в третьих — есть предложения лучше? Если для какого-то issue поменялись/добавились 100 строк будешь для каждой из них дублировать описание? А дополнительные файлы куда прикреплять?
Re[2]: Использование коментариев в исходном коде.
От: alesterre Удмуртия  
Дата: 07.12.10 11:16
Оценка:
Здравствуйте, Klatu, Вы писали:

K>PS но вот за что совершенно точно надо безжалостно пороть программистов — за комментарии типа

K>
K>// this function opens file
K>void OpenFile(string name)
K>{
K>...
K>}
K>

K>

У меня на прошлом месте работы стандарт оформления исходников предполагал написание комментария, помимо прочего, к каждому методу и к каждому параметру. И большинство комментариев были именно такими, как в этом примере (только на русском). Всегда испытывал жуткое раздражение, когда пытался разобраться в огромном непонятном модуле и вместо внятных пояснений натыкался только на изречения КО. Понятно, что те, кто там работал несколько лет, на комментарии вообще не смотрели, и писали их только чтобы было по стандарту, но мне поначалу было очень трудно.
Re[5]: To Undying
От: March_rabbit  
Дата: 09.12.10 11:47
Оценка: 1 (1) +1
Здравствуйте, k.o., Вы писали:

KO>Здравствуйте, March_rabbit, Вы писали:


M_>>Здравствуйте, k.o., Вы писали:


KO>>>А не мог бы ты своё несогласие, в более развёрнутом виде выразить?

M_>>в смысле, за назначением каждой строки программы мне надо будет лазить в сторонний ресурс? Вот спасибо, добрый фей. Мало у меня вопросов возникает, когда исправляю чужую библиотеку.....

KO>Во-первых, это далеко не всегда нужно знать для каждой строки программы,

ага, не для каждой

KO>во-вторых если смотреть на результат blame/annotate, то нужная информация, скорее всего, будет в коментарии к коммиту,

стандартный коммит: fixed bug #11111. (bug: no MusicOnHold sound for phone placed beyond NAT).
Много тебе скажет этот комментарий, если ты увидишь, что добавилось несколько строк в процедуре, которая ни разу не связана с задачей установления/настройки сессии? Почему они там?

KO>ну и в третьих — есть предложения лучше? Если для какого-то issue поменялись/добавились 100 строк будешь для каждой из них дублировать описание?

дублировать описание чего? Как минимум, если ввел процедуру — строка/две с пояснением, зачем процедура нужна. Ввел в процедуру что-то нетипичное для ее назначения (алгоритм работы программы такой, что не получается красиво починить/доработать) — укажи, зачем ЭТО. Если изменение тупое и явное — можно и без комментария.

KO>А дополнительные файлы куда прикреплять?

схемы/стандарты? Стандарты можно и ссылкой. А вот схемы.... У нас авторы конечных автоматов схемы прямо в начале файла в комментариях рисуют. Геморно, зато код читабельный хоть.
Re[2]: Использование коментариев в исходном коде.
От: mrTwister Россия  
Дата: 09.12.10 19:51
Оценка:
Здравствуйте, k.o., Вы писали:

KO>Обычно, пункт 3, описывается в issue-tracker'е. Коментарии для этого, мягко говоря, не самое подходящее место.


У issue-tracker'а гранулярность слишком низкая и пользоваться им не удобно при чтении кода.
лэт ми спик фром май харт
Re[2]: Использование коментариев в исходном коде.
От: mrTwister Россия  
Дата: 09.12.10 19:54
Оценка:
Здравствуйте, 0x7be, Вы писали:

0>Вот мы говорим: "читаемость". Она тоже не есть самоцель, а лишь средство достижения других целей.

Можно обобщить так: если требуется поддержка кода, то он должен быть читаемым.
лэт ми спик фром май харт
Re[2]: Использование коментариев в исходном коде.
От: mrTwister Россия  
Дата: 09.12.10 19:57
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Контракт это интерфейс + семантика. Семантика описывается и кодом и документацией.

Можно, наверное, и так сказать, но более общепринятое определение контракта — это интерфейс + предусловия + постусловия + инвариант.
лэт ми спик фром май харт
Re[2]: Использование коментариев в исходном коде.
От: mrTwister Россия  
Дата: 09.12.10 19:57
Оценка:
Здравствуйте, Klatu, Вы писали:

K>Еще одна задача комментариев, самая важная — объяснить почему код работает именно так, а не иначе. Почему был выбран этот алгоритм, почему использован такой хак и так далее.


K>PS но вот за что совершенно точно надо безжалостно пороть программистов — за комментарии типа

K>
K>// this function opens file
K>void OpenFile(string name)
K>{
K>...
K>}
K>

K>

В принципе, это мало чем отличается от дублирования кода.
лэт ми спик фром май харт
Re[2]: Использование коментариев в исходном коде.
От: Undying Россия  
Дата: 10.12.10 06:02
Оценка: +1
Здравствуйте, k.o., Вы писали:

KO>Обычно, пункт 3, описывается в issue-tracker'е. Коментарии для этого, мягко говоря, не самое подходящее место.


У issue-tracker и у комментариев в коде совершенно разные и уровень детализации, и предназначение. Issue-tracker описывает цель задачи, что-то вроде "пользователь хочет такую-то фичу, надо сделать". Далее мы эту фичу реализуем, пишем в процессе 15 классов и 125 функций, после чего обнаруживаем, что назначение сто первой функции не очевидно. Соответственно мы должны написать пояснение, однако чтобы понять это пояснение, нужно иметь информацию о конкретной реализации. В issue-tracker'е этой информации нет, она есть только в коде. Соответственно размещая пояснение в issue-tracker мы отрываем пояснение от контекста, в котором оно может быть понято.
Re[3]: Использование коментариев в исходном коде.
От: k.o. Россия  
Дата: 10.12.10 08:12
Оценка:
Здравствуйте, Undying, Вы писали:

U>Здравствуйте, k.o., Вы писали:


KO>>Обычно, пункт 3, описывается в issue-tracker'е. Коментарии для этого, мягко говоря, не самое подходящее место.


U>У issue-tracker и у комментариев в коде совершенно разные и уровень детализации, и предназначение. Issue-tracker описывает цель задачи, что-то вроде "пользователь хочет такую-то фичу, надо сделать".


Так, это, ИМХО, как раз и соответсвует

3) Для чего потребовалось решать поставленную задачу. То есть почему этот код необходим.


U>Далее мы эту фичу реализуем, пишем в процессе 15 классов и 125 функций, после чего обнаруживаем, что назначение сто первой функции не очевидно.

Соответственно мы должны написать пояснение, однако чтобы понять это пояснение, нужно иметь информацию о конкретной реализации. В issue-tracker'е этой информации нет, она есть только в коде. Соответственно размещая пояснение в issue-tracker мы отрываем пояснение от контекста, в котором оно может быть понято.

Весь вопрос в том, что ты вкладываешь в понятие "назначение функции", если это

1) Какую задачу решает код.

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

Если же это включает в себя

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

то с болшой вероятностью это всё будет иметь смысл и для остальных 124 функций и 15 классов и как это будет выглядеть в комментариях мне пока непонятно.
Re[3]: Использование коментариев в исходном коде.
От: k.o. Россия  
Дата: 10.12.10 08:33
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Здравствуйте, k.o., Вы писали:


KO>>Обычно, пункт 3, описывается в issue-tracker'е. Коментарии для этого, мягко говоря, не самое подходящее место.


T>У issue-tracker'а гранулярность слишком низкая и пользоваться им не удобно при чтении кода.


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

3) Для чего потребовалось решать поставленную задачу. То есть почему этот код необходим.


Если изначально нет никакого issue, зачем вобще код трогать? А если есть, то там уже должно быть написано зачем мы что-то изменяем в коде.
Re[4]: Использование коментариев в исходном коде.
От: mrTwister Россия  
Дата: 10.12.10 08:44
Оценка:
Здравствуйте, k.o., Вы писали:


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


KO>

KO>3) Для чего потребовалось решать поставленную задачу. То есть почему этот код необходим.


KO>Если изначально нет никакого issue, зачем вобще код трогать? А если есть, то там уже должно быть написано зачем мы что-то изменяем в коде.


В issue-трекере находится гораздо более высокоуровневое описание. Например, некоторый код может выполнять странные действия ради того, чтобы обойти баг в сторонней библиотеке. Но в issue не будет формулировки "обойти баг", там будет "реализовать фичу"
лэт ми спик фром май харт
Re[5]: Использование коментариев в исходном коде.
От: k.o. Россия  
Дата: 10.12.10 09:31
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Здравствуйте, k.o., Вы писали:



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


KO>>

KO>>3) Для чего потребовалось решать поставленную задачу. То есть почему этот код необходим.


KO>>Если изначально нет никакого issue, зачем вобще код трогать? А если есть, то там уже должно быть написано зачем мы что-то изменяем в коде.


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


Так это уже деталь реализации фичи, причины использования этой странной реализации вполне уместно описать в комментарии.
Re[3]: Использование коментариев в исходном коде.
От: 0x7be СССР  
Дата: 10.12.10 19:21
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Здравствуйте, 0x7be, Вы писали:


0>>Вот мы говорим: "читаемость". Она тоже не есть самоцель, а лишь средство достижения других целей.

T>Можно обобщить так: если требуется поддержка кода, то он должен быть читаемым.
Не совсем
Это обобщение будет справедливо в 99.(9)% случаев, но возможны и такие случаи, когда стоимость поддержки нечитабельного кода будет меньше, чем стоимость приведения его в читабельность
Ну а если серьезно, то при выборе между "отрефакторить состояния самоочевидности" и "написать каммент" надо выбирать осознанно и с учетом затрат на оба решения. Лично у меня обычно выбор падает на 1ый вариант, но бывает и второй.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.