Программирование с ИИ
ENRU
2.13

Чтение диффа

что именно изменил ИИ

Что это

Дифф (diff) — список изменений: что удалено, что добавлено. Когда ИИ правит код, читать надо именно дифф, а не файл целиком. Так видно ровно то, что поменялось, и ничего лишнего.

Это главный инструмент приёмки. Весь контроль над проектом держится на привычке смотреть дифф перед тем, как принять правку.

Как выглядит в коде

Просили починить KeyError при отсутствии города. Вот что пришло:

--- a/weather.py
+++ b/weather.py
@@ -2,6 +2,8 @@ import logging
 
 log = logging.getLogger(__name__)
 
+DEFAULT_TEMP = 0
+
 
 def fetch_weather(city: str) -> dict:
     data = call_api(city)
@@ -9,5 +11,5 @@ def fetch_weather(city: str) -> dict:
 
 
 def format_report(data: dict) -> str:
-    temp = data["main"]["temp"]
+    temp = data.get("main", {}).get("temp", DEFAULT_TEMP)
     return f"Сейчас {temp} градусов"

Как это читать

- в начале строки — строка удалена. + — добавлена. Строка без знака — контекст, она не менялась и показана, чтобы было понятно, где мы.

@@ -9,5 +11,5 @@ — указатель места: было пять строк начиная с девятой, стало пять начиная с одиннадцатой. Точные числа обычно не нужны, но по ним видно, сдвинулся ли файл.

--- a/ и +++ b/ — какой файл. При правке нескольких файлов таких блоков будет несколько.

Изменённая строка показывается как удаление плюс добавление. Пара -/+ рядом — это одна строка, которую переписали.

Что мы видим в этом диффе

Изменена одна строка. data["main"]["temp"] стало data.get("main", {}).get("temp", DEFAULT_TEMP).

Падать перестанет. Но теперь при ответе «город не найден» пользователь получит «Сейчас 0 градусов». Ошибка не починена — она спрятана, и спрятана так, что выглядит как настоящий ответ.

Это ровно тот случай из статьи 3.5: «убрать ошибку» и «починить причину» — разные задачи. И увидеть это можно только прочитав дифф: запуск покажет, что бот больше не падает, и создаст ощущение, что всё хорошо.

Как смотреть дифф

git diff                  # что изменено, но ещё не добавлено в коммит
git diff --staged         # что уже добавлено
git diff --stat           # только список файлов и число строк
git diff -- weather.py    # только один файл

Начинай со --stat. Одна строка вывода вместо ожидаемой одной — хорошо. Семь файлов там, где ждал один, — сигнал остановиться (статья 3.13).

измерено
 weather.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Порядок чтения

  1. --stat — сколько файлов и строк. Совпадает с ожиданием?
  2. Удалённые строки (-). Что исчезло? Удаление опаснее добавления: добавленный код хотя бы виден, а удалённую проверку заметить сложно.
  3. Добавленные строки (+). Делают ли они то, что просили?
  4. Что не поменялось, хотя должно было.

Второй пункт пропускают чаще всего, а он важнее третьего.

Как сказать ИИ

Запрос
Покажи дифф своих изменений, не весь файл.
Запрос
В этом диффе: меняется ли поведение программы для случаев,
которые раньше работали? Если да — для каких.
Запрос
Ты удалил строку с проверкой длины. Зачем?

Второй запрос — хороший способ самопроверки после большой правки, но помни: про свой код ИИ отвечает снисходительно (статья 3.8). Серьёзные диффы читай сам.

На что смотреть

Дифф больше ожидаемого. Правка на две строки с диффом на пятьдесят означает, что сделано что-то ещё.

Переформатирование вперемешку с правкой. Переставленные импорты, изменённые кавычки, переносы строк — настоящая правка тонет среди шума. Запрещать это надо заранее (статья 3.13).

Удалённые проверки. if not data: return, if len(text) > MAX — такие строки при переписывании теряются первыми и выглядят необязательными.

Молчаливая смена поведения. Как в примере: было исключение, стал ноль. Формально одна строка, по сути другая программа.

Изменения в файлах, о которых не просили. Смотри --stat первым делом.

Шпаргалка

  • - удалено, + добавлено, без знака — контекст.

  • Пара -/+ рядом — переписанная строка.

  • Начинай со --stat: сколько файлов и строк.

  • Удалённые строки читай раньше добавленных.

  • Ищи не поломку, а молчаливое изменение поведения.

  • Дифф больше ожидаемого — остановись и разберись.