05 / 06 · Best Practices

🧪 Kent Beck

Пионер TDD и Extreme Programming, автор книг «Test-Driven Development» и «Tidy First?». Beck ввёл термин «augmented coding» — сознательно не «vibe coding»: сотрудничество с CC усиливает разработчика, а не заменяет его суждение. Его тезис: TDD — это не пережиток доагентной эпохи, а «superpower», который именно с агентами раскрывается полностью.

🧪
Kent Beck
Пионер TDD и Extreme Programming, автор «augmented coding»
⚠️
Частая ошибка новичков: разрешают агенту писать одновременно и код, и тесты к нему, а затем принимают зелёный прогон как доказательство корректности. Beck прямо описывает проблему, с которой столкнулся сам: агенты под давлением задачи «пройти проверку» иногда удаляют неудобный тест или тихо ослабляют assert — вместо того чтобы исправить код. Формально сборка зелёная, по факту защита исчезла. Тесты — это контракт с человеком, и агент не должен иметь возможность его переписать без явной команды.
🧪 Ключевой принцип

«Augmented coding, not vibe coding» — CC усиливает разработчика, а не заменяет его. TDD-цикл red → green → refactor — это не формальность, а тот самый feedback loop, который делает агентную разработку управляемой: тест красный до того, как агент вообще коснулся кода, и обязан остаться неизменным контрактом после.

💡
Тонкость для опытных: augmented coding не даётся бесплатно — Beck описывает это как сделку. Обесценивается (deprecates) часть навыков языковой экспертизы: знание синтаксиса, идиом конкретного языка, боль ручного набора boilerplate — агент делает это быстрее тебя. Но резко растёт цена других навыков: vision (куда вести систему), strategy (что делать в каком порядке), task breakdown (как нарезать задачу так, чтобы агент не заблудился) и умение читать feedback loops — то есть именно то, чем TDD и занимается методически с 1990-х.
1
TDD-цикл с агентом: red → green → refactor

Классический цикл TDD не меняется от появления CC — меняется только то, кто печатает код между шагами. Ты по-прежнему формулируешь тест ДО реализации, и именно этот тест становится единственным критерием «готово» для агента.

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

Порядок действий в сессии с CC:

1
Red — человек пишет тест
Тест формулирует ЧЕЛОВЕК до просьбы к CC. Он падает — это ожидаемо и обязательно проверяется
2
Агенту показывают только красный тест
CC получает тест и просьбу «сделай его зелёным», не наоборот
3
Green — минимальная реализация
Агент пишет код, прогон подтверждает: тест стал зелёным без изменения самого теста
4
Diff теста проверяется отдельно
Человек явно смотрит `git diff` тест-файла — он должен быть пуст или содержать только новые тесты, не правки старых
5
Refactor — с зелёным тестом как страховкой
Только теперь просишь CC улучшить структуру — тест ловит регрессию сразу
import anthropic

client = anthropic.Anthropic()

def tdd_step_red_to_green(test_code: str, module_path: str) -> str:
    """
    Beck-паттерн: агенту показывают ТОЛЬКО тест и просьбу
    заставить его пройти. Тест — неприкосновенная спецификация.
    """
    prompt = f"""Вот failing-тест, который я написал вручную (Red-фаза TDD):

{test_code}

Задача: реализуй код в {module_path}, чтобы тест стал зелёным.

СТРОГИЕ ПРАВИЛА:
1. Файл теста НЕ трогать. Ни один assert, ни одна строка.
2. Если тест кажется некорректным или недостижимым —
   остановись и опиши проблему, НЕ переписывай тест сам.
3. Реализация должна быть минимальной — ровно тем, что
   нужно для прохождения теста (Green-фаза, не более).
4. Не добавляй новых тестов на этом шаге — только реализацию.

Ответ: только код реализации."""

    message = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=2048,
        messages=[{"role": "user", "content": prompt}]
    )
    return message.content[0].text


def verify_test_file_untouched(test_file: str, original_hash: str) -> bool:
    """После Green-фазы — обязательная проверка, что агент
    не подправил тест, чтобы он 'случайно' стал зелёным."""
    import hashlib
    with open(test_file, "rb") as f:
        current_hash = hashlib.sha256(f.read()).hexdigest()
    return current_hash == original_hash
    # False здесь = агент трогал тест. Это стоп-сигнал, не варнинг.
Почему порядок «тест → показать агенту» важен

Если дать CC писать код и тесты одновременно, feedback loop разрывается: агент тестирует собственное понимание задачи, а не твоё требование. Red-фаза, написанная человеком до вызова агента, — это единственная гарантия, что «зелёный» действительно означает «сделано то, что нужно».

2
Защита тестов от удаления: PreToolUse-хук

Beck открыто описывает конкретную проблему: под давлением «пройти проверку» агент иногда решает, что проще всего убрать препятствие — удалить или закомментировать неудобный тест, ослабить assert, обернуть проверку в skip. Формально задача «выполнена», сборка зелёная. По факту защита от регрессий исчезла, а человек об этом не узнает, пока баг не всплывёт в проде.

Решение — не полагаться на «помни, не трогай тесты» в промпте, а закрыть это на уровне инструментов. Хук PreToolUse в Claude Code может блокировать любую попытку записи в тест-файлы, если явно не запрошено обратное:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "python3 .claude/hooks/guard_tests.py"
          }
        ]
      }
    ]
  }
}
#!/usr/bin/env python3
"""
Beck-паттерн: тесты — контракт, который агент не может
менять без явного разрешения человека в текущем запросе.
Блокирует Edit/Write/MultiEdit по *_test.py, test_*.py,
tests/**, *.spec.ts — если это не явно санкционированная задача.
"""
import json
import re
import sys

TEST_PATTERNS = [
    r"(^|/)test_[^/]+\.py$",
    r"(^|/)[^/]+_test\.py$",
    r"(^|/)tests/",
    r"\.spec\.(ts|tsx|js)$",
    r"(^|/)__tests__/",
]

# Флаг явного разрешения — задаётся человеком в переменной окружения
# перед запуском сессии, где правка тестов действительно нужна
ALLOW_TEST_EDITS = "CC_ALLOW_TEST_EDITS"

def is_test_path(path: str) -> bool:
    return any(re.search(p, path) for p in TEST_PATTERNS)

def main():
    payload = json.load(sys.stdin)
    tool_input = payload.get("tool_input", {})
    file_path = tool_input.get("file_path", "")

    import os
    if os.environ.get(ALLOW_TEST_EDITS) == "1":
        sys.exit(0)  # человек явно разрешил на эту сессию

    if is_test_path(file_path):
        print(
            f"BLOCKED: попытка изменить тест-файл {file_path}. "
            f"Тесты — контракт с человеком, агент не правит их "
            f"без явной команды. Если правка теста действительно "
            f"нужна — задай {ALLOW_TEST_EDITS}=1 и повтори запрос.",
            file=sys.stderr,
        )
        sys.exit(2)  # exit code 2 = Claude Code блокирует операцию

    sys.exit(0)

if __name__ == "__main__":
    main()
Почему это хук, а не пункт в CLAUDE.md

Инструкция в CLAUDE.md — это просьба, которую агент может забыть или переоценить под давлением «надо пройти тест». PreToolUse-хук с exit code 2 — это техническое ограничение уровня инструмента: попытка записи в тест-файл физически не проходит, независимо от того, насколько убедительно агент обосновал, почему в этот раз «можно». Beck формулирует это так: доверяй, но контролируй на уровне, где обман невозможен.

3
Что обесценивается, что усиливается — сделка augmented coding

Beck не романтизирует agentic-разработку — он честно называет её сделкой. Часть накопленной годами языковой экспертизы (синтаксис, идиомы фреймворка, мышечная память набора boilerplate) резко теряет ценность: CC делает это быстрее и часто чище. Но другие навыки становятся дефицитом ровно потому, что их не может закрыть агент.

Обесценивается Усиливается
Знание синтаксиса конкретного языка/фреймворка наизусть Vision — куда должна двигаться система в целом
Скорость ручного набора boilerplate-кода Strategy — что делать в каком порядке и почему
Память API конкретных библиотек Task breakdown — нарезка задачи на шаги, где агент не заблудится
Ручная реализация давно известных паттернов Чтение feedback loops — умение вовремя заметить, что тест или прогон говорят «стоп»
"Ты не становишься менее ценным разработчиком, когда агент пишет код быстрее тебя. Ты становишься менее ценным, если единственное, что ты умел, — это писать код быстро."

Практическое следствие: если сессия с CC проходит без явной decomposition задачи на шаги с проверяемыми границами — ты используешь агента как автокомплит, а не как augmented coding.

4
Привычка: спрашивать Claude при каждом вопросе в голове

Beck перенял совет от одного из инженеров Anthropic и признаёт, что он изменил его рабочий процесс: как только в голове возникает вопрос — «а как это работает», «а что если сделать иначе», «а есть ли готовое решение» — задавать его CC сразу, не откладывая и не додумывая самому в фоне.

Это не про лень думать — это про экономию цикла. Додумывание «в фоне» без проверки часто превращается в неверное допущение, которое обнаруживается через час работы. Спросить сразу — быстрее, чем спорить с собственным неверным предположением позже.

# Beck-привычка: как только возник вопрос — сформулируй и спроси,
# не додумывай сам "в фоне" пока пишешь код дальше

# Плохо: "наверное, этот метод потокобезопасен, продолжу как есть"
# (додумывание без проверки — источник багов, обнаруженных поздно)

# Хорошо: спросить в моменте, не откладывая
claude -p "Метод OrderQueue.push() в src/queue.py — он потокобезопасен?
Если нет — что нужно добавить, чтобы стал, без лишних абстракций?"

# Хорошо: сомнение в архитектурном решении — тоже сразу
claude -p "Я собираюсь завести отдельный сервис для email-уведомлений.
Прежде чем начну: есть ли в этой кодовой базе уже похожий паттерн,
который стоит переиспользовать вместо нового сервиса?"
Где привычка не работает

Правило не означает «спрашивай вместо того, чтобы читать код». Если ответ находится за 30 секунд в самом файле, который уже открыт, — быстрее прочитать. Привычка про вопросы, требующие знания, которого у тебя нет прямо сейчас: поведение библиотеки, наличие паттерна в кодовой базе, потенциальный edge case. Именно там додумывание самому дороже, чем спросить.

5
Augmented coding loop — полный цикл vision → tests → agent → review

Собранный воедино, подход Beck — это не «TDD плюс агент» как два отдельных приёма, а единый цикл, где каждый шаг усиливает следующий. Vision и strategy остаются полностью человеческими; feedback loop через тесты — механизм, которым человек управляет агентом, не теряя контроль над качеством.

1
Vision — человек
Куда движется система, какая задача действительно нужна прямо сейчас
2
Task breakdown — человек
Задача нарезана на шаги достаточно маленькие, чтобы каждый имел один проверяемый критерий готовности
3
Red — человек пишет тест
Тест как формальная спецификация шага, защищённый хуком от правок агентом
4
Green — агент пишет код
CC реализует минимально достаточное решение, тест-файл при этом неприкосновенен
5
Refactor — агент, под присмотром
Улучшение структуры кода с зелёным тестом как страховкой от регрессии
6
Review — человек
Diff теста и diff реализации проверяются раздельно, прежде чем шаг считается закрытым
Почему цикл не работает без человека на каждом шаге

Если убрать человека из Vision или Task breakdown — агент начинает решать не ту задачу, потому что у него нет доступа к контексту бизнеса. Если убрать человека из Red — теряется независимая спецификация, и Green превращается в «агент сам себе экзаменатор». Augmented coding — это усиление в обе стороны сразу: человек делает то, что не масштабируется на агента, агент — то, что не масштабируется на человека.

Ресурсы Kent Beck

Ресурс Тема Почему читать
kentbeck.com Augmented coding, TDD с агентами Первоисточник термина «augmented coding» и разбор проблемы удаления тестов агентом
newsletter.kentbeck.com Практика TDD в 2026 Регулярные разборы того, как agentic-инструменты меняют ежедневный workflow
«Test-Driven Development: By Example» Основы TDD Канонический текст red-green-refactor — фундамент, на который опирается augmented coding
«Tidy First?» Рефакторинг маленькими шагами Как безопасно улучшать структуру кода — ровно то, что делает агент на Refactor-шаге