JavaRush /Курсы /Claude code /Evidence-based Q&A по codebase

Evidence-based Q&A по codebase

Claude code
7 уровень , 1 лекция
Открыта

1. Красивый ответ — ещё не знание

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

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

Отсюда правило:

Если у утверждения нет ссылки на код, тест, конфиг или вывод команды — это не факт, а гипотеза.

Это и есть evidence-based подход. Не недоверие к Claude Code, а смена роли: он не оракул, а быстрый помощник-исследователь. Ищет, суммирует, связывает куски проекта. Источник истины остаётся в репозитории.

Схема, которую держите в голове при каждом вопросе о проекте:

flowchart TD
    A[Вопрос о проекте] --> B[Ответ Claude Code]
    B --> C{Есть доказательства?}
    C -- Нет --> D[Считаем гипотезой]
    C -- Да --> E[Открываем файлы и проверяем]
    E --> F[Фиксируем подтверждённый вывод]

Что прошло через схему — переносите в CODEBASE_INVENTORY.md. Остальное живёт как гипотеза.

Спросите: «Как в Commerce OS подтверждается возврат денег?» Ответ «это делает администратор» бесполезен. Полезным он станет с цепочкой: маршрут, контроллер, проверка прав, сервисный метод, тест, возможно конфиг с порогом ручного подтверждения. До этого перед вами не знание, а уверенно изложенная версия.

2. Доказательства в codebase

Доказательство в репозитории — конкретная вещь, которую можно открыть глазами: файл, метод, тест, конфиг, лог, результат команды. Не «Claude сказал», а «вот место, где это видно».

Держите такую таблицу:

Источник Что он хорошо доказывает Чего он сам по себе не доказывает
Контроллер / маршрут Что существует конкретная HTTP-точка входа Что весь сценарий работает до конца
Сервисный метод Где живёт бизнес-логика Что этот путь реально вызывается пользователем
Тест Какое поведение ожидается в конкретном сценарии Что других сценариев не существует
Конфиг Порог, флаг, режим работы, адреса интеграций Что код действительно использует это значение именно так, как вы подумали
Вывод команды / лог Что произошло во время запуска или теста Почему это произошло, если вы не посмотрели код

Одного источника часто мало. @PreAuthorize("hasRole('ADMIN')") — сильный сигнал, но ещё лучше, когда рядом тест, проверяющий, что не-администратор получает 403 Forbidden. Тогда есть не только «так написано», но и «это проверяется».

Пример из Commerce OS. В модуле payments/ нашли контроллер:

@PostMapping("/api/orders/{id}/refund")
@PreAuthorize("hasRole('ADMIN')")
public RefundResponse approveRefund(@PathVariable Long id) {
    return refundService.approve(id);
}

Даже на старте Spring Boot читаются три вещи. @PostMapping — маршрут, URL запроса. @PreAuthorize — ограничение по ролям. Вызов refundService.approve(id) — управление уходит в сервис.

Тест рядом делает вывод надёжнее:

@Test
void approveRefund_rejectsNonAdmin() throws Exception {
    mockMvc.perform(post("/api/orders/42/refund")
            .with(user("ops").roles("SUPPORT")))
           .andExpect(status().isForbidden()); // 403 Forbidden
}

Теперь вы не угадываете по аннотации, а видите: пользователь с ролью SUPPORT не подтвердит возврат через этот HTTP-путь.

Конфиг достраивает картину:

refund:
  manual-approval-threshold: 100   # суммы выше 100 требуют ручного подтверждения

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

3. Вопросы Claude Code без фантазий

Чаще проблема не в том, что Claude Code ошибается, а в том, как вы спросили. «Как тут работает auth?» — для модели это просьба «расскажи что-нибудь умное и побыстрее». Она старается. Потом вы стараетесь понять, откуда она это взяла.

Хороший вопрос делает три вещи сразу: сужает область поиска, задаёт формат ответа под проверку и отдельно просит список предположений.

Сравните:

Слабый вопрос Сильный вопрос
«Как работает логин?» «Проследи путь логина от формы во фронтенде до сохранения сессии. Укажи файлы, методы, маршруты, тесты и всё, что ты не успел проверить».
«Кто подтверждает возврат денег?» «Покажи, какой HTTP-маршрут отвечает за подтверждение refund, где проверяются права, какой сервис вызывается и есть ли тесты на отказ для non-admin».
«Как устроены платежи?» «Объясни только сценарий ручного возврата денег. Не редактируй файлы. Для каждого шага укажи доказательство из кода или тестов».

Для Commerce OS хороший запрос может выглядеть так:

Объясни, как в этом проекте подтверждается возврат денег.
Проследи путь от HTTP-маршрута до сервисного метода и проверки прав.
Для каждого шага укажи:
- файл и метод
- что именно это доказывает
- есть ли тесты
- какие предположения ты сделал
- уровень уверенности: высокий / средний / низкий
Не редактируй файлы.

Здесь есть несколько важных деталей. Во-первых, вопрос не про «всю систему платежей», а про один конкретный сценарий. Во-вторых, вы просите не просто ответ, а структуру ответа. В-третьих, вы прямо разрешаете неопределённость: «скажи, что не проверил». Это очень полезно. Модель, как и человек, начинает думать аккуратнее, когда её просят не только утверждать, но и отмечать границы знания.

Ещё одна полезная привычка: один вопрос — одно поведение. Не надо в одном сообщении спрашивать и про логин, и про возвраты, и про фоновые задачи, и «кстати, где тут лежат миграции». Так вы сами же загрязняете контекст. Гораздо эффективнее задавать серию маленьких исследовательских вопросов. Это не медленнее — это просто дешевле по ошибкам.

4. Формат ответа, который удобно проверять

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

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

Шаблон может быть таким:

## Утверждение
...

## Доказательства
- файл:
- метод / маршрут:
- тест / команда:

## Что это доказывает
...

## Предположения / не проверено
...

## Уровень уверенности
высокий / средний / низкий

Почему это удобно? Потому что вы можете буквально идти сверху вниз и проверять каждый блок. Если в разделе «доказательства» пусто, перед вами, скорее всего, красивая догадка. Если в разделе «предположения» ничего нет, а тема сложная, это тоже повод насторожиться. В нормальном неизвестном проекте почти всегда есть вещи, которые не были проверены за один проход.

Вот как может выглядеть заполненный фрагмент по нашему примеру с refund:

## Утверждение
HTTP-подтверждение refund доступно только пользователю с ролью ADMIN.

## Доказательства
- `payments/RefundController.java`, метод `approveRefund(...)`
- аннотация `@PreAuthorize("hasRole('ADMIN')")`
- тест `payments/RefundControllerTest#approveRefund_rejectsNonAdmin`

## Что это доказывает
Маршрут `POST /api/orders/{id}/refund` защищён по роли ADMIN,
а пользователь с ролью SUPPORT получает 403.

## Предположения / не проверено
Не проверены фоновые jobs и внутренние batch-процессы, которые могут обходить HTTP-путь.

## Уровень уверенности
Высокий для HTTP-маршрута, средний для всей системы возвратов.

Заметьте, как меняется качество ответа. Он перестаёт быть «модель рассказала историю» и становится рабочей заметкой инженера. И вот такую заметку уже удобно сохранять в свои черновики, передавать коллеге или использовать позже, когда вы вернётесь к этому модулю проекта.

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

5. Польза assumptions и confidence в ответе

На этом месте многие новички думают примерно так: «Ну да, конечно, ещё просить у модели уровень уверенности... Может, ей ещё чай предложить?» Звучит немного занудно, но на практике это один из самых полезных приёмов. Когда вы просите Claude Code явно выписать assumptions, то есть предположения, и confidence, то есть уровень уверенности, вы фактически заставляете его отделять проверенное от додуманного.

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

Удобно держать в голове такую простую шкалу:

Уровень уверенности Обычно означает
Высокий Есть код, маршрут или метод, плюс тест или явный вывод команды
Средний Есть код и, возможно, конфиг, но нет теста или полного подтверждения сценария
Низкий Есть только косвенные признаки: naming, неполный trace, догадка по структуре проекта

Представьте, что Claude пишет: «Уверенность высокая». Что вы хотите за этим увидеть? Минимум два независимых источника: например, маршрут и тест. Если он пишет «средняя», это не плохо. Это честно. А честный средний уровень уверенности полезнее, чем фальшивый высокий. В инженерии вообще лучше аккуратное «не до конца проверено», чем бодрое «всё ясно», после которого падает прод.

Хорошая формулировка запроса может быть такой:

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

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

6. Ответ и код расходятся: перепроверяем

Самый интересный момент начинается тогда, когда Claude Code сказал одно, а вы открыли файл и увидели другое. У новичка в этот момент обычно две крайности: либо «модель тупит, всё пропало», либо «наверное, я не так понял код, пусть модель права». Обе реакции не очень полезны. Реакция инженера спокойнее: отлично, у нас есть конфликт, значит, нужно уточнить область утверждения.

Например, Claude говорит: «Refund может подтверждать только ADMIN». Вы открываете проект и находите ещё какой-нибудь RefundApprovalJob. Всё, паника? Нет. Первый вопрос теперь не «кто ошибся», а «о каком именно пути шла речь». Возможно, Claude описал только HTTP-маршрут, а вы нашли фоновую обработку. Это не обязательно противоречие: иногда это просто две разные точки входа в одну бизнес-область.

В таких случаях лучше переходить от общих вопросов к уточняющим. Например:

Ты описал HTTP-путь подтверждения refund.
Теперь проверь, есть ли в проекте другие пути подтверждения:
background jobs, scheduled tasks, internal service calls или batch-процессы.
Для каждого варианта укажи файл и степень уверенности.

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

git grep "approveRefund"                 # ищем все упоминания подтверждения возврата
git grep "manual-approval-threshold"     # ищем, где используется порог ручного подтверждения
./gradlew test --tests "*RefundControllerTest"  # прогоняем точечные тесты по возвратам

Даже если вы пока не очень уверены в консольных командах, логика здесь простая. git grep — это быстрый поиск по проекту. Он помогает не спорить на ощущениях, а проверить, сколько вообще мест в коде связано с интересующим поведением. А тесты показывают, какое поведение реально закреплено в проекте.

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

7. Сквозной пример Commerce OS: refund

Давайте теперь соберём всё вместе на одном цельном примере. Представим, что вы разбираете Commerce OS и хотите понять, кто именно может подтверждать возврат денег. Это реалистичный вопрос: он касается прав доступа, платежей и рисковых операций. Значит, красивый ответ без доказательств здесь особенно опасен.

Вы начинаете не с «Как тут устроены платежи вообще?», а с узкого вопроса:

Объясни, как в Commerce OS подтверждается возврат денег.
Сосредоточься только на ручном подтверждении refund.
Для каждого шага покажи:
- маршрут или точку входа
- файл и метод
- проверку прав
- наличие тестов
- что осталось непроверенным
Не редактируй файлы.

Допустим, Claude Code отвечает, что нашёл payments/RefundController.java, маршрут POST /api/orders/{id}/refund, аннотацию @PreAuthorize("hasRole('ADMIN')"), вызов refundService.approve(id) и тест approveRefund_rejectsNonAdmin. Уже неплохо. Но на этом мы не останавливаемся и открываем ключевые места.

Во-первых, смотрим контроллер:

@PostMapping("/api/orders/{id}/refund")
@PreAuthorize("hasRole('ADMIN')")
public RefundResponse approveRefund(@PathVariable Long id) {
    return refundService.approve(id);
}

Это даёт нам сразу три факта. Есть конкретный HTTP-маршрут. Есть ограничение по роли. Есть сервис, куда уходит бизнес-логика. Во-вторых, смотрим тест:

@Test
void approveRefund_rejectsNonAdmin() throws Exception {
    mockMvc.perform(post("/api/orders/42/refund")
            .with(user("ops").roles("SUPPORT")))
           .andExpect(status().isForbidden()); // 403 Forbidden
}

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

refund:
  manual-approval-threshold: 100   # суммы выше 100 требуют ручного подтверждения

После этого ваш уже проверенный вывод может выглядеть так:

## Утверждение
Ручное подтверждение refund через HTTP-маршрут доступно только ADMIN.

## Доказательства
- `payments/RefundController.java` → `POST /api/orders/{id}/refund`
- `@PreAuthorize("hasRole('ADMIN')")`
- `payments/RefundControllerTest#approveRefund_rejectsNonAdmin`
- `application.yml` → `refund.manual-approval-threshold: 100`

## Что это доказывает
HTTP-путь подтверждения защищён ролью ADMIN,
а возвраты выше 100 проходят через ручное подтверждение.

## Непроверено
Не изучены background jobs и внутренние сервисные вызовы вне HTTP-маршрута.

## Уровень уверенности
Высокий для HTTP-сценария, средний для всей подсистемы refund.

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

С этого момента отношение к вопросам по codebase заметно меняется. Вы больше не спрашиваете Claude Code «что тут происходит?» в надежде, что он окажется электронным шаманом. Вы задаёте исследовательский вопрос, требуете доказательства, разрешаете неопределённость и проверяете критические куски глазами.

Работа с AI перестаёт быть гаданием и начинает очень напоминать нормальную инженерную практику. А подтверждённые выводы потом спокойно ложатся в CODEBASE_INVENTORY.md: не весь диалог целиком, а короткое утверждение с пометками на источник и с записью, что ещё не проверено.

1
Задача
Claude code, 7 уровень, 1 лекция
Недоступна
Evidence-based вопрос к Claude Code о login flow
Evidence-based вопрос к Claude Code о login flow
1
Задача
Claude code, 7 уровень, 1 лекция
Недоступна
Review ошибочного AI-ответа про способ хранения сессии
Review ошибочного AI-ответа про способ хранения сессии
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ