Четыре отговорки против комментариев
Антон объясняет, почему тезис книги ему близок: он больше занимается управлением, аналитикой и архитектурой, но регулярно читает чужой код — и не всегда в первозданном виде. Ему интересно разбирать изнутри популярные приложения, которыми все пользуются каждый день, а там нет ни комментариев, ни осмысленно названных методов, переменных и классов, и весь контекст приходится восстанавливать самому. Читать код — само по себе время и лишняя мозговая работа, иногда с компиляцией, когда всего-то нужно вызвать метод.
Первую отговорку — «код документирует сам себя» — участники связывают с книгами Роберта Мартина. Александр вспоминает «Code Complete» Стива Макконнелла, одну из первых больших книг, которая на него повлияла, и месячной давности интервью, которое у Макконнелла взял в другом книжном клубе инженерный директор из Google: спустя тридцать лет после первого издания собеседник напоминает ему ту самую фразу, и Макконнелл только и отвечает: «О боже ты мой».
Он имел в виду другое: документации и комментариев обычно нет, читать всё равно приходится код — так пусть он будет хотя бы понятным. Александр отмечает, как вырванная из контекста фраза превращается в мем, которым потом отбиваются от комментариев. Автор возражает по существу: если код приходится читать, чтобы понять поведение, абстракция уже протекла.
Илья добавляет, что сигнатуры и типы описывают лишь часть, а неформальные договорённости кодом не выразишь; Антон приводит метод, который проксирует ошибки вызовов уровнем ниже, — чтобы собрать их перечень, надо прочитать много чужого кода, тогда как в Java или Go хватает сгенерированной документации.
Отговорку «нет времени» автор меряет так: набор кода занимает около десяти процентов работы, а комментарии — это не долг, а инвестиция в продуманный дизайн.
Отговорка про устаревание снимается уровнем абстракции — высокоуровневые комментарии меняются редко; а хорошая документация, отмечают участники, лечит ровно те симптомы сложности, которые не чинятся генерацией кода: когнитивную нагрузку и неизвестное неизвестное.
Отговорка «все комментарии, что я видел, бесполезны» лечится тем, что полезные начинаете писать вы, и тогда они появляются и в соседних системах компании.
Четыре уровня и проверка комментария
Одноразовый скрипт в стиле тактического торнадо комментировать не обязательно, но участники вспоминают код, написанный по принципу «написал и забыл»: через два-три года понять заложенные в нём компромиссы и ограничения почти невозможно.
Тринадцатая глава требует от комментария добавленной ценности: повторять очевидное из кода не надо. Один из ведущих признаётся, что в начале карьеры был грешен — писал комментарии формально, раз положено, а отсутствие в них смысла считал вопросом второго порядка. Участники вспоминают принцип бутерброда и складывают образ слоёного пирога: сверху крышка про то, зачем всё это вообще написано, ниже сам код, а внутри низкоуровневые пояснения, как он работает.
Антон пересказывает четыре уровня комментариев: интерфейсные — про поведение и структуру, а не перечисление методов; комментарии к полям структур — зачем поле и какие значения принимает; комментарии реализации — не пересказ кода, а контекст вроде требований стандарта; и «загадочный единорог», кросс-модульные комментарии, которые автор любит, но редко встречал.
Кросс-модульные комментарии автор предлагает держать в отдельном файле дизайн-заметок: он дальше от кода, зато даёт единый источник истины со ссылками вместо правки одного и того же в десятке мест.
Дальше идёт алгоритм: завести соглашения — для языков есть Javadoc, godoc, Doxygen с генерацией документации; не повторять код; и дать код новому читателю, спросив, сможет ли он восстановить из него такой же комментарий. Если сможет, комментарий, вероятно, лишь повторяет код.
Отдельный слайд — план документации интерфейса: поведение метода, параметры и возвращаемое значение, исключения, которых не видно в сигнатуре, и предусловия вызова.
Нейросети, имена и полугодовой баг
Восстановит ли посторонний такой же комментарий по коду? Этот критерий Антон считает устаревающим: по его объяснению, языковая модель может дополнить контекст благодаря похожим фрагментам из других проектов. Один из ведущих возражает, что человеку для такого пришлось бы держать в голове всю кодовую базу, — и участники шутят, что хорошие комментарии стоит писать хотя бы ради того, чтобы моделям было проще генерировать код.
Глава про имена начинается с истории бага, который автор искал полгода. Он писал со студентами распределённую файловую систему (рассказчик уточняет — «по-моему»), в ней плавал редкий баг, ученики сдались, а Джон нашёл причину не чтением кода, а постепенным сужением зоны поиска: переменная block означала то логический, то физический блок, и в одном месте на диск уходил мусор. При чтении ошибку не видел никто — из контекста всегда ясно, какой блок ожидается.
По мысли автора, разные имена для разных сущностей предотвратили бы эту ошибку. Отсюда рекомендации: имя создаёт образ в сознании читателя, а не писателя, требует точности и консистентности — источник и назначение называются из одного словаря, — а чем дальше объявление переменной от использования, тем длиннее должно быть имя. Из книги участникам запомнились вложенные структуры socket и sock: кто из них за что отвечает, докладчик уже не помнит.
Глава про «комментарии первыми» подкупает тем, что интересную концептуальную часть работы вы тратите на описание абстракций, а не на рутину в конце; это ещё и валидация дизайна — не получается написать комментарий, значит вы не понимаете, как всё устроено. Александр вспоминает совет писать сначала псевдокод и связывает главу со стратегическим программированием, а продакшен-код сейчас, признаются они с Антоном, пишут близко к никогда.
Последняя глава — про изменение кода: не дублировать, не уносить в сообщения коммитов то, чему место рядом с кодом, и при перечитывании собственного диффа перед ревью проверять, надо ли обновить документацию.
Итог: пять глав из двадцати двух — почти четверть книги; впереди, по словам ведущего, ещё шесть глав и финальный выпуск с зелёными и красными флажками, а комментарии участники сравнивают с хлебными крошками, ведущими к смыслу кода.
Что стоит унести с собой
- 01Отговорка «код документирует сам себя» разбивается о простую проверку: если код приходится читать, чтобы понять поведение, абстракция протекла — а Макконнелл, по словам Александра, имел в виду совсем не это.
- 02Комментарии распадаются на четыре уровня — интерфейс, поля структур, реализация и редкие кросс-модульные заметки; последние автор предлагает держать в отдельном файле дизайн-заметок как единый источник истины.
- 03Проверка «если комментарий восстанавливается по коду, он не нужен», по мнению Антона, устаревает: языковая модель достраивает контекст по похожему коду из других проектов, человеку же нужна вся кодовая база в голове.
- 04Полгода поиска бага из-за переменной block, которая означала то логический, то физический блок, — довод за точность имён: разные сущности должны называться по-разному.