Два лагеря спорят об одном и том же десятилетиями. Одни требуют комментировать каждую строку, другие гордо заявляют "мой код сам себя документирует" и оставляют после себя функцию из четырёхсот строк без единого пояснения. Обе крайности стоят дорого: в первом случае код зарастает комментариями-переводами, во втором знание о правилах живёт только в голове автора и умирает вместе с его отпуском. Стилевой стандарт Python PEP 8 существует с 2001 года и начинается с наблюдения Гвидо ван Россума: код читают гораздо чаще, чем пишут. Из этой строчки вырастает весь разумный подход к документированию: сначала сделать текст программы понятным, потом объяснить то, что в текст не помещается, и закрепить пояснения так, чтобы они не врали. У излишества и у молчания цена разная: первое тонет в шуме, второе в вопросах командного чата. Ниже разбор того, где проходит граница на практике.

Код читают чаще, чем пишут, и следствия для документирования

Число чтений одной строки за её жизнь измеряется десятками: автор перечитывает написанное, ревьюер проверяет, тестировщик разбирает сценарий, новичок изучает устройство, а через год автор возвращается к своему коду уже как чужой человек. Гвидо ван Россум заметил это в самом начале истории Python, и с 2001 года фраза о том, что код читают гораздо чаще, чем пишут, открывает официальный стилевой стандарт языка PEP 8. Гарольд Абельсон и Джеральд Сассман в классическом учебнике о структуре программ сформулировали то же самое жёстче: программы пишутся прежде всего для чтения людьми и лишь во вторую очередь для исполнения машинами. Мартин Фаулер в книге о рефакторинге 1999 года перевёл мысль в вызов: любой дурак напишет код, который поймёт компьютер, хороший программист пишет код, который поймёт человек. Следствие простое. Документирование не украшение после работы, а часть самой работы, и его качество измеряется не количеством комментариев, а скоростью, с которой новый читатель начинает понимать программу.

Экономика здесь безжалостна к обеим крайностям. Основная стоимость программы это не первый релиз, а годы изменений: правки, инциденты, доработки, миграции. Каждый час, потраченный командой на распутывание чужого кода, оплачивается по тарифу инженера, и сам потраченный час не двигает продукт. Новичок в первые месяцы почти только читает, и от качества прочитанного зависит, когда он закоммитит первую полезную правку: через три дня или через три недели. Документирование в широком смысле, имена, докстринги, тесты и пояснения, это ускоритель чтения, оплаченный однажды и работающий годами.

Скрытая статья расходов, вопросы. Каждое "как тут считается комиссия" в командном чате прерывает двоих: спрашивающего и того, кто отвечает по памяти, рискуя забыть деталь. Хорошо описанный код отвечает сам, и тишина в чате становится финансовым показателем.

Самодокументируемый код и его честные пределы

Самодокументируемый код это не лозунг, а набор конкретных приёмов. Имена говорят, что хранится и что происходит: pay_by_card вместо do_stuff, is_pensioner вместо flag1. Короткие функции делают путь чтения плоским, промежуточные переменные заменяют пояснение описательным именем, булевы литералы исчезают в именованных константах. Разница читается мгновенно:

create_order(user, True, False)
create_order(user, with_penalty=True, delayed=False)

Во второй строке вызов понятен без заглядывания в определение. Приёмы работают безотказно, но у них есть честный предел: имя объясняет, что делает код, и никогда не объяснит, почему код обязан делать именно так.

Пример предела. Возрастная скидка:

if user.age >= 65:
    user.discount = 10

Читателю ясно каждое слово, но неясно главное: откуда взялись 65 и 10, из закона, из договора или из решения продуктовой встречи трёхлетней давности. Именованные константы уточняют смысл:

PENSION_AGE = 65
PENSION_DISCOUNT_PERCENT = 10

if user.age >= PENSION_AGE:
    user.discount = PENSION_DISCOUNT_PERCENT

И всё равно источник правила остаётся за кадром. Самодокументируемость отвечает на вопрос "как", бизнес-правила живут в вопросе "почему", и в этот зазор текст программы не пролезает.

Комментарии объясняют причины, а не пересказывают операции

Комментарий нужен там, где заканчивается текст программы. Позиция зафиксирована давно: комментарий объясняет причину, а не переводит операцию. Стандарт PEP 8 требует, чтобы комментарии были законченными предложениями, и предупреждает прямо: комментарий, противоречащий коду, хуже отсутствия комментария. Плохой и хороший экземпляр различаются наполнением, а не длиной:

total = total + fee  # прибавляем комиссию к итогу
total = total + fee  # комиссия не входит в цену, пункт 4 договора

Первый пересказывает код и не сообщает ничего, второй несёт знание, которого в коде нет. Устойчивый фильтр из книги о рефакторинге звучит так: захотелось написать комментарий, сначала попробуй отрефакторить код так, чтобы комментарий стал не нужен. Осталось после фильтра, значит, комментарий настоящий: ссылка на пункт требования, предупреждение о неочевидном поведении, заметка о ловушке производительности или объяснение обходного пути сторонней библиотеки.

У полезных пояснений есть узнаваемые типы: ссылка на пункт требования или договора, причина неочевидного технического решения, предупреждение о поведении, которое выглядит ошибкой, но ею не является, пометка о временном обходном пути с номером тикета. Отдельный признак здоровой культуры в том, что команды не боятся удалять комментарии: строка, пересказывающая очевидное, обычно маскирует неудачную структуру, и в литературе о качестве кода её прямо сравнивают с освежителем воздуха. Код починен, пояснение больше не нужно.

Докстринги и стандарты описания публичных интерфейсов

Публичные интерфейсы документируют в специальном формате. Стандарт PEP 257 предписывает структуру: первая строка сжато отвечает на вопрос "что делает", за ней пустая строка, затем подробности, включая ограничения и то, что не вывести из сигнатуры. Докстринг скрипта работает как сообщение о правилах запуска и показывается при неверных аргументах.

def calc_penalty(amount: int, days_late: int) -> int:
    """Считает неустойку за просрочку платежа.

    Правило из договора: один процент от суммы за каждый день
    просрочки, максимум десять процентов. Округление вниз до копеек.
    """

Такие описания собираются в справочники автоматически: pydoc показывает их в консоли, Sphinx с расширением autodoc собирает сайт документации, rustdoc, javadoc и doxygen делают то же для своих языков. В Go принято начинать пояснение с имени сущности, а среди знаменитых поговорок языка есть строка "ясное лучше хитрого". Контроль покрытия описаниями доверяют линтерам pydocstyle и interrogate: они считают функции без докстрингов и ломают сборку в CI при снижении доли.

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

Тесты как исполняемая документация поведения

Тесты документируют поведение надёжнее любого текста, потому что не умеют врать: устаревший пример падает, устаревший комментарий просто продолжает существовать. Читаемые названия превращают набор проверок в спецификацию:

def test_discount_zero_for_adults():
    assert discount(30) == 0

def test_discount_ten_percent_for_pensioners():
    assert discount(70) == 10

Модуль doctest из стандартной библиотеки Python идёт дальше и делает примеры в докстрингах исполняемыми:

def discount(age: int) -> int:
    """Процент скидки по возрасту покупателя.

    >>> discount(70)
    10
    >>> discount(30)
    0
    """
    return 10 if age >= 65 else 0

Запуск командой python3 -m doctest file.py проверяет каждый пример, а pytest с ключом --doctest-modules включает их в общий прогон. Примеры перестают быть декорацией: изменение поведения сначала роняет докстринг и лишь потом чужой код. В сложных доменах та же мысль живёт в стиле "дано, когда, тогда": блоки подготовки, действия и проверки читаются как сценарий, и новый инженер изучает требования по тестам быстрее, чем по устаревшему описанию.

Работает и организационная сторона. Один тест проверяет одно поведение, шаги читаются сверху вниз, подготовка вынесена в понятные фикстуры, и файл тестов служит каталогом возможностей модуля. У исполняемых примеров есть и цена: они плохо подходят для проверок с побочными эффектами и внешними ресурсами, поэтому зрелые базы держат равновесие, простые функции получают примеры в докстрингах, сложные сценарии живут в обычных тестах с читаемыми названиями.

Реальная цена устаревших и лживых комментариев

У документации есть главный враг, и это не лень, а время. Код меняется каждую неделю, комментарий меняется, если о нём вспомнили. Строка, обещающая "здесь всегда блокировка", переживает три рефакторинга и продолжает обещать уже несуществующее. Стандарт PEP 8 формулирует жёстко: комментарий, противоречащий коду, хуже отсутствия комментария, а актуальность пояснений обязательна при каждом изменении кода. Цена измеряется часами: программист, поверивший лживой строке, строит на ней гипотезу, и опровергается она только отладчиком. Хуже единичной лжи разъедание доверия: прочитав два обманувших пояснения, инженер перестаёт читать любые, и команда теряет документацию целиком, сохранив её видимость. Отсюда рабочее правило: комментарий правится в том же коммите, что и код, а лживая строка приравнивается к багу.

Устаревание умножается копированием: пояснение переезжает вместе с кодом в три файла и врёт в каждом по-разному. Поэтому зрелые команды относятся к комментариям как к коду: у них есть ревью, стиль и право на удаление. Бесполезную строку вычёркивают без сожаления, ведь стоимость поддержки текста не ниже стоимости поддержки кода, а польза от мёртвой строки отрицательная.

Практический баланс для команды и кодовой базы

Командный баланс умещается в пять строк:

  1. сначала имена, структура и тесты, комментарии пишутся после того, как код уже стал понятным;
  2. публичные модули, функции и классы получают докстринг по структуре стандарта, с первой строкой-резюме;
  3. комментарии объясняют причины, ссылки на требования и ловушки, пересказ операций запрещён;
  4. примеры в докстрингах исполняются вместе с тестами и обновляются тем же коммитом;
  5. устаревший комментарий считается дефектом и чинится в том же тикете, что и код.

На ревью баланс проверяется одним вопросом: объясняет ли этот текст то, чего нет в коде. Если да, это документация; если нет, его место в корзине.

Измерить успех документирования можно одним числом: сколько дней проходит от прихода новичка до его первого осмысленного коммита. Команды с дисциплиной описаний укладываются в дни, команды с кодом-загадкой теряют недели и заодно узнают о скрытых правилах продукта из инцидентов.

Разумный итог не в выборе между лагерями, а в разделении труда. Код говорит, как устроена работа; докстринги говорят, что обещает интерфейс; тесты доказывают, что обещания выполняются; комментарии добавляют единственное, что не выразить иначе, причины и происхождение правил. Такой пакет не устаревает незаметно: падает тест или рушится пример, и документация сама требует внимания. Команде это экономит самый дорогой ресурс, часы понимания, а автору даёт тихую страховку: следующий читатель кода через год это он сам, и встреча пройдёт спокойно, если пояснения к тому времени не соврут.