devnoize справочник

Уведомления и ревью

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

Ревью как канал сигнала

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

Отсюда правило, сформулированное во вводной главе: всё, что можно проверить автоматически, должно проверяться автоматически и до того, как изменение увидит человек.

Автоформатирование

Споры о стиле кода прекращаются в тот момент, когда стиль определяет программа, а не человек. Автоформатер переписывает код в единый вид, и обсуждать становится нечего. Важно не то, какой именно стиль выбран, а то, что он один и применяется без исключений.

Базовые настройки редактора стоит зафиксировать в корне проекта в файле .editorconfig — его понимают почти все редакторы и среды разработки без дополнительных расширений:

ini
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4

[*.{yml,yaml,json}]
indent_size = 2

[Makefile]
indent_style = tab

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

Линтеры

Линтер находит не стиль, а вероятные ошибки: неиспользуемые переменные, недостижимый код, сравнение с None через равенство, изменяемые значения по умолчанию в аргументах функций. Но линтер тоже может шуметь. Включённые «на всякий случай» все правила подряд дают сотни предупреждений, которые разработчики учатся подавлять, не читая.

  • Начинайте с небольшого набора правил, которые ловят настоящие ошибки, и расширяйте его постепенно.
  • Каждое правило либо блокирует слияние, либо выключено. Предупреждения, которые ни на что не влияют, никто не исправляет.
  • Подавление правила в конкретной строке сопровождается кратким объяснением причины.

Хуки pre-commit

Чем раньше обнаружена проблема, тем дешевле её исправить. Проверка на машине разработчика до коммита занимает секунды; та же проверка в CI — минуты и лишний цикл «отправил — дождался — исправил — отправил снова». Фреймворк pre-commit позволяет описать набор хуков в одном файле и одинаково запускать их локально и в CI:

yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-merge-conflict
      - id: check-added-large-files
        args: ["--maxkb=500"]
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.4.4
    hooks:
      - id: ruff
        args: ["--fix"]
      - id: ruff-format

Хуки локально легко обойти, поэтому те же проверки обязательно запускаются в CI — первым и самым быстрым заданием:

yaml
lint:
  stage: .pre
  image: python:3.12-slim
  variables:
    PRE_COMMIT_HOME: "$CI_PROJECT_DIR/.cache/pre-commit"
  cache:
    key:
      files: [.pre-commit-config.yaml]
    paths: [.cache/pre-commit]
  script:
    - apt-get update -qq && apt-get install -y -qq git
    - pip install -q pre-commit
    - pre-commit run --all-files --show-diff-on-failure

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

Настройка уведомлений

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

  • Подписка по участию. Уведомления приходят только по задачам и изменениям, где вы автор, рецензент или упомянуты, а не по всему проекту.
  • Автоматическое назначение рецензентов по файлу владельцев кода. Запрос приходит тем, кто отвечает за изменённую часть, а не всей команде.
  • Результаты CI — только о своих изменениях и только о падениях. Уведомление об успешной сборке не несёт информации: успех — ожидаемое состояние.
  • Разные каналы для разной срочности. Вызов дежурного — через систему оповещения, запрос ревью — через систему контроля версий, обсуждения — в чате. Смешивание всего в одном месте гарантирует, что срочное утонет.

Дайджесты вместо потока

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

Дайджест собирает такие события за период и доставляет одним сообщением в предсказуемое время: например, по понедельникам утром. Хороший дайджест короткий, сгруппирован по смыслу и начинается с того, что требует решения. Если в дайджесте нечего сообщить, его лучше не отправлять вовсе, чем отправлять пустой.

Проверка на полезность

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

Типичные ошибки

  • Ревью стиля руками. Любое замечание, которое повторяется больше двух раз, — кандидат в правило линтера или форматера.
  • Упоминание всей команды. Сообщение, адресованное всем, не адресовано никому. Лучше назвать одного ответственного.
  • Уведомления об успехе. Сообщения «сборка прошла», «задача обновлена», «проверка завершена» создают фон, на котором теряются сообщения о проблемах.
  • Одновременное включение новых правил линтера. Сотня новых предупреждений в один день приводит к массовому подавлению. Новые правила включаются по одному, вместе с исправлением существующих нарушений.

Итог

  • Ревью — для того, что может оценить только человек. Стиль и формализуемые ошибки проверяет машина.
  • Автоформатер снимает споры о стиле; внедряется одним отдельным изменением.
  • Линтер начинается с малого набора правил; каждое правило либо блокирует, либо выключено.
  • Хуки pre-commit дают быструю обратную связь локально, те же проверки обязательны в CI.
  • Уведомления — по участию, о падениях, а не об успехах; несрочное — в дайджест.