Недавно в LinkedIn поделился эмоциями о том, что в большинстве случаев при работе с внешними заказчиками в коде нет комментариев. Вообще нет комментариев. И как же после этого приятно заглядывать в код, в котором комментарии есть.
К моему удивлению, там случился срач в котором мне пытались доказать, что комментарии врут, поэтому их писать не нужно.
Аргументы были не просто старые, а совсем уж древние, впервые их услышал лет 35 назад, еще когда только-только учился программировать. И с тех пор выслушивал их неоднократно.
Разбирать подобные домыслы в очередной раз нет ни сил, ни времени, ни желания. Если кто-то убежден, что есть самодокументирующийся код, то бог вам судья. Позволю себе только напомнить, что хорошо написанный код показывает только то, что и как сделано, но не может ответить на два очень важных вопроса:
- почему это сделано именно так, а не иначе?
- зачем вообще это было сделано?
Никакой "типа самодокументирующийся код" не может ответить на эти вопросы. А уж плохо написанный код не сможет вменяемо рассказать даже о том что именно было реализовано.
Первоначально я хотел на этом и закончить, но встретил в статье про переиздание знаменитой книги "Мифический человеко-месяц" вот такой абзац:
Однако есть и другая точка зрения на этот вопрос. Например, Мартин (Роберт, а не Джордж), автор книги «Чистый код», утверждает, что комментарии — это зло. Даже будучи среди исходного кода они всё равно могут стать неактуальными. «Не трать время на написание комментариев», – говорит Мартин. Вместо этого он предлагает более тщательно подходить к процессу именования переменных, методов и классов. Если всё делается правильно, то и необходимость в комментариях отпадает.
и подумал, что если уж так все запущено, то почему бы не попробовать привести пример кода с комментариями и без? Просто для того, чтобы каждый мог сделать собственные выводы.
Disclaimer. Приведенный код -- это черновик, который еще не компилировался и не тестировался.
Итак, вот фрагмент без комментариев:
template<typename T>
void
doAttemptToSwitchFromReadOnlyToReadWrite(T * objectToLock)
{
auto & globalList = getGlobalListFor(objectToLock);
std::unique_lock globalListLock{ globalList._lock };
auto it = globalList._objects.find(objectToLock);
if(it != globalList._objects.end())
{
auto & lockInfo = it->second;
if(AccessMode::ReadOnly != lockInfo._currentMode)
throw std::runtime_error{
"doAttemptToSwitchFromReadOnlyToReadWrite: "
"lockInfo._currentMode != AccessMode::ReadOnly "
"in the global lock list"
};
if(1u == lockInfo._ownersCount)
{
lockInfo._currentMode = AccessMode::ReadWrite;
}
else if(isWaitingQueueEmpty(lockInfo))
{
OwnerCountForLockingUpgrateTrx ownerCounterTrx{ lockInfo };
const auto requestResult = makeWaitingAccessorInfoThenWait(
globalListLock,
lockInfo,
AccessMode::ReadWrite);
if(AccessRequestResult::granted != requestResult)
throw PossibleDeadlock{
"doAttemptToSwitchFromReadOnlyToReadWrite: "
"unable to upgrade ReadOnly lock to ReadWrite lock even "
"after waiting"
};
ownerCounterTrx.commit();
}
else
{
throw PossibleDeadlock{
"doAttemptToSwitchFromReadOnlyToReadWrite: "
"there is no possibility to upgrade ReadOnly lock "
"to ReadWrite lock"
};
}
}
else
{
throw std::runtime_error{
"doAttemptToSwitchFromReadOnlyToReadWrite: there is no "
"information about objectToLock in the global lock list"
};
}
}
|
А под катом он же, но в своем исходном виде, с комментариями. Посмотрите, подумайте, с каким кодом вам было бы комфортнее работать, если бы он вам достался на сопровождение. Я-то свои выводы уже давно сделал, чего и вам желаю.