Pull to refresh

Comments 38

Спасибо за статью, пока читал, аж пульс повысился))

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

Хорошее предостережение. Я ожидал, что такие задачи должны для claude быть прям тривиальными, все таки очень мало творческой части, формальное преобразования одного диалекта в другой, а оказывается и тут все не так просто.

Проблема в том, что невозможно толком его консервативностью управлять. Ну т.е. с человеком можно договориться, с чатботом нельзя. Можно только надеяться.

Если ты позовешь собаку - она придет. Если кота - он, возможно, примет во внимание.

Было бы интересно узнать сколько PR пришлось возвращать на доработку и сколько реальных косяков всё-таки пропустили (но это через годик). И сколько все денег по итогу стоило...

По возвратам примерно каждый пятый PR шёл на доработку, чаще не из-за ошибок а из-за того что Claude выбирал тип который формально правильный но не наш паттерн. Реальных косяков в продакшене не было, но именно потому что тестовое покрытие держали жёстко, без этого страшно даже думать. По деньгам вышло примерно $800-850 на токены за весь проект, это в два-три раза дешевле ручной работы если считать честно с зарплатой.

С человеком тоже не всегда договоришься, особенно если это джун, дорвавшийся до рефакторинга. Нейронке хотя бы можно жесткие системные промпты прописать и она не будет обижаться

Я тоже так думал пока не начали. Типы это самое простое, дальше идут conditional types, overloads, дженерики которые Claude пишет корректно но не так как я написал бы сам, и потом ревью которое в итоге съело больше времени чем сама миграция. Формально один диалект в другой, по факту архитектурные решения пачками.

Думаю многим нейросетям сейчас не хватает одного - приостановка написания кода и уточнение вопросом по типу: «я хочу преобразовать этот кусок кода таким образом, но не уверен, так ли надо сделать конкретно в этой ситуации?». Это и количество потраченных токенов уменьшило бы, да и время потраченное на рефакторинг кратно снизилось.

У меня было такое, что агент остановился и задал вопрос. Но только один раз такое было.

В курсоре есть plan mode и он вполне переспрашивает, показывает план того что будет делать итд итп.

Но радости от этого немного. Если всё это проверять, то ... оно конем, проще и быстрее сделать самому.

Речь о том, что у меня именно во время исполнения остановился задать вопрос. Причем не локальный агент, а облачный.

Согласен, у нас это решалось через правило в CLAUDE.md что перед изменением публичных интерфейсов надо выписать план и дождаться ок. Не идеально, иногда пропускал, но лучше чем ничего. Хочется чтобы это было встроено в модель, а не костыль через промпт.

Современные агенты уже умеют делать паузы через вызов специальных тулзов для запроса апрува у юзера. Нужно просто правильно настроить песочницу перед запуском скрипта

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

Справедливо, не буду спорить. Статья писалась быстро и этот слой не отработал как надо, чувствуется. Принял, следующие буду вычитывать именно на этот критерий отдельно.

Слышу. Следующая будет лучше.

Год назад Claude вроде такого не умел, а проект стартовал не ранее сентября 2025 года, судя по статье (6 месяцев + 10 недель)

Да, примерно так. Шесть месяцев это общий стаж с Claude Code, конкретная миграция шла около десяти недель. Стартовали в районе конца лета 2025, тогда Claude как раз вышел на уровень где результат был предсказуем, не в теории а на практике.

Про silent logic change — тот же класс ошибок у меня на компиляторе. Был план, где агент перетипизировал утилитную функцию, тесты прошли, а через день я случайно открыл вызов из другого модуля и увидел что возвращается не то.

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

5-15 файлов в батче — это эмпирика? У меня плавает.

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

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

Финальное «годен/негоден» всё равно у меня. Цепочка агент → критик → я. Без понимания бизнес-логики на моей стороне ничего не починить, тут согласен.

Провисшие допущения, хороший термин. У нас были такие же случаи, план фиксировал инвариант, критик его не оспаривал, а оспорить надо было. Добавил в процесс шаг: после закрытия плана явно перечисляем каждое допущение и задаём вопрос «что если это неправда». За два месяца поймали так три кейса, один из которых точно ушёл бы в прод без этого.

Да, именно такой кейс. Скомпилилось, тесты зелёные, а в runtime ведёт себя иначе. Второй агент который смотрит на допущения после закрытия плана, хорошая идея, беру в копилку. У нас такого не было только потому что ревью делал вручную после каждого батча. По 5-15 файлам да, эмпирика. Плавает от размера и плотности типов. На простых утилитах можно и 20, на файлах с дженериками лучше ближе к 5. Ориентировался на то когда начинал чувствовать что контекст расплывается.

Про плотность типов точно, у меня то же на плотности абстракций в плане. На задачах вида «поправить дженерик в трёх местах» батч держит 10-15 файлов. Когда план трогает type inference, режу до 3-5; дальше агент теряет нить между файлами. «Контекст расплывается» это в точности то ощущение, что у тебя на дженериках.

Плотность абстракций лучше описывает проблему чем размер батча. У меня похожая точка разреза: сколько разных файлов нужно держать в голове чтобы принять одно решение. Три и меньше, батч большой. Пять и больше, режу агрессивно. С type inference всё сложнее, там решения каскадируют и часто не видно заранее насколько далеко цепочка тянется.

Промпты с явным указанием контекста вызовов работают отлично, забрал себе на заметку. Жаль только что вся эта магия рассыпается, как только у тебя в базе появляется хитрая фабрика с динамическими импортами

С фабриками и динамическими импортами боль понятна. У нас таких мест в проекте хватало, и там я работал руками. Просто не доверял агенту когда зависимость не прямая. Это пока нерешённый класс проблем, у меня во всяком случае.

Логически «правильно» — типы проставлены верно. Но поведение изменилось: null теперь рендерится как строка "null" вместо пустой строки. В продакшене это сломало отображение имён пользователей у которых не заполнено поле.

Это говорит о том, что у вас не хватает юнит тестов.

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

Занимаюсь типизацией больших проектов на Python. Без предварительного покрытия тестами всяких граничных случаев получаем много ошибок. Плюсом получаем дополнительные проверки и более надёжный код.

Согласен. У нас тесты на бизнес-логику были, а вот граничные случаи, null, undefined, пустая строка, не везде. Именно там и поймали. Теперь это первое что проверяю перед тем как запускать миграцию.

Что действительно хорошего принесли нам модели это за секунды получить все эти тесты которые никто не хочет писать и отнимают уйму времени.

Раньше делали спеки со всеми граничными случаями , потом начали забивать на это.

А сегодня это всего лишь вопрос желания и понимания.

Именно. Мы раньше тоже срезали на граничниках, “потом допишем”. Потом превращалось в никогда. Сейчас описываю кейсы словами, Claude пишет тесты за минуту. Уровень покрытия вырос, и это не заслуга дисциплины, просто стоимость написать тест упала до нуля.

Очень рад, что к вам в команду пришло поднимание.

У меня пока это не встречается с большим энтузиазмом.

Покрытие простых случаев до сих пор считается как ненужные проверки.

Хотя тоже какая разница. Это бежит миллисекунды и требует 0 времени на поддержку сегодня.

Знакомо. У нас тоже поначалу называли это “ненужными проверками”. Переломный момент был когда именно простой граничный случай сломал прод. После этого разговор стал другим.

Высокий уровень покрытия не отражает качество тестов, вообще никак. Тесты, которые тестируют некачественно права на жизнь не имеют.

Согласен. Я имел в виду не процент, а сам факт что граничные случаи теперь описаны и проверены, пусть и несовершенно. До этого их не было вообще. Процент сам по себе не метрика.

Процент это да метрика просто надо правильно работать.

Покрытие 50% это хорошо, 70% отлично, а если ниже 30% это повод задуматься, скорее всего, и обычно так, у нас мало проверок.

А что такое некачественно?

Положим у нас JS функция sum(a,b) ожидает объект.

По вашему проверки на null, undefined,NaN не нужны ведь этого никогда не произойдёт?:)

Sign up to leave a comment.

Articles