- BrainTools - https://www.braintools.ru -

Десять лет в индустрии я писал код руками. Три месяца назад перестал

После выхода Claude Opus 4.7 стало очевидно, что агент технически быстрее меня. А 28 мая Anthropic выпустила Opus 4.8 с теми же ценами, заметно лучшим coding/agentic-скором и новой возможностью держать в голове миграции на сотни тысяч строк

И всё же расслабиться не выйдет, потому что есть нюанс: эрудиция у него принципала, а суждения джуна. Он знает двадцать способов решить задачу и ни одной причины предпочесть один другому – потому что не ему потом это поддерживать

Десять лет в индустрии я писал код руками. Три месяца назад перестал - 1

Если разобрать, чего именно ему не хватает, набирается ровно три вещи:

Памяти [1]. Каждая новая сессия начинается с чистого листа. Он не помнит, что вчера мы договорились не плодить feature-flags, что в прошлую субботу выпилили шесть классов-фабрик, что в этом сервисе моки в тестах под запретом. Без напоминания он повторит каждую ошибку [2], которую уже исправлял

Вкуса [3]. Он учился на усреднённом GitHub, а усреднённый GitHub это корпоративная Java с трёхэтажными try-catch и javadoc на сеттеры. Он искренне считает, что так и надо. Своего мнения «нравится / не нравится» у него нет, потому что он не писал код десять лет и не разгребал чужое наследие

Тормозов. По дефолту он хочет писать больше, а не меньше. Спросишь endpoint, получишь endpoint плюс DTO плюс feature flag плюс абстрактный базовый класс «на будущее» плюс параметризованный тест на пять кейсов. Сам он не остановится никогда

Знания принципала, поведение [4] задорного стажёра. Чтобы из этого вышел толк, кто-то должен играть тимлида – держать память, навязывать вкус, ставить тормоза. Этим я и занимаюсь. Причём сразу на трёх проектах

Три проекта

Я веду параллельно три проекта.

PulseLens. SaaS-аналитика для тимлидов. Java 21, Spring Boot, Postgres, мультитенантность, интеграции с GitLab, GitHub и Jira. Готовлюсь к US-launch

Luna Tarot. Telegram-бот с мистическим тарологом. Spring Boot + React Mini App, Claude Haiku 4.5 как голос Луны. Расклады, карта дня, эзотерический дневник

Третий проект. Python-пайплайн, скрапер плюс Gemini Flash для batch-разбора плюс Opus для финального аудита и генерации. Что именно делает, пока оставлю за кадром

Три разных стека, три аудитории, три домена. Один процесс работы с Claude и одна общая боль [5]: без правил его код за неделю превращается в кашу

Что не так с кодом по умолчанию

Чтобы было предметно – один простой запрос. Просишь «добавь endpoint для удаления пользователя» и Claude за минуту пишет рабочий endpoint. С правами доступа, транзакцией. И с горой лишнего…

  • Javadoc на четыре строки, где написано, что метод удаляет пользователя по ID.

  • Try-catch на EntityNotFoundException, хотя в проекте уже есть GlobalExceptionHandler.

  • DTO DeleteUserRequest с одним полем userId, хотя ID уже в path-параметре.

  • Feature flag app.users.delete-enabled, на всякий случай.

  • Где-нибудь if (user == null) throw... рядом с .orElseThrow().

Это не плохой код. Это код, усреднённый по GitHub

С тестами хуже. По умолчанию агент не пишет интеграционные тесты, он пишет «модульные» поверх моков. Мокирует репозиторий, сервис, базу. Тест зелёный, проверяет, что вызвался repo.save [6](). О том, что реальная JPA-связь сломалась, узнаёшь в проде. Стиль и уровень тестов нужно проговаривать явно

И отдельная боль, типовая для любого агента, это попытки обойти твою собственную систему проверок:

  • Возникает warning от PMD или SpotBugs, агент вместо рефакторинга ставит @SuppressWarnings("PMD.GodClass").

  • Тест мешает мержу, агент добавляет @Disabled с комментарием «фикс в следующем PR».

  • Покрытие упало ниже порога, агент понижает порог в build.gradle.kts с 85% до 80%.

  • Checkstyle ругается на длину метода, агент сверху лепит // CHECKSTYLE:OFF.

Агент оптимизирует на «билд зелёный», а не на «качество не упало»

Любопытно, что Anthropic это сама признала. В анонсе 4.8 написано прямо: новая модель «вчетверо реже оставляет недочёты в собственном коде без упоминания, чем предыдущая». То есть на этой проблеме инженерили специально. Значит, она остаётся и в 4.8, просто стала реже. Кнут всё равно нужен

Три уровня правил

Лечится это тремя уровнями – по одному на каждую дыру. Память лечит CLAUDE.md [7], вкус – .claude/rules/, тормоза – линтеры. Без всех трёх не работает: убери любой, и агент продавит брешь именно в нём

Три уровня правил

Три уровня правил

Уровень 1, против амнезии. CLAUDE.md [7] в корне. Не про код, а про продукт. Что делаем, для кого, в какой фазе, что в приоритете, какие архитектурные решения уже приняты. Claude читает этот файл в начале каждой сессии и сразу попадает в контекст, который иначе пришлось бы пересказывать каждый раз

В PulseLens 200 строк, в Luna Tarot 80, в третьем 50. Без этого файла любой запрос «добавь страницу X» превращается в «придумай продукт с нуля и добавь страницу X»

Уровень 2, против безвкусицы. Папка .claude/rules/ с императивными правилами. Это маленькие законы стиля, тестирования и архитектуры, которых у агента нет своих

.claude/rules

.claude/rules

Разнесены по файлам:

  • code-style.md [8]: функциональный стиль вместо циклов, Optional вместо null, никаких Object[] как контейнера, никаких хардкоженных строк вместо enum

  • testing.md [9]: только интеграционные тесты на реальном Postgres через Testcontainers. Моки только для внешних клиентов, всё остальное настоящее. AssertJ вместо JUnit-ассертов, новая фича плюс новый E2E в том же PR

  • architecture.md [10]: Controller только дёргает Service, репозиторий из контроллера запрещён, никаких God-классов

  • workflow.md [11]: каждая задача в отдельном git worktree, чтобы вести три фичи параллельно

  • definition-of-done.md [12]: что должно быть зелёным перед мержем

Эти файлы Claude видит в каждой сессии. Поведение [13] под их давлением выправляется не потому, что он «понял», а потому что правило всегда сверху

Уровень 3, главный. Против отсутствия тормозов. Линтеры и тесты.

Это единственный уровень, который агент не может обойти словами. Без него остальные два это пожелания, а не правила. Если у тебя нет третьего, не стоит начинать

Почему именно он главный разберем на примере: билд краснеет, агент предлагает: «добавлю @Disabled [14], фикс в следующем PR». Я не даю – и через две-три итерации он чинит по-настоящему. Уровни 1 и 2 он может уговорить словами. Линтер уговорить нельзя

Правило простое. Билд зелёный тогда PR мержится. Билд красный – никаких отговорок. Никаких @SuppressWarnings [15], никаких @Disabled [14], никаких пониженных порогов. Это прописано отдельным пунктом в definition-of-done.md [12], и я сверяю это в каждом ревью. Стандартный набор у меня и в PulseLens [16], и в рабочих сервисах:

  • Checkstyle: стиль, форматирование, импорты, длина методов, фигурные скобки

  • PMD: цикломатическая сложность, длина класса, дубли, антипаттерны, lambda-to-method-reference

  • SpotBugs: потенциальные баги, NPE, equals/hashCode

  • JaCoCo: покрытие по строкам/веткам/методам с порогами 85/70/87%

  • pg-index-health: здоровье схемы Postgres, ненужные индексы, отсутствующие FK, дубли, неоптимальные таблицы

  • Playwright: 20+ E2E-сценариев, прокликивают каждую страницу

Отдельно про JaCoCo. Пороги 85/70/87 это не потолок, а пол. Поднял новый код покрытие – порог в build.gradle.kts поднимается следом. Откатить назад уже нельзя: код, который завтра уронит покрытие, не пройдёт билд

В Luna Tarot набор тот же, без pg-index-health. В Python-проекте ruff, black, mypy.

CLAUDE.md [7] и .claude/rules/ это пряник. Линтеры и тесты это кнут. Без кнута пряник не работает

Конкретные примеры

PulseLens. Поймал Claude на хардкоде статусов:

List<String> stuckStatusNames = List.of("In Progress", "Code Review", "Testing");

Открыл code-style.md [8], добавил:

Запрещено хардкодить категории/типы как строковые литералы. Использовать enum в domain/model/enums/. Default-значения брать из enum.

Пять PR подряд, ни одного хардкода

Luna Tarot. Тянул фичи про запас: feature flag для тестового режима, интерфейс TarotEngine под одну реализацию, кеш с TTL. В CLAUDE.md [7] появилось:

Не добавляй интерфейсы там, где одна реализация. Не добавляй feature flags для функций, которые ещё не нужны. Три похожих строки лучше преждевременной абстракции. YAGNI.

Сработало на 70%. Остальное ловлю в ревью

Что осталось мне

Руками я почти не пишу. Что делаю:

  1. Формулирую задачу через код и контекст. Не «добавь страницу», а постановка с привязкой к конкретным репозиториям, моделям БД, компонентам. Половина промпта — про то, чего делать НЕ нужно: «не трогай топбар, не меняй URL других страниц». Чем точнее границы, тем меньше потом работы на ревью. Саму постановку всё чаще делает Claude: обсуждаю задачу с агентом в чате, он через MCP заводит тикет в трекер Jira и RFC/ADR на Confluence. Репозитории и схема БД у него уже на входе – поэтому формулировка выходит конкретной, а не «нужно, чтоб работало»

  2. Согласовываю план до кода. Для всего нетривиального сначала «опиши, какие файлы создашь, какие тронешь, какие модели изменишь». Читаю, спорю. Потом – «делай»

  3. Делаю code review каждого PR двумя слоями. Первый отдельной сессией Claude в режиме «найди проблемы, не пиши код» по чеклисту правил. Второй – сам, глазами, по диффу. Системную проблему, пойманную дважды, закрепляю правилом – как с хардкодом выше. Оно встраивается в pipeline и работает на следующих PR автоматически

  4. Запускаю продукт сам. Резонный вопрос: зачем, если есть тесты? Затем, что тесты проверяют «правильно», а не «хорошо». Зелёный билд гарантирует, что ничего не сломалось и регрессий нет, и это снимает с меня девяносто процентов. Но оставшиеся десять не ловит ни один тест: 300 мс лага на кнопке, рваную анимацию, модалку, которая открывается на полкадра позже, текст, который технически верный, но звучит не как наш бренд. Это видно только глазами и пальцами. Поэтому каждую фичу я прокликиваю руками – не вместо тестов, а после них

Аналогия

Когда люди пересели с пеших переходов на лошадей, скорость выросла в десять раз. Но лошадь это не бесплатный мотор. Её надо кормить, поить, чистить, подковывать, лечить, выгуливать, объезжать. Без этого лошадь либо встанет, либо понесёт

С агентом то же самое. Claude это не бесплатный код. Его надо кормить контекстом (CLAUDE.md [7]) и деньгами (подписка), учить правилам (.claude/rules/), держать в стойле линтеров (билд-проверки), регулярно объезжать (code review)

Помогать агенту это не про вежливость. Это про то, чтобы он работал на тебя, а не против тебя

Сейчас я думаю так. Claude начинает заменять руки. Голова нужна как раньше, а вкус даже сильнее

Автор: igoresha_s

Источник [17]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/31129

URLs in this post:

[1] Памяти: http://www.braintools.ru/article/4140

[2] ошибку: http://www.braintools.ru/article/4192

[3] Вкуса: http://www.braintools.ru/article/6291

[4] поведение: http://www.braintools.ru/article/9372

[5] боль: http://www.braintools.ru/article/9901

[6] repo.save: http://repo.save

[7] CLAUDE.md: http://CLAUDE.md

[8] code-style.md: http://code-style.md

[9] testing.md: http://testing.md

[10] architecture.md: http://architecture.md

[11] workflow.md: http://workflow.md

[12] definition-of-done.md: http://definition-of-done.md

[13] Поведение: http://www.braintools.ru/article/5593

[14] @Disabled: https://www.braintools.ru/users/Disabled

[15] @SuppressWarnings: https://www.braintools.ru/users/SuppressWarnings

[16] PulseLens: https://pulselens.io/

[17] Источник: https://habr.com/ru/articles/1041296/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1041296

www.BrainTools.ru

Rambler's Top100