Claude написал фичу для моей Telegram Mini App. Я протестировал всё руками и вот что из этого вышло.
Начал проверять и нашел первый баг - данные не обновляются. Покопался, починил. Спустя пару часов второй - статус дуэли не меняется.
Уже примерно понимал о чём речь, за 14 минут починил. Проходит пару итераций и третий баг - символа не хватало в строке, и условие молча не срабатывало.
Три бага и одна причина - магические строки.
Открой свой проект и поищи что-нибудь типа 'completed'. Если нашёл в нескольких файлах, поздравляю, у тебя магические строки.
Голые значения в коде без имени: 'completed', 'creator', 'tiebreaker_time'. С числами та же штука: 8, 48, 3000. "Магические" - потому что через месяц ты сам не вспомнишь откуда взялось и почему именно столько.
В моём коде про новую фичу вышло так: 8 вопросов на дуэль и 48 часов на ответ. Оба числа были просто цифрами, раскиданы по файлам. Если я захочу поменять на 10 вопросов, то придётся искать все восьмёрки по проекту и молиться чтобы всё нашлось корректно.
На большие операции LLM может предложить скрипт - ведь зачем делать 50-100 итераций, когда можно написать скрипт и за 2-3 прохода все поправить?
Вот только не факт, что найденные 8 могли бы быть только из нужного кода. Что если другое магическое число поменяется, а я не узнаю? Что если тестов на эти функционалы нет?
Так и появляются баги и технический долг.
Что если LLM ошибся и опечатался? Написал
complited вместо completed. По факту у тебя ноль ошибок, но код молча пойдёт по другой ветке. И узнать получится только от пользователя, а может быть и вовсе - не узнаешь.Рассинхрон – вот это меня и кусало. Строка
completed в 4 файлах. Я менял логику, поправил в трёх, а в четвёртом забыл. Ну как забыл - я не знал что она там тоже есть. А query keys для React Query вообще были записаны по-разному: ['duels', 'my'] в одном файле, ['duel', code] в другом.Инвалидация кеша бьёт по ['duels']. Один компонент обновляется, два других показывают старые данные. Ошибок всё так же ноль.
И третье. Claude частенько генерит магические строки на автомате. Каждый промпт - это новая порция.
Он может забыть, что в прошлый раз написал
creator. В новом файле может написать 'author'. Та же логика, а строки разные. Хотя у меня конкретно такого не было, но это вопрос времени и кондиции системы.65 мест в 11 файлах
Столько я заменил когда собрал всё в константы. Думал будет больше, если честно.
Было: category: 'myTurn' | 'waiting' | 'completed'
Стало: category: DuelCategory
Один файл constants.ts, один источник правды. Опечатался в константе - TypeScript подчеркнёт красным до запуска. Поменял значение - поменялось везде. Поменял 8 вопросов на 10 - одна строка вместо поиска по проекту.
И да, TypeScript тут спасает. Playwright ловит сценарии, но опечатку в строке не поймает. А типы - поймают, очень удобно.
И чтобы Claude не генерил для тебя магические строки - добавь в CLAUDE.md:
"Никогда не используй строковые литералы для статусов, ролей, типов и ключей. Всегда выноси в именованные константы: enum, as const, const.
Числовые значения: лимиты, таймауты, размеры выноси в именованные константы с понятным названием."
И соответсвенно проверь то, что у тебя уже есть при помощи этого промпта:
"Найди все магические строки и числа в проекте. Покажи: 1) где одна и та же строка повторяется в разных файлах, 2) где числа используются без именованных констант, 3) предложи замену на enum или const объект. Сгруппируй по файлам."
Если решишь проверить проект, отпиши в комментарии, сколько их у тебя нашлось и как много файлов? Интересно, сколько нас таких 😎
