Сам я придерживаюсь мнения о том, что во многом наличие/отсутствие документации зависит от культуры организации. В некоторых организациях знания хранятся в головах у сотрудников, в некоторых — в документах ворда. И я лично, плохого в этом не виду ничего.
Например наш проект, средний по размеру (~40 человеко/лет) пережил уже несколько версий, частично сменилась команда которая над ним работает и при всё при этом документации по нему по сути нет никакой, ни по архитектуре, ни по коду. Комментариев в коде нет тоже. И проблем это не вызывает. Обратите внимание, я не говорю что это круто — я лишь говорю, что нам это не доставляет никаких проблем. А если нет разницы — зачем платить больше? (с)
Поэтому, во многом, вопрос к тем кто практикует документирование — а зачем вам это? Что, собственно, вам дают залежи документации? Кто её читает? Или она нужно только для того, что бы унять какие-то страхи менеджмента? Так для этого есть более совершенные методы.
Здравствуйте, Патрик, Вы писали:
П>Сам я придерживаюсь мнения о том, что во многом наличие/отсутствие документации зависит от культуры организации. В некоторых организациях знания хранятся в головах у сотрудников, в некоторых — в документах ворда. И я лично, плохого в этом не виду ничего.
П>Например наш проект, средний по размеру (~40 человеко/лет) пережил уже несколько версий, частично сменилась команда которая над ним работает и при всё при этом документации по нему по сути нет никакой, ни по архитектуре, ни по коду. Комментариев в коде нет тоже. И проблем это не вызывает. Обратите внимание, я не говорю что это круто — я лишь говорю, что нам это не доставляет никаких проблем. А если нет разницы — зачем платить больше? (с)
Ну если нет разницы, то действительно, зачем платить больше?
Пока гром не гремит, зачем креститься-то?
Сам я убедился в том, что документировать код нужно обязательно когда потребовалось одновременно вести три или четыре проекта, быстро и неожиданно переключаясь с одного проекта на другой. Тогда лично моих способностей держать в голове кучу деталей по всем проектам просто не хватило. Я элементарно забывал, что писал в каком-то проекте пару дней назад. Не говоря уже про код, написанный несколько месяцев назад.
Да и сейчас мной написано столько всего, что я просто не в состоянии помнить форматы каких-нибудь методов и их особенности. В таких случаях автодокументаторы типа doxygen или javadoc очень выручают. Загружаешь в браузере доку по библиотеке и видишь не только форматы и пояснения, но и примеры можно посмотреть и даже туториалы. А в продвинутых IDE тебе тоже самое прямо по ходу набора текста подсказывается. Я считаю, что за такое удобство можно заплатить временем на написание комментариев в коде.
Сам я придерживаюсь мнения, что код документировать нужно обязательно. Даже если он и кажется тривиальным. Имхо, это как противопожарная безопасность: лучше перебдеть, чем перебзд... Поэтому, если в ходе code review я вижу незадокументированный код, то даю по рукам и заставляю задокументировать его.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Патрик, Вы писали:
П>Что уважаемая общественность думает о необходимости документировать/комментировать код?
Очень много зависит от решаемой задачи. Иной код самодостаточный. А в случае реализации сложного алгоритма надо хотя бы ссылку на источник привести А если написанию кода предшествовали математические выкладки, то это может помочь сэкономить преемнику массу времени
E>Ну если нет разницы, то действительно, зачем платить больше? E>Пока гром не гремит, зачем креститься-то?
Дык уж несколько лет не гремит, и не только у меня
E>Сам я убедился в том, что документировать код нужно обязательно когда потребовалось одновременно вести три или четыре проекта, быстро и неожиданно переключаясь с одного проекта на другой. Тогда лично моих способностей держать в голове кучу деталей по всем проектам просто не хватило. Я элементарно забывал, что писал в каком-то проекте пару дней назад. Не говоря уже про код, написанный несколько месяцев назад.
Ты один их писал? Или были какие-то подчинённые? Если были — то наверное стоило делегировать им бОльшую часть работы и заниматься лишь их контролем...? Хотя, я конечно, не в курсе конкретной ситуации, поэтому воздержусь от особых комментариев.
Здравствуйте, Патрик, Вы писали:
П>Здравствуйте, eao197, Вы писали:
E>>Ну если нет разницы, то действительно, зачем платить больше? E>>Пока гром не гремит, зачем креститься-то?
П>Дык уж несколько лет не гремит, и не только у меня
Так я и говорю, если не гремит, то чего уж выделываться.
E>>Сам я убедился в том, что документировать код нужно обязательно когда потребовалось одновременно вести три или четыре проекта, быстро и неожиданно переключаясь с одного проекта на другой. Тогда лично моих способностей держать в голове кучу деталей по всем проектам просто не хватило. Я элементарно забывал, что писал в каком-то проекте пару дней назад. Не говоря уже про код, написанный несколько месяцев назад.
П>Ты один их писал?
В том-то и дело, что один. И неприятно было в один прекрасный момент понять, что вот-он рубеж моих способностей. Не такой уж и далекий оказался.
П> Или были какие-то подчинённые? Если были — то наверное стоило делегировать им бОльшую часть работы и заниматься лишь их контролем...?
А вот недавно был как раз такой случай, когда из-за недостаточного количества комментариев в коде одного подчиненного прилось объяснять второму подчиненному, что, как и почему.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
П>> Или были какие-то подчинённые? Если были — то наверное стоило делегировать им бОльшую часть работы и заниматься лишь их контролем...?
E>А вот недавно был как раз такой случай, когда из-за недостаточного количества комментариев в коде одного подчиненного прилось объяснять второму подчиненному, что, как и почему.
У нас это регулярно происходит, и ничего...Объясняем! Коммуникация, однако
Здравствуйте, Патрик, Вы писали:
П>Что уважаемая общественность думает о необходимости документировать/комментировать код?
Комментировать конечно надо, только с умом: пришлось помню разбираться в старом коде на работе. Там было очень мало комментариев, а те которые были являлись бесполезными... ну например, как мило после кропотливого анализа пары экранов кода без комментариев встретить такой коментарий:
Вот пример, как на мой взгляд, хорошо задокументированой программы, написаной в стиле литературного программирования. Однако эта, имхо, заслуживающая внимания методология, не получила должного распространения. Почему? Не знаю. Я пробовал написать несколько программ по этой методологии, получалось достаточно забавно.
Здравствуйте, Патрик, Вы писали:
П>Что уважаемая общественность думает о необходимости документировать/комментировать код?
Думаю, что по возможности код должен обладать следующими характеристиками:
1. Понятность, т.е. его должно понимать максимальное количество программистов.
2. Легкость модификации, т.е. если код потребуется изменить через большой промежуток времени и возможно не тому кто его создал, то это не должно вызвать затруднений (в том числе и с пониманикм).
3. Осмысленность, т.е. код должен делать то, что планировал его создатель.
Так вот комментарии помогают достичь всех этих целей. Конечно если они сделаны с умом и если нет других факторо на прочь убивающих толк от комментариев.
Так что коментарии не самоцель, а одна из састовляющих при получении качественного программного продукта.
... << RSDN@Home 1.2.0 alpha rev. 516>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
П>Что уважаемая общественность думает о необходимости документировать/комментировать код?
IMHO прежде всего нужно стремиться к самодокументируемому коду. В идеале должен комментироваться только дизайн (связи между классами и назначение отдельных классов).
В самом самом коде (реализации) должны быть комментированы разве что нестандартные ходы (например, отпимизаця).
Плюс придерживание одинакового стиля кодирования для разных членов проекта.
Знания вполне могут хранятся в головах, когда все сидят на одном и том же проекте долгое время и досконально знают концепwию, которую несет этот проект. Однако, когда начнется переключение между разными проектами (то бишь концепциями), начнут возникать проблемы.
Патрик,
> Что уважаемая общественность думает о необходимости документировать/комментировать код? > Я смотрю, что мнения на этот счёт радикально расходятся
По крайней мере, легко согласиться с тем, что нужно документировать неочевидные моменты. Конечно, критерии очевидности очень сильно сильно зависят от человека к человеку, но если сойтись на буквальной трактовке слова "очевидный", то станет несколько легче. А именно: если некоторое предположение, сделанное автором, или причина, почему именно так написано, не видны из кода, то нужно их задокументировать. С другой стороны, возможно, стоит подумать о том, как сделать видимыми в коде вещи, размещаемые в комментариях...
Например, из свеженького.
Есть интерфейсы — наследники некоторого ICommunicator, представляющие собой связь некоторых backend операций с окружением, в том числе с GUI. Например, если в ходе выполнения операции обнаружилось, что некоторый файл копируется поверх уже существующего, то backend операция "спрашивает", что нужно делать: заменить файл, пропустить его, оставив уже существующий, или вообще прервать всю операцию. Или, скажем, каталог назначения не существует, и нужно получить подтверждение. Изначально в качестве результатов подобных функций были выбраны символы, представляющие собой акроним названия кнопки, выбранной пользователем в соответствующем диалоге. Скажем 'o' — "OK", 'r' — "Retry", 'v' — "Overwrite", 'c' — "Cancel", 'k' — "Skip" и т.п.
А иногда, даже зная, что, скажем, символ 'o' означает "OK", все равно неясно, что именно означает "OK" в данном случае.
. . .
if ( !file_exists( path ) )
{
switch ( communicator.destination_folder_does_not_exists( path ) )
{
case'c': // Cancel
. . .
case'o': // here "OK" means that we should go on and create missing folder
. . .
default:
throw UnexpectedCommunicatorAnswer();
}
}
. . .
Также нужно документировать интерфейс, чтобы описать, что же за char возвращают данные функции...
Вместо узаконивания такого положения дел комментированием можно сделать два очевидных шага: 1) уйти от акронимов названий кнопок, вообще абстрагируясь от конкретных вариантов, предложенных пользователю; 2) ввести константы с понятными именами, чтобы не надо было в точке использования документировать все это дело. Скажем, ввести перечислимый тип, включающий все возможные варианты "смыслов" ответов пользователя:
enum CommunicatorAnswer
{
communicator_cancel,
communicator_continue, // go on, ignore the warning and continue the operation
communicator_overwrite,
communicator_skip,
communicator_retry
};
if ( file_exists( path ) )
{
switch ( communicator.file_exists( path ) )
{
case communicator_cancel: . . .
case communicator_overwrite: . . .
case communicator_skip: . . .
default: throw UnexpectedCommunicatorAnswer();
}
}
if ( !file_exists( path ) )
{
switch ( communicator.destination_folder_does_not_exists( path ) )
{
case communicator_cancel: . . .
case communicator_continue: . . .
default: throw UnexpectedCommunicatorAnswer();
}
}
Однако теперь видны другие недостатки: 1) в месте объявления функций-членов ICommunicator совершенно неочевидно, какие из вариантов ответов они могут возвращать; 2) в точке использования неясно, учтены ли все варианты ответов, или же по ошибке о каком-то из них забыли.
Можно разбавить код комментариями...
А можно так изменить код, чтобы было совершенно очевидно, какие варианты ответов может возвращать та или иная функция, и чтоб в месте использования можно было легко увидеть, что никакой из возможных вариантов не забыт:
Более того, как можно заметить, мы еще и избавились от проверки времени исполнения, что получен ожидаемый ответ, т.к. теперь это делается во время компиляции! Заодно сравнить результат функции с ответом, который она не может вернуть, нельзя — это также будет диагностировано компилятором.
Как видно, один комментарий в коде, все-таки, остался... Но надо же, в конце концов, на чем-то остановиться!
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
P.S.
>> Всё это здорово, конечно, а не проще ли было бы сделать два enum а для кодов возврата двух разных функций?
ПК>Когда как... Если есть код, который умеет обрабатывать результаты разных нештатных ситуаций, то, полагаю, все-таки, не проще.
Ну и, естественно, мы не получим некоторых существенных достоинств в случае решения, описанного выше: 1) в точке использования не будет видно, что обрабатываются все ситуации; 2) если набор значений, возвращаемых функцией, будет расширен, мы не получим от компилятора никаких подсказок об этом в точках использования. В случае же примера выше, мы явно выражаем происходящее и в месте объявления функции (что она может возвращать), и в месте ее использования (что пользователь ожидает от функции); и компилятор следит за совпадением ожиданий пользователя с тем, что функция возвращает на самом деле.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Павел Кузнецов
E>А во что это все превратиться, если потребуется новые коды возврата добавить? timedout, например?
В пересмотр всей программы. Если изменился контракт объекта (он стал возвращать новые значения), то есть смысл во всех точках вызова убедиться, что эти новые значения корректно обработаны. Здесь компилятор просто заставит это сделать
Впрочем, такую расширяемость можно закладывать заранее: например,
template< unsigned Mask, class OnUnexpected = do_static_assert >
class CommunicatorAnswer
{
unsigned value_;
public:
template<unsigned SrcMask, class T >
CommunicatorAnswer(CommunicatorAnswer<SrcMask, T> src,
enable_if_c(
(SrcMask & ~Mask)==0, // если маска исходного типа меньше или равна нашей маскеvoid*)::type = NULL
)
: value_(src.value())
{}
template<unsigned SrcMask, class T >
CommunicatorAnswer(CommunicatorAnswer<SrcMask, T> src,
enable_if_c(
(SrcMask & ~Mask)!=0, // если маска исходного типа больше нашей маскиvoid*)::type = NULL
)
: value_(OnUnexpected()(Mask,src.value())) // выполним замену (или даже получим по рогам при компиляции)
{}
};
struct do_static_assert
{
// нет operator() - будет ошибка компиляции
};
static do_runtime_assert
{
unsigned operator()(unsigned mask, unsigned value) const
{
if((value & ~mask) != 0)
throw logic_error("кривые кирпичи мне подсунули");
return value;
}
};
static do_supress
{
unsigned operator()(unsigned mask, unsigned value) const
{
if((value & ~mask) != 0)
value = /*первый попавшийся ненулевой бит маски*/;
return value;
}
};
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, eao197, Вы писали:
E>>Здравствуйте, Павел Кузнецов
E>>А во что это все превратиться, если потребуется новые коды возврата добавить? timedout, например?
К>В пересмотр всей программы. Если изменился контракт объекта (он стал возвращать новые значения), то есть смысл во всех точках вызова убедиться, что эти новые значения корректно обработаны. Здесь компилятор просто заставит это сделать
Да это-то я понимаю. Мне просто интересно, хорошо ли это? Нет ли здесь попытки замутить сознание в тривиальном, в общем-то, случае?
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Почему-то пример в итоге свелся к "нужно ли комментировать код".
Это не совсем то же самое, что и "документировать код".
Чем меня сразу покорил тот же boost, так это именно своей документацией.
Я не любитель читать чужие исходные тексты и потому как откомментирован boost,
мне все равно. Для поддержки boost'а вменяемые комментарии могут важными,
ну а а мне как пользователю библиотеки важнее описание что это вообще такое
и как этим добром пользоваться.
А Патрик как раз и спрашивал о подобной общей библиотеке маштаба одной компании.
Ее будет полезно и задокументировать, и откомментировать, и оттестировать
и code review провести...