Skip to content

Четыре самых частых задачи: изучение кодовой базы, исправление багов, рефакторинг, написание тестов

📚 Навигация по серии: В предыдущей статье [15 Как задавать вопросы и давать инструкции] мы научились "как правильно говорить" — разбивать размытые требования на точные инструкции. В этой статье мы посмотрим под другим углом: 80% повседневной работы сводится к этим четырем типам задач, и для каждой я дам вам шаблон инструкции, который можно просто скопировать, заполнить пробелы и использовать.

Ребята, сегодня поговорим о самом практичном.

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

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

Скажем так: универсальные навыки — это внутренняя сила (цигун), а эти четыре шаблона — боевые приемы. Внутреннюю силу вы уже натренировали, сегодня я передам вам приемы.

Прочитав эту статью, вы получите:

  • По одному готовому к копированию шаблону инструкции для четырех высокочастотных задач (изучение / исправление багов / рефакторинг / написание тестов).
  • Ключевое понимание "почему нужно делать именно так" для каждого типа, а не простое зазубривание шаблонов.
  • Шпаргалку по четырем типам задач, которую можно сохранить и использовать по мере необходимости.
  • Полный практический пример, который можно повторить с ожидаемым результатом (пройдем весь процесс исправления на реальном баге).

01 Для начала запомните: четыре вида задач, четыре инструмента

Перед тем как начать, давайте четко разделим "характер" этих четырех задач. Они предъявляют совершенно разные требования к Claude, и если использовать неправильный подход, результат будет намного хуже.

Аналогия: четыре инструмента в ящике, для каждого — свое применение. Отвертка нужна, чтобы закручивать винты, гаечный ключ — чтобы закручивать гайки. Если вы попытаетесь закрутить винт гаечным ключом, это будет неудобно. Изучение, исправление багов, рефакторинг, написание тестов — это четыре разных инструмента. Ключ не в том, "умеете ли вы использовать Claude", а в том, "какой инструмент достать для этой задачи".

Их главное различие кроется в одном измерении: трогает ли эта задача ваш код?

ЗадачаТрогает ли кодЧто в основном делает ClaudeЗа чем вам нужно следить больше всего
Изучение кодовой базыНет (только чтение)Читает файлы, объясняет вамПравильно ли он объясняет
Исправление баговДаИщет первопричину + исправляетПравильно ли найдена причина, есть ли регрессионный тест
РефакторингДа (но поведение не меняется)Эквивалентно переписываетНе изменилось ли поведение после правок
Написание тестовДобавляет файлыГенерирует тесты + покрывает граничные случаиВсе ли граничные случаи (edge cases) покрыты

Заметили? Изучение — это нулевой риск (он только читает, но не пишет), поэтому можно смело спрашивать обо всем; исправление багов и рефакторинг — это хирургическое вмешательство, нужно сначала попросить его объяснить, а потом уже позволять действовать; написание тестов находится где-то посередине — он создает новые файлы и не трогает ваш исходный код, но вам нужно следить, чтобы он не ленился и не тестировал только "нормальные условия".

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

💡 Итог в одном предложении: Сначала классифицируйте четыре типа задач по принципу "трогает ли код" — изучайте смело с нулевым риском, а при задачах с вмешательством сначала попросите его объяснить, а затем уже изменять.


02 Изучение незнакомой кодовой базы: от общего к частному, три уровня вопросов

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

Как это делалось раньше? Вы открывали папку, смотрели на десятки директорий в недоумении, кликали в каждый файл по очереди и через пару часов всё ещё ничего не понимали. Теперь в этом нет необходимости — Claude Code воспринимает текущую директорию как рабочую область. Он может сам прочитать весь проект, вам нужно только спрашивать.

Аналогия: вы приходите в новую компанию, вы не полезете сразу в исходный код какого-то модуля, а сначала зададите старожилам вопросы на трех уровнях. Первый уровень: "Чем вообще занимается наша компания и как выглядит общая архитектура?"; Второй уровень: "Где находится код, отвечающий за платежи?"; Третий уровень: "Как проходит путь заказа от оформления до списания средств в коде?". От общего к частному, от плоскости к линии — это стандартный ритм изучения.

Согласно демонстрации в официальной документации, этим трем уровням соответствуют три типа вопросов:

text
Дай мне общий обзор этой кодовой базы, расскажи об её основных архитектурных паттернах.
text
В каких файлах находится код, отвечающий за аутентификацию пользователей? Как эти файлы взаимодействуют друг с другом?
text
Отследи процесс входа в систему от фронтенда до базы данных.

Надежная привычка — задавать вопросы первых двух уровней в Plan Mode (режиме планирования) — то есть перед началом работы дважды нажать Shift+Tab, чтобы переключиться в режим планирования (первое нажатие переходит в acceptEdits, второе — в plan). Почему? Потому что на этапе изучения мы хотим, чтобы он только читал и рассказывал, и не хотим, чтобы он от избытка энтузиазма начал изменять файлы. В Plan Mode он не тронет ваш исходный код, и сколько бы вы ни спрашивали, он не изменит ни строчки вашего кода.

Например, взявшись за старый проект на Go на 30 тысяч строк, в первый день можно поступить так: сначала попросить "общий обзор", чтобы понять, на сколько сервисов он разделен, затем "где код, отвечающий за X", чтобы локализовать их по очереди, и наконец, выбрать ключевой путь "отследи, как проходит этот запрос". За полдня можно во всем разобраться, тогда как раньше на это ушло бы два-три дня.

Здесь я даю вам шаблон для изучения, просто заполните ключевые слова для вопросов трех уровней:

text
Я только что взялся за этот проект, помоги мне быстро вникнуть. Действуем в три этапа:
1. Дай мне обзор общей архитектуры, объясни основные модули и их обязанности.
2. В каких файлах находится код, отвечающий за [интересующая вас функция, например, «оплата заказа»]?
3. Отследи полный путь выполнения [какого-либо ключевого процесса, например, «от создания заказа до оплаты»].
Объясняй так, чтобы было понятно новичку, и пока не меняй никакой код.

💡 Итог в одном предложении: У изучения только один ритм — от общей архитектуры к конкретным файлам, а затем к цепочке выполнения, спрашиваем на трех уровнях от большего к меньшему, первые два уровня безопаснее всего спрашивать в Plan Mode.


03 Исправление багов: вставить ошибку → найти причину → исправить → добавить регрессионный тест

Исправление багов — это еще один высокочастотный вид задач, и в то же время самый подверженный сбоям.

Почему легко потерпеть неудачу? Потому что самая частая ошибка новичков: вставить ошибку и бросить фразу "помоги исправить", после чего Claude выдает способ, "заставляющий ошибку исчезнуть". Обратите внимание, "исчезновение ошибки" не равно "решению проблемы" — во многих случаях это просто маскировка симптомов, первопричина все еще там, и в следующий раз она вылезет снова.

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

В официальных лучших практиках неоднократно подчеркивается железное правило, которое стоит повесить на стену:

Исправьте это и убедитесь, что сборка прошла успешно. Устраните первопричину, а не подавляйте ошибку.

Поэтому правильный процесс исправления бага состоит из четырех шагов, и ни один из них нельзя пропустить:

  1. Вставить ошибку + шаги воспроизведения: полный текст ошибки, стек вызовов, а также "что я сделал, чтобы это произошло".
  2. Заставить его локализовать первопричину: сначала не позволяйте ему вносить изменения, пусть он четко объяснит, "почему возникла ошибка".
  3. Дать исправление: если первопричина определена верно, тогда разрешите ему вносить изменения.
  4. Добавить регрессионный тест: написать тест, который воспроизводит этот баг, чтобы гарантировать, что эта же ошибка больше не повторится в будущем.

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

Многие наступали на эти грабли. Например, исправили баг с парсингом даты, Claude быстро все поправил, ошибка исчезла, и код закоммитили. А через две недели другой коллега при рефакторинге вернул эту строку обратно, и тот же баг воскрес на том же месте — потому что не оставили тест, и никто не знал, что эту строку трогать нельзя. Поэтому при исправлении любого бага всегда должен быть четвертый шаг.

Вот вам шаблон для исправления багов:

text
Я столкнулся с багом.
Информация об ошибке: [полностью вставьте ошибку и стек]
Шаги воспроизведения: [что я сделал, чтобы вызвать её, это случайная ошибка или она воспроизводится всегда]
Пожалуйста:
1. Сначала локализуй первопричину, объясни, почему возникает ошибка, пока не меняй код.
2. Дай мне вариант исправления, который устраняет первопричину, не нужно просто маскировать ошибку.
3. После внесения изменений добавь регрессионный тест, который воспроизводит этот баг, и запусти его, чтобы убедиться, что он проходит.

💡 Итог в одном предложении: Исправление багов в четыре шага — вставить ошибку и шаги воспроизведения, сначала найти первопричину, затем исправить, и, наконец, добавить регрессионный тест; без этого "замка" в виде регрессионного теста тот же самый баг рано или поздно воскреснет.


04 Рефакторинг: сначала описать текущее состояние → задать цель → изменять мелкими шагами → тестировать до и после

Работа по рефакторингу имеет самый высокий риск, потому что вы трогаете "несломанный код".

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

Аналогия: делать ремонт в квартире, где живут люди, но так, чтобы жильцам не пришлось съезжать. Вы должны гарантировать, что вода и электричество работают как обычно, люди продолжают жить, вы просто красите стены и укладываете провода. Рефакторинг — это "ремонт с жильцами" — функции (жизнь жильцов) не должны пострадать ни на мгновение.

Поэтому безопасный подход к рефакторингу состоит из четырех шагов, суть которых в том, чтобы "намертво зафиксировать поведение с помощью тестов":

  1. Сначала попросить его объяснить текущее состояние: понять, что именно сейчас делает этот код и какие у него есть скрытые поведения.
  2. Четко сформулировать цель рефакторинга: вам нужно "разбить функцию на части", "переписать в современном стиле" или "избавиться от дублирования"? Укажите конкретно.
  3. Изменять мелкими шагами: официальные рекомендации четко советуют "рефакторить небольшими, тестируемыми инкрементами", не позволяйте ему переписывать все с нуля за один раз.
  4. Тесты должны проходить до и после изменений: перед рефакторингом запустите тесты, чтобы сохранить базовый уровень, после изменений запустите снова — оба результата должны совпадать.

Четвертый шаг — это жизненно важный орган рефакторинга. Если у этого кода сейчас нет тестов, то первый шаг рефакторинга — не изменять его, а сначала добавить тесты — сначала с помощью тестов "сфотографировать" "текущее поведение", как снимок, а после рефакторинга сверить со снимком. Рефакторинг считается успешным, только если поведение не изменилось. Это полностью совпадает с официальными лучшими практиками: дайте Claude способ проверить свою работу, иначе "выглядит правильно" будет единственным сигналом, а рефакторинг, который просто выглядит правильным, чаще всего таит в себе мины.

Здесь есть жесткое правило, которого стоит придерживаться: не позволяйте Claude напрямую рефакторить код, не покрытый тестами. Представьте ситуацию, когда вы в спешке просите его отрефакторить утилитарную функцию без тестов, и он "оптимизирует" граничную ветвь — эта ветвь выглядела как мертвый код, но на самом деле обрабатывала редкий ввод. Об этом вы узнаете только тогда, когда все сломается в продакшене. Всегда сначала добавляйте тесты, а потом уже рефакторите. Это немного медленнее, но зато вы больше никогда не перевернетесь.

Вот вам шаблон для рефакторинга:

text
Я хочу сделать рефакторинг [имя файла / функции].
Цель рефакторинга: [конкретно опишите, например, «разбить на более мелкие функции», «переписать в современном стиле», «устранить дублирование»]
Требования:
1. Сначала объясни текущее поведение этого кода, включая граничные случаи, которые легко упустить.
2. Если для него еще нет тестов, сначала добавь тесты, покрывающие существующее поведение.
3. Делай рефакторинг мелкими шагами, сохраняя внешнее поведение абсолютно неизменным.
4. Запусти тесты до и после рефакторинга, чтобы убедиться, что результаты совпадают.

💡 Итог в одном предложении: Жизненная сила рефакторинга — "поведение не должно меняться". Сначала опишите текущее состояние, затем задайте цель, вносите изменения мелкими шагами, намертво фиксируйте поведение тестами, которые проходят до и после; если тестов нет, сначала добавьте их, а потом действуйте.


05 Написание тестов: главное — заставить его покрыть граничные случаи

Последняя категория: добавление тестов к коду.

Claude на самом деле очень хорошо справляется с написанием тестов — он просмотрит ваши существующие файлы тестов и напишет их в соответствии с используемым фреймворком и стилем утверждений (assertions), стиль выровняется автоматически, вам не нужно его учить. Но вы должны знать об одной ловушке: если вы не дадите особых указаний, он по умолчанию будет тестировать только "нормальные ситуации".

Что значит тестировать только нормальные ситуации? Например, для функции деления он проверит "6 разделить на 2 равно 3" — это правильно, но что если разделить на 0? Что если передать отрицательное число? А что если передать null? Именно в этих "граничных случаях (edge cases)" и возникают настоящие баги, и именно их тесты должны покрывать в первую очередь.

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

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

Напиши тесты для foo.py, покрывающие граничный случай выхода пользователя из системы. Избегай использования mock.

Сравните два варианта запросов, и разница будет очевидна:

❌ Размытый запрос✅ Точный запрос
«Напиши тесты для этой функции»«Напиши тесты для функции divide, обратив особое внимание на такие граничные случаи, как деление на 0, отрицательные числа и нечисловой ввод»
Он протестирует только нормальный путь, покрытие будет искусственно завышеноОн протестирует места, где действительно может произойти сбой

Еще один небольшой совет: используйте @, чтобы напрямую указать ему целевой файл (напишите @src/utils/math.py). Он сначала прочитает файл целиком, прежде чем начать работу. Это намного точнее, чем описывать словами "та функция divide в том файле math". Использование ссылок @ обсуждалось в предыдущих главах, и здесь оно как раз кстати.

Вот вам шаблон для написания тестов:

text
Напиши тесты для [имя функции] в @[путь к файлу].
Требования:
1. Используй существующий в проекте фреймворк для тестирования и стиль утверждений (assertions).
2. Обрати особое внимание на покрытие граничных случаев: [перечислите все, что придет в голову, например, «пустой ввод, ноль, отрицательные числа, сверхбольшие значения, неправильные типы»].
3. Также помоги мне подумать, какие еще граничные случаи я мог не перечислить, и протестируй их тоже.
4. После написания запусти их все, и если есть упавшие, исправляй, пока не пройдут.

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

💡 Итог в одном предложении: При написании тестов не говорите просто "напиши тесты" — явно заставляйте его покрывать граничные случаи (пустые значения, нули, отрицательные числа, ошибки типов), а затем просите его дополнить те границы, о которых вы не подумали. Нормальный путь — это самое неважное.


06 Практика: пройдем процесс исправления на реальном баге

Просто посмотреть шаблоны недостаточно, нужно попробовать их на практике. Ниже мы используем "исправление багов" в качестве практического примера — в нем присутствуют все четыре шага, если вы его пройдете, остальные три типа сможете применять по аналогии. Здесь я специально спрятал настоящий баг, чтобы вы его исправили.

Шаг первый: создаем игрушечный проект с багом (Mac / Linux)

bash
mkdir bug-demo
cd bug-demo
echo 'def average(numbers):
    return sum(numbers) / len(numbers)' > calc.py

Пользователи Windows: mkdir и cd вводите так же, calc.py создайте в Блокноте и вставьте туда эти две строки на Python.

Функция average считает среднее значение, и с виду с ней все в порядке — но если передать пустой список, она сломается из-за деления на 0. Это и есть баг, который мы будем исправлять.

Ожидание: В папке bug-demo есть файл calc.py, содержащий эти две строки с функцией average.

Шаг второй: запускаем Claude Code

bash
claude

Ожидание: Появляется экран приветствия, внизу — поле ввода.

Шаг третий: применяем шаблон исправления бага, вставляем ошибку и просим исправить

В поле ввода введите (это тот самый заполненный шаблон из раздела 03):

text
Я столкнулся с багом.
Информация об ошибке: при вызове average([]) возникает ZeroDivisionError: division by zero
Шаги воспроизведения: если передать пустой список в функцию average в calc.py, баг воспроизводится 100%
Пожалуйста:
1. Сначала локализуй первопричину, объясни, почему возникает ошибка, пока не меняй код.
2. Дай мне вариант исправления, который устраняет первопричину, не нужно просто маскировать ошибку.
3. После внесения изменений добавь регрессионный тест, который воспроизводит этот баг, и запусти его, чтобы убедиться, что он проходит.

Ожидание: Claude сначала назовет вам первопричину — при пустом списке len(numbers) равно 0, и при делении на 0 происходит сбой; затем он предложит diff (например, возвращать 0 при пустом списке или выбрасывать более понятное исключение) и остановится, ожидая вашего одобрения. После одобрения он также создаст новый файл с тестами (например, test_calc.py), в котором будет отдельный тестовый случай для пустого списка.

Шаг четвертый: одобряем изменения, смотрим, как выполняются тесты

Поняв diff, выберите "Одобрить / Yes". Затем Claude запустит только что написанные тесты.

Ожидание: В терминале вы увидите результаты тестов, например:

text
test_calc.py::test_average_empty_list PASSED
test_calc.py::test_average_normal PASSED

Видите, что все тесты зеленые = этот баг исправлен, и на него повешен замок — если в будущем кто-то вернет эту строку, тест сразу же станет красным и забьет тревогу.

Шаг пятый: выходим, проверяем, что файл действительно изменился

Выйдите из Claude (введите exit или нажмите Ctrl+D), вернитесь в терминал и посмотрите:

bash
cat calc.py

(В Windows PowerShell используйте type calc.py)

Ожидание: В функцию average в файле calc.py уже добавлена логика обработки пустого списка, а в директории появился файл с тестами. Если это совпадает с одобренным вами diff = полный процесс исправления бага прошел успешно, поздравляем!

⚠️ Внимание: Если на третьем шаге Claude не написал тест по своей инициативе, скорее всего, вы удалили пункт 3 из шаблона. Не пропускайте эту фразу — именно замок в виде регрессионного теста отличает новичка от опытного разработчика.

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

Шпаргалка по четырем типам рабочих процессов


07 Краткие итоги

В этой статье мы разбили 80% вашей повседневной работы на четыре типа, и для каждого дали фиксированный подход и готовый к копированию шаблон:

ЗадачаСуть шаблона в одном предложенииЗа чем нужно следить внимательнее всего
Изучение кодовой базы«Общая архитектура → Где код для X → Отследи процесс»Спрашивать на трех уровнях от большего к меньшему, первые два в Plan Mode
Исправление багов«Ошибка и шаги воспроизведения → Поиск причины → Исправление → Регрессионный тест»Устранять причину, а не симптомы; не экономить на регрессионных тестах
Рефакторинг«Текущее состояние → Цель → Мелкие шаги → Тесты до и после»Поведение не должно меняться; если тестов нет, сначала добавить
Написание тестов«Напиши тесты, обрати внимание на пустые значения/нули/отрицательные числа/ошибки типов»Явно заставлять тестировать границы, затем просить восполнить пробелы

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

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


В следующей статье 17 «Изображения и мультимодальность» — до этого мы только "печатали инструкции", но некоторые вещи трудно объяснить словами: скриншот ошибки, дизайн-макет, диаграмма структуры базы данных. В следующей статье мы научим вас, как скармливать изображения напрямую в Claude, чтобы он работал, глядя на картинку. Подумайте сами: если бы вы могли просто скинуть ему тот скриншот ошибки, над которым ломали голову, разве это не сэкономило бы кучу сил?


Рекомендуем к прочтению