Курсор агент или чат: как навести порядок в чужой функции
Курсор агент ищут, чтобы нейросеть сама почистила код. Это статья LibraChat: до и после рефакторинга функции расчёта заказа, девять правок и что каждая меняет.
Евгений
Дизайнер-партнёр LibraChat
8 мин чтения
Функция расчёта заказа на сайте знакомого магазина была записана в одну строку. Скидка, доставка, цикл по товарам, и посередине ветка, которая не делала ничего. После правки та же логика заняла двадцать аккуратных строк, и каждую можно прочитать вслух. Запрос «курсор агент» ищут те, кто хочет, чтобы нейросеть сама навела порядок в коде. Сразу оговорюсь: здесь блог LibraChat, а функцию я правил в нашем чате. Cursor — редактор кода компании Anysphere, о нём здесь больше ничего не будет. Ниже было и стало, девять правок и три приёма, как просить такую работу.
Было: функция, ради которой ищут «курсор агент»
Я дизайнер. Код для меня как макет: сразу видно, где порядок, а где свалка. Вот что было на сайте:
```javascript
function calc(o){var t=0;for(var i=0;i<o.items.length;i++){t=t+o.items[i].price*o.items[i].qty}if(o.coupon=="SALE10"){t=t-t*0.1}if(t>5000){t=t}else{t=t+300}return t}
```
Что здесь не так глазами человека, который код не пишет:
ветка `t = t`, которая ничего не делает и только путает.
Владелец магазина хотел поменять порог бесплатной доставки и боялся открыть этот файл. Его понять можно. Поменяешь не ту цифру, и покупатели увидят на кассе другую сумму, чем на баннере. Для магазина это хуже, чем старый порог: сразу пишут в поддержку и уходят.
Приём 1. Курсор агент или чат: просить читаемость, а не «улучшить»
Слово «улучши» каждый понимает по-своему. Для одного это скорость, для другого краткость, для третьего новые возможности. Я попросил конкретное: чтобы было проще читать, и чтобы каждое изменение было объяснено отдельно.
Перепиши эту функцию на JavaScript так, чтобы её было проще читать, и объясни каждое изменение отдельным пунктом: function calc(o){var t=0;for(var i=0;i<o.items.length;i++){t=t+o.items[i].price*o.items[i].qty}if(o.coupon=="SALE10"){t=t-t*0.1}if(t>5000){t=t}else{t=t+300}return t}
Вторая половина запроса для меня главная. Код без объяснения я бы не смог проверить. С объяснением могу.
Стало: та же логика, двадцать строк
Ответ начался одной фразой: та же логика, только без «простыни» и пустой ветки. Дальше шёл код. Самое заметное изменение для меня — константы в начале функции:
```javascript
const SALE_COUPON = "SALE10";
const DISCOUNT_RATE = 0.1;
const FREE_SHIPPING_FROM = 5000;
const SHIPPING_FEE = 300;
```
Теперь любой, кто откроет файл, видит: порог бесплатной доставки 5 000 рублей, сбор 300, скидка по купону 10%. Владельцу магазина, чтобы поменять порог, нужно исправить одну цифру в одной строке с понятным именем.
Остальное тело функции читается сверху вниз, как короткий рецепт. Сначала сумма по товарам. Потом скидка, если есть купон. Потом доставка, если сумма не дотянула до порога. В конце итог. Для меня это та же визуальная иерархия, что в хорошем макете: блоки идут в порядке, в котором о них думает человек, и между ними есть воздух. Пустые строки в коде работают как отступы между секциями страницы. Их никто не замечает, пока их нет.
Девять правок и что каждая меняет
В ответе было девять пунктов. Я свёл их в таблицу до и после:
Что · Было · Стало
Имя параметра — `o` — `order`
Форма — одна строка — строки с отступами
Объявление суммы — `var t` — `let total`
Цикл — индекс `i` и `o.items[i]` — `for...of`, сразу товар
Накопление — `t = t + ...` — `total += ...`
Числа — `0.1`, `5000`, `300` — именованные константы
Сравнение купона — `==` — `===`, строгое
Восьмой пункт я перечитал дважды. Пустая ветка `t = t` ничего не делала, и условие перевернули: доставка добавляется, когда сумма не больше 5 000. В ответе отдельно сказано, что при ровно 5 000 сбор начисляется так же, как раньше. Логика не поменялась ни на рубль.
И девятый, самый деликатный. Имя функции `calc` оставили. Если её вызывают в других местах сайта, переименование сломало бы их. В ответе предложено имя получше, `calculateOrderTotal`, но только если переименовывать можно.
Дизайнеру не всё равно, как выглядит код
Сначала я честно не собирался в это лезть. Магазин — клиент по дизайну, мой участок — карточки и баннеры. Но порог бесплатной доставки стоял крупно на главном баннере, который я рисовал. Владелец попросил поменять 5 000 на 4 500, и я пообещал, что поправлю баннер к пятнице. Оказалось, что баннер поправить просто, а сайт продолжает считать по старому порогу. Цифра на картинке и цифра в коде разошлись.
Я попробовал найти, где эта цифра живёт в коде, и нашёл ту самую строку. Сам грешил похожим в макетах: когда-то у меня в одном файле было три одинаковых кнопки с тремя чуть разными оттенками синего. Никто не мог сказать, какой из них правильный. Хаос в макете и хаос в коде устроены одинаково: одна и та же вещь записана в нескольких местах, и никто не помнит, где главная.
Константы в начале функции решают это так же, как стили в дизайн-системе. Одна цифра, одно имя, одно место.
Приём 2. Попросить сохранить поведение
Рефакторинг — это когда код становится понятнее, а результат остаётся тем же. Это я проверил сам, на трёх заказах:
Заказ на 4 000 без купона: было 4 300, стало 4 300.
Заказ на 6 000 с купоном SALE10: было 5 400, стало 5 400.
Заказ ровно на 5 000: было 5 300, стало 5 300.
Третий случай — граница, и именно там чаще всего ломаются переписанные условия. Знак «больше» легко превращается в «больше или равно», и на ровных суммах покупатель внезапно получает бесплатную доставку или, наоборот, лишний сбор. Здесь не сломалось. В следующий раз я сразу добавлю в запрос «поведение не меняй, особенно на границе 5 000», чтобы нейросеть держала это в голове с первой строки.
Приём 3. Не принимать то, что не понимаешь
Из девяти пунктов я не сразу понял третий: почему `let` лучше `var`. В ответе объяснено одной фразой: переменная видна только внутри функции и не «всплывает». Мне хватило. Но если бы не хватило, я бы спросил в том же чате. Я проверил себя простым тестом: смогу ли я объяснить владельцу магазина каждую из девяти правок за минуту. Смог. Значит, правку можно отдавать дальше. Правило дизайнера, которое работает и с кодом: не ставь в макет то, что не можешь объяснить клиенту.
Курсор агент, чат или разработчик: где граница
Чат переписал функцию и объяснил каждое изменение. Но он видит только ту функцию, которую я показал. Он не знает, откуда она вызывается, что в `order.items` приходит на самом деле и нет ли где-то ещё копии этой же логики. Выкатывать правку на живой сайт я не взялся. Передал её знакомому разработчику, приложив таблицу правок. Он проверил вызовы и выкатил за десять минут. На следующий день владелец сам поменял порог на 4 500, впервые без звонка мне.
Редакторы кода со встроенными агентами умеют смотреть весь проект сразу. Это другой класс инструментов, для программистов. Для владельца магазина или дизайнера, которому нужно понять и поправить одну функцию, хватает чата. Мне не нужен был помощник, который пройдёт по всему проекту. Мне нужно было, чтобы одна понятная функция заменила одну непонятную. Это задача на вечер, и вечера хватило.
Задачи профессиональных разработчиков, где код живёт годами и его много, разобраны отдельно: нейросеть для программиста.
Посмотри на свою «простыню»
Найди функцию, которую боишься трогать: в своём проекте, на сайте, в учебном задании. Отправь её в чат LibraChat с просьбой переписать для читаемости и объяснить каждое изменение отдельным пунктом. Попробуй потом проверить поведение на трёх входах, один из которых — граница. Одна функция укладывается в бесплатный тариф, остальные варианты перечислены на странице тарифов.