Недавно в 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" }; } } |
А под катом он же, но в своем исходном виде, с комментариями. Посмотрите, подумайте, с каким кодом вам было бы комфортнее работать, если бы он вам достался на сопровождение. Я-то свои выводы уже давно сделал, чего и вам желаю.