SkobarevЗаметкиБаза знанийПроектыОбо мнеRead in English

Разработка с LLM без технического долга

#LLM#micro SaaS

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

Это не про недоверие к модели. Это про то, что в micro SaaS дежурный по проду — вы, и другого не будет.

Где модель экономит дни

Выигрыш реальный и он не в «написать за меня продукт», а в конкретных блоках:

Задача Что даёт модель Риск
Чужой API по документации вытаскивает ограничения и форматы за минуты документация врёт, проверять запросом
Вёрстка лендинга четыре блока и адаптив за час лишние зависимости и мёртвый CSS
Конфиг деплоя, nginx, systemd рабочий шаблон вместо чтения мануалов права и секреты по умолчанию небезопасные
Разбор чужих выгрузок парсер под кривой CSV за полчаса молча съедает битые строки
Миграции и SQL синтаксис без опечаток удаляющий запрос без бэкапа
Текст, письма, тексты ошибок черновик, который остаётся отредактировать вода и обещания, которых продукт не даёт

Свой пример: когда я разбирал двенадцать площадок для автопостинга, половина работы была не в коде, а в их особенностях. У LinkedIn токен требует ручной переавторизации раз в шестьдесят дней, у Bluesky ссылки в тексте размечаются по байтовым офсетам UTF-8 — с кириллицей это отдельное развлечение. Модель достаёт такие детали из документации за минуты. Дальше их всё равно надо проверить настоящим запросом: часть API ведёт себя не так, как написано.

Где модель создаёт долг

Долг появляется не от плохого кода, а от кода, за который никто не отвечает. Четыре типовых источника.

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

Незаказанные зависимости. Модель охотно тянет библиотеку на задачу в десять строк. Каждая зависимость — это обновления, уязвимости и чужие поломки в вашем расписании.

Абстракции «на вырост». Интерфейс с одной реализацией, фабрика на один объект, конфиг для значения, которое никогда не менялось. Это выглядит как хорошая архитектура и работает как лишний слой, через который вы ночью продираетесь к настоящей ошибке.

Тихое проглатывание ошибок. try/except вокруг всего с пустым телом или логом в никуда. Продукт не падает, а просто перестаёт делать то, за что заплатили, и вы узнаёте об этом от клиента.

Правило приёмки

Практика, которая держит долг на нуле без замедления работы:

  1. Одна задача — один дифф. Не «сделай оплату», а «добавь обработчик вебхука, проверь подпись, верни 200». Задача формулируется так, что её результат можно прочитать за пять минут.
  2. Прочитать вслух. Если вы не можете объяснить дифф своими словами — он не принят. Не «переспросить у модели», а именно объяснить: понимание проверяется на выходе, а не на входе.
  3. Проверить не глазами, а запуском. Любая ветка, цикл и парсер получают один запуск на настоящих данных. Данные клиента всегда грязнее демо: пустые поля, лишние колонки, даты в трёх форматах.
  4. Диффы только в git. Каждый шаг — отдельный коммит с человеческим сообщением. Возможность откатиться на один шаг назад дороже любого рефакторинга.
  5. Зависимости — по списку. Новая библиотека добавляется, только если вы сами решили её добавить.

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

Что не отдаётся модели без проверки

Список короткий и не режется никогда — он же перечислен в минимальном наборе первой версии:

  • Деньги. Проверка подписи вебхука, идемпотентность, порядок «списали — выдали доступ». Сценарий «деньги ушли, доступ не появился» — худший из всех, и он пишется руками и тестом.
  • Доступ и разграничение клиентов. Один клиент не должен видеть данные другого. Это проверяется отдельным тестом, а не чтением кода.
  • Границы доверия. Всё, что приходит извне: формы, загруженные файлы, ответы чужих API. Валидация здесь не «на будущее», а обязательна.
  • Секреты. Ключи в переменных окружения, не в репозитории и не в диалоге.
  • Удаляющие миграции. Перед DROP и DELETE — дамп, всегда.
  • Бэкапы и логи. Логи такие, чтобы по ним было видно, что делал конкретный клиент. Это ваш единственный инструмент в три часа ночи.

Как понять, что долг уже накопился

Признаки, каждый из которых виден без аудита:

  • на баг из одной строки уходит вечер, потому что сначала надо вспомнить, как устроен модуль;
  • вы боитесь трогать файл и обходите его новым кодом рядом;
  • в проекте есть места, про которые вы говорите «оно как-то работает»;
  • при ошибке в проде вы идёте читать код, а не логи;
  • обновление одной библиотеки ломает две несвязанные функции.

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

Чек-лист перед деплоем

  1. Каждый дифф прочитан и объясняется своими словами.
  2. Все внешние данные валидируются на входе.
  3. Сценарий оплаты покрыт тестом, включая ошибку провайдера.
  4. Секретов в репозитории нет.
  5. Логов достаточно, чтобы восстановить путь конкретного клиента.
  6. База копируется по расписанию, восстановление проверено хотя бы раз.
  7. Новых зависимостей нет — или каждая добавлена осознанно.
  8. Есть способ откатить деплой одной командой.

Семь из восьми — это не «почти готово», а «есть один способ потерять деньги или данные». Дешевле закрыть его сейчас.

Что модель не меняет

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

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

Частые вопросы

Можно ли сделать micro SaaS, если сам почти не пишешь код?

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

Как понять, что модель написала плохой код, если я не эксперт?

По трём признакам, которые видны без экспертизы: вы не можете объяснить своими словами, что делает функция; в диффе меняется больше файлов, чем вы просили; появились библиотеки, которых вы не заказывали. Любой из трёх — повод не принимать дифф, а разбить задачу мельче.

Стоит ли давать модели доступ к продовой базе или ключам?

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

Нужны ли тесты, если продукт живёт пятьдесят часов?

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

Что делать с кодом, который работает, но я его не понимаю?

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

← База знаний