Код с предупреждениями — правила работы с AI-помощником в проде price_parser.py · main · Claude Code 4.7 1 def parse_price_xlsx(path, schema): 2 # TDD: тесты в tests/test_parser.py — 47 кейсов 3 workbook = openpyxl.load_workbook(path) 4 rows = [] 5 # NB: пограничный случай НЕ ТРОГАТЬ — добавлено после инц. 2025-11-04 6 if cell.value is None : continue 7 price = decimal_from_cell(cell.value) 8 rows.append({"sku": ..., "price": price}) 9 return rows ! Не использовать без code review ! Прогнать regression suite CLAUDE.md обновлён decisions_log: запись #189 Tests: 47/47 PASS · 12.3s 5 правил применения AI-помощника ITfresh · Claude Code в коммерческих проектах · TDD + регрессия + ревью
Каждая строка кода, которую Claude отдаёт нам в репозиторий, проходит регрессионный набор и ревью человеком.
· 17 мин чтения · Семёнов Е.С., руководитель ITfresh

5 правил Claude Code в проде: что мы у клиентов не пускаем без присмотра

5 правил Claude Code в проде: что мы у клиентов не пускаем без присмотра

Представьте: у нас был клиент, крупная юрфирма с 35 рабочими местами прямо у Цветного бульвара. За полгода я и моя команда, используя Claude Code, успешно завершили для них четыре проекта. Что это было? Парсер прайсов от трёх разных поставщиков канцелярии, отчётность по часам юристов из Битрикса, удобный телеграм-бот для обработки заявок и даже интеграция 1С с почтовым шлюзом. Мой опыт чётко показал: с AI-помощником ты действительно ускоряешься в 2-3 раза. Но есть нюанс: без строгих правил он же запросто превратит проект в полную кашу буквально за две недели. Поэтому сегодня я поделюсь пятью правилами, которые мы в ITfresh тщательно обкатали и без которых ни один клиентский код у нас в прод не уходит.

Зачем мы вообще полезли в Claude Code

Знаете, в моей команде сейчас шесть инженеров. И что круто, трое из них не просто админят, но и отлично пишут код — на Python, PowerShell, а кое-что даже на Go. Но вот какая ситуация часто бывает: у клиента, скажем, на 35 человек, постоянно возникают такие, знаете, мелкие задачки. Типа, «ой, нам бы скрипт, который из выгрузки 1С сделает красивый Excel для бухгалтера». Сажать под это дело full-time разработчика — ну просто невыгодно. Раньше как мы поступали? Либо изобретали какой-нибудь костыль через макрос Excel, либо просто отказывались от такой работы, либо вообще нанимали фрилансера за свой счёт. Не самый лучший вариант, прямо скажем.

Но вот появился Claude Code, и с декабря 2025 года он стал для нас настоящим спасением! Теперь задачу, на которую раньше у инженера уходило 2-3 дня в обычном режиме, мы закрываем всего за 6-8 часов. Подумайте сами: юрфирма получает нужный скрипт буквально за один день, бухгалтер просто счастлив, мы продолжаем зарабатывать на абонентке без всяких потерь, а заказчик, что самое главное, больше не платит фрилансеру. Все в выигрыше!

Однако первый месяц, когда мы только-только подсели на Claude и, наивно, решили: «да ладно, он сам разберётся», — оказался, мягко говоря, тяжёлым. В репозитории клиента в какой-то момент появилось аж 11 функций parse_price_*. Почему? Потому что Claude каждый раз умудрялся писать новую, вместо того чтобы использовать уже существующую! А тесты, которые он сам же сочинял, всегда горели зелёным. Ну конечно, они же проверяли результат, который сам Claude и насчитал — идеальная круговая порука! В итоге мы потратили целых три дня на чистку всего этого бардака, и после этого я уже твёрдо решил: пора садиться и прописывать наши внутренние правила.

Правило 1. TDD — сначала тесты, потом код. Всегда.

Мой главный щит, если хотите, против Claude — это test-driven development, и я применяю его в самой жёсткой форме. Запомните: я просто не разрешаю Claude писать никакой production-код до тех пор, пока в репозитории не появится набор тестов, чётко описывающих то самое желаемое поведение. Вот так, никаких исключений.

Как это выглядит на практике

Вот смотрите, беру я задачу, например, «парсер прайса поставщика А». И сразу говорю себе: никакого claude code! Сначала я сам, своими руками, в редакторе VS Code, без всяких там ассистентов, создаю файл tests/test_parser_supplier_a.py. В него я закладываю 8-12 самых разных кейсов. Это может быть и нормальный файл, и файл с пустыми строками где-нибудь посередине, и с напрочь сломанной кодировкой, или даже файл с двумя листами. Я проверяю цены, которые могут быть через запятую или через точку, цену ноль, цену с пробелом-разделителем тысяч, и, конечно, ситуацию, когда отсутствует обязательная колонка. Вот так, сначала тесты, потом всё остальное.

# tests/test_parser_supplier_a.py
import pytest
from decimal import Decimal
from app.parsers.supplier_a import parse_price_xlsx, ParserError

def test_normal_file_returns_all_rows():
    rows = parse_price_xlsx("tests/fixtures/supplier_a/normal.xlsx")
    assert len(rows) == 1284
    assert rows[0]["sku"] == "ART-00001"
    assert rows[0]["price"] == Decimal("145.50")

def test_empty_rows_in_middle_are_skipped():
    rows = parse_price_xlsx("tests/fixtures/supplier_a/empty_rows.xlsx")
    assert len(rows) == 17

def test_comma_decimal_separator():
    rows = parse_price_xlsx("tests/fixtures/supplier_a/comma.xlsx")
    assert rows[0]["price"] == Decimal("99.90")

def test_missing_required_column_raises():
    with pytest.raises(ParserError, match="обязательная колонка price"):
        parse_price_xlsx("tests/fixtures/supplier_a/no_price.xlsx")

def test_zero_price_is_kept_not_filtered():
    # Бывает у поставщика когда товар "под заказ"
    rows = parse_price_xlsx("tests/fixtures/supplier_a/zero_price.xlsx")
    zeros = [r for r in rows if r["price"] == Decimal("0.00")]
    assert len(zeros) == 4

Только после этого даю Claude задачу: «реализуй app/parsers/supplier_a.py так, чтобы все тесты в tests/test_parser_supplier_a.py прошли. Не модифицируй сами тесты». В CLAUDE.md команды есть жёсткое правило: никогда не редактировать файлы из директории tests/, только из app/.

Чем это спасает

Без TDD Claude уходит в свободный полёт и пишет код, который проходит тесты, которые он сам же и сочинил. Был у меня случай: попросил без TDD написать парсер — он сделал. Прислал юрист настоящий файл прайса — а там половина строк пропущена. Зашёл в код: Claude поставил if cell.value and len(str(cell.value)) > 5: continue «чтобы пропускать заголовки», а реальные SKU поставщика как раз короче 5 символов. С TDD такая ошибка ловится тестом «test_short_sku_is_kept» в первый же запуск.

Правило 2. CLAUDE.md как долгая память проекта

Надо понимать, что Claude при каждом новом запуске видит наш проект как будто с нуля. Если не зафиксировать контекст прямо в файле, он будет постоянно изобретать велосипед — причём иногда правильно, а иногда и нет. Именно поэтому я теперь в каждом клиентском репозитории создаю в корне специальный файл CLAUDE.md. И Claude, умница, автоматически читает его каждый раз при старте. Это очень экономит время и нервы.

Что должно быть в CLAUDE.md

На примере проекта парсера прайсов для юрфирмы:

# CLAUDE.md — память проекта pricing-aggregator

## Контекст бизнеса
- Заказчик: юрфирма 35 РМ, ЦАО Москва
- Цель проекта: ежедневно собирать прайсы 4 поставщиков канцелярии
  и складывать в один Excel для офис-менеджера
- Запуск: cron на сервере APP01 в 06:30 МСК

## Архитектура
- Python 3.12, poetry, pytest
- app/parsers/ — по одному модулю на поставщика
- app/aggregator.py — собирает result в один Excel
- app/notifier.py — отправляет результат в Telegram чат -100123...

## Жёсткие правила
- НИКОГДА не модифицировать тесты в tests/
- Все цены — Decimal, никаких float
- Все сравнения SKU — case-insensitive через .upper()
- Кодировка входных Excel — может быть любая, openpyxl справится
- Если поставщик прислал файл < 100 строк — НЕ обновлять, прислать
  алёрт в Telegram, это признак что файл сломанный

## История инцидентов (НЕ удалять, читать перед изменениями)
- 2025-11-04: поставщик Б добавил столбец "Бренд" со скидками,
  парсер ловил скидку как цену. Решение — явный mapping колонок.
- 2026-01-18: SKU вида "0001" в Excel приходил как int 1, парсер ронялся.
  Решение — value.strip() или str(int) для числовых ячеек.
- 2026-03-22: cron начал падать с TimeoutError на скачивании файла
  у поставщика Г. Решение — таймаут 60 сек + 3 ретрая с backoff.

## Кого спрашивать
- Бизнес-вопросы — Семёнов Е.С., @ITfresh_Boss
- Доступ к данным поставщиков — кладовщик Сергей, +7 (903) ...

Файл architecture.md рядом

Ещё один документ — docs/architecture.md, где я расписываю модули и их связи. Не диаграмму UML, а текст: «модуль А вызывает модуль Б, на вход — словарь такой формы, на выход — список объектов такого типа». Этот файл я сам обновляю после каждого ревью, и Claude его читает.

Decisions log

Третья необходимая вещь, которую я требую, — это файл docs/decisions_log.md. Туда мы коротко, но ёмко записываем каждое решение, буквально: «почему мы сделали именно так, а не иначе». Например, на проекте юрфирмы у нас за полгода накопилось уже 189 таких записей! Это наша такая резервная память, очень нужная. Представьте: через год ты возвращаешься к коду и уже не помнишь, зачем тут какой-то странный if. У других подрядчиков, к сожалению, такие if'ы просто удаляют, а через неделю — бац! — инцидент. Мы так не хотим.

Правило 3. Регрессионный набор золотых данных

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

Как мы это организовали

Вот, например, для парсера прайсов мы используем 12 образцовых Excel-файлов. По 3 от каждого поставщика, чтобы охватить всё разнообразие. Один файл всегда самый свежий, так сказать, «нормальный». Второй — обязательно с какой-нибудь известной экзотикой, а третий — с краевыми случаями. И для каждого из них у нас чётко зафиксирован ожидаемый JSON-результат, который лежит в tests/fixtures/regression/golden/*.json. Никаких сюрпризов.

# tests/test_regression.py
import json, pytest
from pathlib import Path
from app.parsers import parse_by_supplier

REGRESSION_DIR = Path("tests/fixtures/regression")

@pytest.mark.parametrize("input_file", list(REGRESSION_DIR.glob("input/*.xlsx")))
def test_regression_against_golden(input_file):
    golden_file = REGRESSION_DIR / "golden" / f"{input_file.stem}.json"
    expected = json.loads(golden_file.read_text(encoding="utf-8"))

    actual = parse_by_supplier(input_file)

    # Сравнение по полному соответствию структуры
    assert len(actual) == expected["count"], \
        f"Количество строк изменилось: {len(actual)} != {expected['count']}"

    for i, expected_row in enumerate(expected["sample_rows"]):
        assert actual[i]["sku"] == expected_row["sku"]
        assert str(actual[i]["price"]) == expected_row["price"]

Когда Claude вносит правки и я выкатываю PR, GitHub Actions гоняет регрессию. Если она упала — значит, мы сломали что-то рабочее. Клиенту такой PR не уходит до выяснения, почему.

Чем это лучше юнит-тестов

Юнит-тест, по сути, проверяет что-то вроде: «функция X на вход [1,2] вернёт 3». А регрессия уже смотрит на картину целиком: «полный pipeline на реальном файле клиента даёт тот самый результат, который мы месяц назад зафиксировали как правильный». Понимаете, это как два разных щита, и мне нужны оба. Claude очень охотно проходит юнит-тесты, при этом запросто ломая интеграцию, — и он даже не понимает, что именно сломал, пока ты не покажешь ему diff golden-файла. Вот такой он, наш помощник.

Правило 4. Code review каждой строки человеком

Правило неудобное и медленное. Но альтернатива — катастрофа.

Как я это делаю

Каждый PR от Claude, который приходит в наш приватный GitHub, я обязательно проверяю лично. Я читаю diff целиком, вот прямо от корки до корки, не «скроллю» бездумно — я вчитываюсь в каждую новую строчку и каждую изменённую. На проекте парсера это занимает у меня 1-2 часа в неделю. А вот на проекте интеграции с 1С может уйти и до 3 часов. Да, это много. Но, честно говоря, это и есть та самая работа, за которую клиент мне платит. И я делаю её ответственно.

На что я смотрю в ревью:

Pre-commit и линт

Хорошо, что половину этих проблем отлавливает наша автоматика. У нас в каждом клиентском репозитории стоит вот что:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.5.0
    hooks:
      - id: ruff
        args: [--fix, --exit-non-zero-on-fix]
      - id: ruff-format
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.10.0
    hooks:
      - id: mypy
        args: [--strict, app/]
  - repo: local
    hooks:
      - id: pytest
        name: pytest
        entry: poetry run pytest -x --tb=short
        language: system
        pass_filenames: false
        always_run: true

Если у Claude в коде типизация поплыла — pre-commit его разворачивает ещё до коммита. Это ускоряет ревью: я не теряю время на формальные замечания, разбираю только смысловые.

Правило 5. Явные границы инициативы в промптах

Если ты скажешь Claude просто: «улучши парсер», — он с одного маху переименует пять модулей, добавит поддержку формата CSV, который ты вообще-то не просил, и обновит все зависимости в pyproject.toml. Это ещё хорошо, если только этим ограничится! А бывает, что он ещё и логику ретраев перепишет. Вот такой он, инициативный.

Как я формулирую задачи

Шаблон, по которому я даю Claude задачи в нашем общем командном чате:

# Задача: добавить поддержку CSV для поставщика Г

## Что нужно сделать
- Создать новый модуль app/parsers/supplier_g_csv.py
- Реализовать функцию parse_price_csv(path) -> list[dict]
- Покрыть тестами в tests/test_parser_supplier_g_csv.py
  (минимум 8 кейсов, по аналогии с supplier_a)

## Что НЕЛЬЗЯ делать
- Не трогать app/parsers/supplier_a.py, supplier_b.py, supplier_v.py
- Не модифицировать app/aggregator.py
- Не изменять pyproject.toml — все нужные библиотеки уже есть
- Не переименовывать существующие функции
- Не удалять и не менять тесты в tests/

## Где взять контекст
- CLAUDE.md в корне
- docs/architecture.md, секция "Парсеры"
- tests/fixtures/supplier_a/ как образец структуры

## Ожидаемый коммит
- Один файл новый: app/parsers/supplier_g_csv.py
- Один файл новый: tests/test_parser_supplier_g_csv.py
- Несколько новых fixture-файлов в tests/fixtures/supplier_g/
- Никаких других изменений

Жёсткий список «нельзя» работает. Без него я часами разбирался, что там Claude натворил, теперь — пять минут diff и в репо.

Что мы намерили: цифры со своих проектов

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

Проект                                    Без Claude   С Claude    Ускорение
parser-supplier-a (юрфирма)               21 ч.        7 ч.        3,0×
parser-supplier-g-csv (юрфирма)           12 ч.        4 ч.        3,0×
report-bitrix-hours (юрфирма)             18 ч.        9 ч.        2,0×
1c-mail-gateway (торговая комп.)          44 ч.        21 ч.       2,1×
telegram-bot-zayavki (торговая комп.)     16 ч.        5 ч.        3,2×
incident-debug-1c-print (торговая)        9 ч.         8,5 ч.      1,06×

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

Контр-нарратив: что вредно из популярных советов

Знаете, во многих YouTube-блогах на эту тему прямо-таки призывают к «vibe coding» — мол, просто болтай с Claude и принимай всё, что он тебе напишет. По моему опыту, это работает только до тех пор, пока твой проект не превышает 500 строк кода. После этой отметки начинается настоящая катастрофа! У меня был клиент, где прежний подрядчик именно так и делал: в итоге через четыре месяца они получили Python-проект на 14 000 строк, в котором было пять разных реализаций отправки email, три определения класса Order с совершенно разными полями, а тесты, по сути, проверяли ничто. В итоге мы просто выкинули 60% этого кода. Ужас.

Есть ещё один совет, с которым я категорически не согласен: «не тратьте время на CLAUDE.md, он и так умный». Нет, и ещё раз нет! Без CLAUDE.md Claude каждый раз будет изобретать архитектуру проекта заново, словно впервые. А вот если CLAUDE.md есть, он встраивается в уже существующую структуру буквально за пять минут. Поверьте мне, эта пара минут, потраченная на обновление файла, с лихвой окупается при каждом запуске. Это must-have.

Чего я не доверяю Claude совсем

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

А вот где я доверяю ему охотно, так это: парсинг файлов, генерация самых разных отчётов, веб-скрейпинг небольшого объёма, создание REST API для внутренних нужд клиента, разработка telegram-ботов и написание скриптов миграции из системы А в систему Б. Здесь он показывает себя отлично.

FAQ: что чаще всего спрашивают клиенты

Заменяет ли Claude Code обычного программиста?

Нет, и даже через два года он точно не заменит человека. Claude Code — это такой, знаете, инициативный junior, у которого энциклопедическая память, но почти нулевая ответственность. Рабочий код он, конечно, напишет за пять минут. Но вот через две недели без постоянного контроля у вас на руках окажется проект с дублирующимися функциями, абсолютно противоречивой архитектурой и тестами, которые, по сути, ничего не проверяют. Чтобы Claude приносил реальную пользу, рядом обязательно нужен senior-разработчик или администратор нашего уровня, который будет внимательно читать каждый коммит. Без этого никак.

Что нельзя писать в Claude Code, если работаешь с прод-системами клиента?

Запомните одно важное правило: в Claude Code ни в коем случае нельзя кидать боевые пароли, настоящие ключи API, дампы баз с персональными данными клиентов или реквизиты их контрагентов! Хотя Anthropic и не использует API-запросы для тренировки своих моделей, логи всё равно проходят через серверы в США. А это, извините, уже означает, что данные улетают за пределы и нарушается 152-ФЗ. Поэтому у нас в ITfresh для всех клиентских проектов мы используем приватный OpenRouter, в который встроен санитайзер. Он автоматически вырезает все паттерны паролей и ИНН перед тем, как данные куда-либо отправятся. Безопасность превыше всего.

Сколько времени экономит Claude Code на типовом проекте?

По нашим собственным замерам, которые мы делали на четырёх клиентских проектах за последние полгода, экономия по чистому времени написания нового кода составила от 2,1 до 3,4 раза! Скрипты миграций, парсеры выгрузок 1С в Excel, всякие нестандартные отчёты в SQL — вот здесь выгода просто огромная, максимальная! Но если говорить о сложной интеграции с тонкой бизнес-логикой, то выигрыш падает до 1,3-1,5×. Это потому, что гораздо больше времени уходит на тщательную постановку задачи и доскональную проверку. А на отладке боевых багов его помощь и вовсе почти нулевая — тут уже нужен настоящий инженер с глубоким контекстом.

Как контролировать качество кода, который пишет Claude?

У нас в работе есть три чётких уровня контроля. Первый — это TDD: мы сначала пишем тесты от руки, и только потом просим Claude реализовать тот код, который эти тесты успешно проходит. Второй — это необходимый регрессионный набор «золотых» данных. Например, для парсера прайса у нас есть 12 эталонных Excel-файлов и чётко зафиксированный JSON, который должен получаться. И, наконец, третий — это обязательный code review человеком: каждую строку, которую закоммитил Claude, я лично читаю глазами перед тем, как отправить клиенту. Без этих трёх вещей наш AI-помощник за неделю запросто превратит любой проект в настоящую свалку.

Где у Claude Code граница, после которой он ломает больше, чем чинит?

По моему опыту, к таким задачам относятся рефакторинг кода, которому уже больше двух лет, да ещё с совсем непонятной бизнес-логикой, а также бои с production-инцидентами. Новое Claude пишет просто чудесно, но вот в чужой, запутанной legacy он разбирается очень плохо. Он начинает «упрощать», теряя при этом важные пограничные случаи, которые прежний разработчик когда-то добавил после какой-нибудь конкретной аварии. На инцидентах он вообще любит «всё переписать» вместо того, чтобы просто найти один-единственный сломанный if. Поэтому на таких задачах я к Claude вообще не подхожу — сажусь сам и читаю код, тут без вариантов.

Итог

Итак, Claude Code — это настоящий рабочий инструмент 2026 года, и у нас в ITfresh он действительно ускоряет проекты для клиентов в 2-3 раза. Но, как я уже говорил, без жёстких правил он же эти проекты и ломает. Я лично обкатал пять ключевых правил на четырёх разных клиентских кейсах: TDD до написания кода, CLAUDE.md как наша внешняя память, регрессия с «золотыми» данными, обязательное ревью каждой строки и чёткие, явные границы инициативы. С этими правилами AI становится полноценным коллегой. А вот без них — он превращается в настоящую обузу.

Похожая задача в вашей компании?

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

Написать в Telegram  или  +7 903 729-62-41

Семёнов Е.С., руководитель ITfresh

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.