Позвольте мне рассказать о самом дорогом «LGTM», который я когда-либо видел. Он был в запросе на включение, который выглядел достаточно безобидно — небольшое изменение в нашей логике обработки платежей. Рецензент, старший инженер, которого я уважал, одобрил его, оставив комментарий, который до сих пор преследует меня: «Отлично выглядит! Хорошая работа, что всё просто 👍».

Этот «простой» код был запущен и тут же дважды списал средства за заказы 847 клиентов во время Чёрной пятницы. Исправление заняло 3 минуты. А возврат средств, гневные письма и подпорченная репутация? На восстановление ушло несколько месяцев.

Вот что интересно: когда я позже спросил рецензента, он признался, что у него были опасения по поводу обработки ошибок, но он не хотел «создавать сложности», поскольку автор уже потратил на это время. Он был вежлив.

И в этом-то и проблема.

Пандемия вежливости в отзывах о коде

Ваши обзоры кода, вероятно, страдают от того, что я называю «параличом вежливости» — склонностью отдавать предпочтение вежливости перед полезностью. Это эпидемия в нашей отрасли, и она незаметно подрывает качество вашего кода.

Вот неудобная правда: большинство разработчиков предпочтут выпустить код с ошибками, чем задеть чьи-то чувства. Мы создали культуру, в которой «конструктивная критика» выродилась в «конструктивные любезности».

Рассмотрим реальные комментарии, которые я собрал из обзоров кода:

Вежливый комментарий:

«Отлично выглядит! Может быть, стоит добавить обработку ошибок, когда будет возможность 😊»

Полезный комментарий:

«Это вызовет необработанное исключение, если API вернёт null. Здесь нужна надлежащая обработка ошибок, прежде чем это можно будет объединить. Вот шаблон, который мы используем в других местах: [пример кода]»

Один комментарий делает всех счастливыми. Другой предотвращает сбои в работе.

Анатомия «вежливых» обзоров кода

flowchart TD A[Создан запрос на включение] --> B{Рецензент обнаружил проблему} B -->|Вежливый путь| C["Хм, может быть, упомянуть об этом мягко?"] C --> D["Отлично выглядит! Малое предложение..."] D --> E[Проблема отправлена в производство] B -->|Эффективный путь| F["Это нужно исправить"] F --> G[Чёткая, прямая обратная связь] G --> H[Проблема исправлена до слияния] style E fill:#ffcccc style H fill:#ccffcc

«Вежливый» обзор кода следует предсказуемому шаблону:

1. Тревога при выявлении проблемы Рецензент обнаруживает проблему, но сразу начинает сомневаться в себе. «Не слишком ли я придирчив? Не подумают ли они, что я создаю сложности?»

2. Ритуал смягчения То, что должно быть прямым отзывом, обёрнуто в слои вежливости:

  • «Небольшое предложение…»
  • «Небольшое замечание, но…»
  • «Возможно, стоит рассмотреть…»
  • «Когда будет время…»

3. Ловушка для побега Отзыв включает в себя разрешение полностью его проигнорировать. «Вы можете учесть это в последующей работе» — это кодовое выражение для «Я снял с себя ответственность».

4. Преждевременное одобрение Несмотря на выявление проблем, обзор всё равно одобряется. В конце концов, автор уже приложил усилия, верно?

Почему «вежливые» отзывы разрушают качество кода

Эффект размывания

Когда обратная связь слишком мягкая, критические проблемы теряются в шуме. Авторы учатся распознавать сигналы срочности. Если всё сформулировано как «предложение», ничего не кажется обязательным.

Я видел запросы на включение с 15 комментариями, в которых использовались такие слова, как «может быть» и «рассмотреть». Автор разумно предположил, что все они являются необязательными улучшениями, и объединил код, не устранив ни одной из проблем.

Проблема ложных срабатываний

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

Исследования показывают, что обзоры кода могут уменьшить количество ошибок примерно на 36%, но только если они действительно эффективны. Просмотр с галочкой и смайликами не приносит никакой пользы, создавая иллюзию контроля качества.

Упущенная возможность обучения

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

«Отличная работа! Всё отлично работает. Может быть, когда-нибудь подумать об крайних случаях.»

Что им нужно, так это:

«Эта функция не обрабатывает случай, когда userId равен null. Это вызовет ошибку 500. 
Вот как это исправить:
if (!userId) {
    throw new ValidationError('User ID is required');
}
Этот шаблон следует применять ко всем пользовательским вводам.»

Культурные корни вежливости в отзывах

Ловушка вежливости в открытом коде

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

Усилитель удалённой работы

Удалённая работа заставила нас быть ещё более осторожными в выборе тона. Без языка тела и выражения лица мы компенсируем это чрезмерной вежливостью. Каждый комментарий обёрнут в пузырчатую плёнку.

Щит синдрома самозванца

Многие разработчики используют вежливость как защиту от вида некомпетентности. «Кто я такой, чтобы критиковать код этого старшего разработчика?» Но для выявления ошибок опыт не требуется — свежее зрение часто замечает то, что упускает опыт.

Как на самом деле выглядят эффективные обзоры кода

Прямой, но не разрушительный

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

Неэффективно (слишком вежливо):

«В целом отлично выглядит! Интересно, может быть, стоит подумать о добавлении тестов? Не спешим! 😊»

Неэффективно (слишком резко):

«Нет тестов? Ты что, шутишь? Это мусор.»

Эффективно:

«Эта функциональность требует модульных тестов перед слиянием. Конкретно:
1. Протестировать успешный путь с допустимым вводом
2. Протестировать обработку ошибок для недопустимого ввода
3. Протестировать крайние случаи, такие как пустые массивы
Вот наш шаблон тестирования: [ссылка]»

Трёхуровневая система обратной связи

Классифицируйте свою обратную связь по степени важности:

🔴 Обязательно исправить (блокирующая):

  • Уязвимости безопасности
  • Логические ошибки
  • Проблемы с производительностью
  • Отсутствие обработки ошибок

🟡 Следует исправить (рекомендуется):

  • Нарушения стиля кодирования
  • Проблемы с поддерживаемостью
  • Доступны лучшие шаблоны

🟢 Можно исправить (желательно):

  • Микрооптимизации
  • Альтернативные подходы
  • Субъективные предпочтения

Пример реализации:

# 🔴 ОБЯЗАТЕЛЬНО ИСПРАВИТЬ: эту уязвимость SQL-инъекции нужно устранить
def get_user(user_id):
    query = f"SELECT * FROM users WHERE id = {user_id}"  # Уязвимо!
    return db.execute(query)
# Исправленная версия:
def get_user(user_id):
    query = "SELECT * FROM users WHERE id = %s"
    return db.execute(query, (user_id,))
# 🟡 СЛЕДУЕТ ИСПРАВИТЬ: рассмотрите возможность использования более описательного имени переменной
data = get_user_data()  # Какого рода данные?
user_profile = get_user_data()  # Намного понятнее
# 🟢 МОЖНО ИСПРАВИТЬ: это работает, но есть более лаконичный подход
result = []
for item in items:
    if item.is_valid():
        result.append(item.name)
# Альтернатива: [item.name for item in items if item.is_valid()]

Принцип «Потому что»

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

Слабо:

«Используйте const вместо let здесь.»

Сильно:

«Используйте const вместо let здесь, потому что эта переменная никогда не переназначается. 
Это предотвращает случайные изменения и сигнализирует о намерениях будущим читателям.»

Создание культуры конструктивной критики

Шаг 1: Установление контрактов на рецензию

Создайте явные соглашения о том, чего должны достичь обзоры кода. Вот шаблон:

## Наш контракт на рецензию кода
**Что мы рассматриваем:**
* Правильность (работает ли это?)
* Поддерживаемость (можно ли изменить это позже?)
* Производительность (достаточно ли быстро?)
* Безопасность (безопасно ли это?)
* Тестируемость (можно ли убедиться, что это работает?)
**Как мы даём обратную связь:**
* Будьте прямолинейны в отношении проблем
* Объясните, почему вы делаете предложения
* Классифицируйте обратную связь по степени важности
* Приводите примеры