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

Почему вывод ИИ становится трудным для поддержки
Код, сгенерированный ИИ, кажется отличным в первый день: он быстро запускается и сразу показывает результат. Проблемы начинаются через несколько дней, когда нужно добавить фичу, исправить баг или передать проект другому человеку. Без чётких правил модель оптимизирует «сделай так, чтобы сейчас работало», а не «сделай так, чтобы было легко менять позже».
Обычно причина — расплывчатые подсказки. Если вы не указываете правила по структуре папок, именованию и конфигурации, модель заполняет пробелы по‑разному каждый раз. В результате файлы оказываются разбросаны по случайным каталогам, одно и то же понятие называют тремя разными способами, а настройки прячутся в местах, о которых никто не догадывается. Код всё ещё может работать, но он становится хрупким.
Признаки приближающегося хаоса: несогласованные стили для похожих фич, непредсказуемое размещение файлов, дрейф имён (userService, users_service, UserSvc) и конфигурация, смешанная с кодом без ясных значений по умолчанию. Небольшие изменения начинают вызывать неожиданные поломки в других местах.
Для единственного фаундера или небольшой команды «поддерживаемость» обычно означает, что вы быстро находите нужные вещи, можете изменить одно поведение, не ломая пять других, и без проблем вводите нового человека в проект. Также это означает меньше ночных сюрпризов вроде сломанной авторизации, раскрытых секретов или путаницы из папок.
Добавляйте ограничения, когда проект проживёт дольше демо или когда ожидается больше одного итерации. Пусть модель импровизирует только для одноразовых экспериментов, быстрых спайков или одиночных скриптов. Если вы собираетесь выпускать, поддерживать или платить кому‑то за правки позже — задайте ограничения с самого начала.
Три самых важных ограничения
Если вы хотите подсказки для поддерживаемого кода, не просите сначала добавить больше функций. Начните с трёх ограничений, которые определяют, как код организован, как что называется и как работает конфигурация. Их больно менять потом.
1) Структура папок (куда помещать что)
Правило по папкам делает вывод предсказуемым и предотвращает «всё в корне».
Задайте правила вроде: один входной файл, группировать код по ответственности и отделять код приложения от конфигурации, скриптов и тестов. Скажите явно, чего нельзя делать (например, никакой бизнес‑логики в UI‑компонентах, никакого доступа к базе внутри роутов).
2) Именование (как вы это потом узнаете)
Правила именования сокращают дублирование и путаницу. Без них появляются два файла, делающих одно и то же, или utils.ts, превращающийся в мусорную папку.
Будьте конкретны: имена файлов, компонентов, функций, маршрутов и таблиц базы данных должны следовать одному стилю и отражать назначение. Используйте согласованные глаголы для действий (create, update, delete) и избегайте расплывчатых имён вроде data, helper или thing.
3) Конфигурация (как обрабатывать настройки и секреты)
Многие прототипы от ИИ ломаются при переходе от локального запуска к реальному развёртыванию. Чёткие ограничения конфигурации этому препятствуют.
Определите правила заранее:
- Одно место для конфигурации (переменные окружения + один модуль конфигурации), а не разбросанные константы
- Отдельные дефолты для dev и prod с безопасными значениями по умолчанию
- Никогда не хардкодьте секреты, токены или ключи API в коде или примерах файлов
- Предоставьте минимальный пример
.envс плейсхолдерами только - Выполняйте быструю остановку (fail fast) при отсутствии обязательных настроек с понятной ошибкой
Если вы унаследовали приложение, сгенерированное ИИ, которое игнорирует эти правила, обычно сначала делают именно эту уборку, потому что она упрощает все последующие исправления.
Повторно используемый шаблон подсказки
Самый быстрый выигрыш — небольшой блок ограничений, который можно вставлять в любую просьбу и менять только то, что важно для проекта.
Вот шаблон, который можно копировать как есть:
CONSTRAINTS
1) Before coding, output a brief file tree (max 15 lines). Ask 2-4 questions only if needed.
2) Folder structure:
- Keep source in /src
- Keep shared utilities in /src/lib
- Keep UI components in /src/components
- Keep config in /config
3) Naming:
- Files: kebab-case (user-profile.ts)
- React components: PascalCase
- Functions/vars: camelCase
- No single-letter names (except i/j in loops)
4) Configuration and secrets:
- Read all secrets from environment variables
- Provide a sample .env.example (no real secrets)
- Safe defaults for dev, strict checks for prod
5) If a rule conflicts with the framework:
- Follow the framework default
- Explain the conflict in 2-3 sentences
- Suggest the closest alternative that keeps the spirit of the rule
6) Output:
- Generate code file-by-file with clear filenames
- Add short comments only where the intent is not obvious
Делайте правила конкретными, но не слишком детальными. Хорошие ограничения описывают проверяемые исходы (где живут файлы, как выглядят имена, откуда берутся секреты). Пропустите мелкие стильные правила, которые создают лишнюю работу.
Одна полезная привычка: попросить дерево файлов сначала. Это заставляет модель спланировать, и даёт вам шанс сказать «перенеси auth в /src/lib» прежде чем она начнёт писать 10 файлов.
Если вы чините код, сгенерированный ИИ, ограничения ускоряют ремонт. Когда всё лежит там, где ожидать, легче увидеть, чего не хватает, и исправить без сломанных зависимостей.
Пошагово: как писать ваши ограничения
Хорошие подсказки для поддерживаемого кода начинаются с ясности и добавляют только те правила, которые вы действительно будете контролировать. Если добавить слишком много — модель начнёт игнорировать их или писать лишнее.
Простой рабочий поток, который работает
Напишите подсказку в пяти частях, в этом порядке:
- Одно предложение о том, что нужно сделать (для кого и основное действие).
- Зафиксируйте базовые вещи стека (фреймворк, язык и версии, влияющие на синтаксис или конфигурацию). Остальное опустите.
- Установите правила проекта: как организованы папки и как именуются файлы, компоненты и функции.
- Определите, как работает конфигурация: что в переменных окружения, какие безопасные дефолты и что никогда не коммитить.
- Потребуйте последовательность вывода: сначала план файлов, затем код, затем краткая самопроверка того, что было верифицировано.
Этот порядок важен. Если начать с папок и имен до постановки цели, вы получите аккуратную структуру, решающую не ту задачу.
Маленький пример (проще словами)
Представьте, что нужен простой трекер счетов для фрилансера. Если вы зафиксируете React + TypeScript и скажете «серверный код в /api, UI в /web, общие типы в /shared», вы предотвратите массу хаоса. Добавьте правила именования вроде «компоненты PascalCase, хуки начинаются с use» — и вы избежите дальнейшей загадки о том, где живёт логика.
Будьте строги по конфигурации: «читайте секреты только из env, предоставьте .env.example и fail fast с понятной ошибкой при отсутствии переменной». Одна такая строка предотвращает классические проблемы со сломанной авторизацией и раскрытыми секретами.
Завершите требованием самопроверки: это подтолкнёт модель поймать пропущенные файлы, несоответствие имён и небезопасные дефолты до того, как вы это увидите.
Ограничения структуры папок, которые держат проект в порядке
Чистое дерево папок — одно из самых простых ограничений. Цель не в совершенстве, а в предсказуемости: чтобы вы (или кто‑то другой) могли быстро находить вещи и править их, не ломая чужие части.
Простая структура, подходящая для большинства небольших веб‑приложений:
src/ui/для экранов и переиспользуемых компонентовsrc/domain/для бизнес‑правил (что делает приложение)src/data/для работы с базой и внешними API (как хранятся и забираются данные)src/shared/для действительно общих хелперов (маленькие, скучные, повторно используемые)src/config/для дефолтов настроек приложения (не секретов)
Ещё одно правило: разделяйте UI, бизнес‑логику и доступ к данным. Проще говоря, UI не должен самой напрямую обращаться к базе, а код доступа к базе не должен решать, что пользователь может делать.
Чтобы файлы не превращались в 800‑строчные монстры, определите «одна ответственность на файл» практично. В одном файле — одна основная цель (один компонент, один сервис, один репозиторий). Если нужны две разные заголовочные части — разделите. Если что‑то переиспользуется в трёх местах — вынесите в shared/. Если переиспользование только внутри одной фичи — держите внутри папки фичи. Избегайте общей папки utils/: требуйте специфичных папок вроде shared/date/ или shared/format/.
Правило для создания нового модуля vs добавления в существующий: создавайте новую папку только когда в приложении появляется новая концепция. В биллинговом приложении это может быть domain/invoices/ и ui/invoices/ когда счёта становятся полноценной функцией, а не одиночным экраном.
Если вы наследуете запутанный вывод ИИ, эти ограничения ускоряют исправление: большая часть работы — перемещение кода в чёткие границы перед безопасным ремонтом логики, авторизации или безопасности.
Правила именования, которые предотвращают путаницу позднее
Именование — место, где вывод ИИ часто уходит в сторону. Если в подсказке вы жёстко зададите стиль, вы потратите меньше времени на поиск импортов, угадывание назначения функций и распутывание «почти одинаковых» моделей.
Выберите один стиль для каждой категории и не смешивайте. Простое соответствие, которое можно вставить в подсказки:
- Файлы и папки: kebab-case (например,
user-profile.ts) - React‑компоненты / классы: PascalCase (например,
UserProfile) - Функции и переменные: camelCase (например,
fetchUserProfile) - Константы: SCREAMING_SNAKE_CASE (например,
MAX_RETRIES) - API‑маршруты: kebab-case (например,
/user-profile)
Имена файлов должны соответствовать тому, что они экспортируют. Если файл экспортирует UserService, назовите его user-service.ts (или UserService.ts, если это ваше правило). Не экспортируйте пять несвязанных вещей из одного файла. Один основной экспорт на файл делает импорты предсказуемыми и рефакторы безопаснее.
Для функций используйте сначала глагол, который описывает действие: getUserById, validateSignupForm, saveInvoice, sendPasswordResetEmail. Избегайте расплывчатых имён process, handleThing или doWork. Если функция асинхронная, будьте последовательны: либо везде добавляйте суффикс Async, либо полагайтесь на контекст, но не смешивайте.
Модели данных используйте в единственном числе (User, Invoice). Поля БД придерживайтесь одного соглашения (snake_case часто для SQL; camelCase часто в приложении). Выберите одно и придерживайтесь его. Сопоставляйте имена так, чтобы createdAt соответствовал created_at, а не create_date в одном месте и created в другом.
Небольшой список «не использовать» экономит время позже: temp, misc, helper2, final_v3, newNew. Если в кодовой базе много таких имён, переименование и реорганизация часто окупаются сразу, потому что неясные имена скрывают баги.
Ограничения для конфигурации: окружения, секреты и дефолты
Чётко разделяйте, что является конфигурацией, а что — кодом. Конфигурация — всё, что меняется между dev, staging и prod: URL базы данных, ключи API, разрешённые источники, настройки cookies, feature flags. Код — логика, которая остаётся одинаковой: маршруты, валидация, бизнес‑правила.
Хорошее правило — отделять runtime‑конфиг от build‑time конфигурации. Runtime‑конфиг должен приходить из переменных окружения, чтобы его можно было менять без пересборки. Build‑time конфиг может жить в файлах, которые коммитятся в репозиторий, например типизированный модуль конфигурации с безопасными дефолтами или config/*.json для незашифрованных значений.
Секреты требуют явных правил, потому что прототипы ИИ часто их протекают:
- Никогда не хардкодьте секреты в коде или конфигурации
- Никогда не логируйте секреты (включая debug‑логи)
- Никогда не коммитьте секреты (коммитьте только пример файла)
- Fail fast при отсутствии обязательного секрета
- Используйте ясные имена вроде
DATABASE_URLиJWT_SECRET
Дефолты тоже важны. Попросите безопасные, скучные дефолты, чтобы приложение вело себя предсказуемо до настройки. Например: CORS должен быть ограничен (разрешён только известный список), auth cookies должны быть HttpOnly и Secure в проде, сессии — с коротким idle timeout и понятным max age.
Также потребуйте одно место для документации конфигурации. Самый простой подход — единый .env.example с комментариями и короткий раздел «Configuration» в README с перечислением переменных, их назначением и примерным значением. Это экономит часы позже, особенно когда прототип работал на одном ноутбуке, но ломается при развёртывании.
Ограничения по качеству: ошибки, валидация и небольшие тесты
Большинство приложений, сгенерированных ИИ, ломаются в проде по скучным причинам: неясные ошибки, отсутствие валидации и отсутствие тестов вокруг рискованных частей. Несколько ограничений качества делают вывод проще для отладки и последующих исправлений.
Начните с требования единого подхода к обработке ошибок. Попросите один паттерн везде, а не мешать бросание строк, спонтанные ответы и молчаливые провалы. Требуйте, чтобы ошибки были явными, имели одинаковую форму и безопасны для показа пользователю.
Далее требуйте валидацию на границах — там, где в систему попадают внешние данные: API‑маршруты, формы, вебхуки, фоновые задания. При отсутствии валидации появляются странные баги вроде «работает у меня» или «ломается только для некоторых пользователей».
Ограничения, которые можно скопировать:
- Используйте единый формат ошибки (например:
{ code, message, details? }) и никогда не бросайте простые строки. - Валидируйте все внешние входы на границе, возвращайте понятные ошибки валидации и не доверяйте данным с клиента.
- Держите функции небольшими (примерно 20–40 строк) и делайте возвращаемые значения предсказуемыми (без смешанных типов).
- Логируйте неожиданные сбои с достаточным контекстом для воспроизведения (request id, user id если доступен, действие).
Тесты не обязаны быть большими, чтобы быть полезными. Попросите минимальный набор, соответствующий рискам. Если есть логин, платежный поток или create/update действие — начните с них. Лёгкий минимум может включать отказ в авторизации для некорректных учётных данных, базовый успешный путь для ключевого потока и один тест валидации, подтверждающий, что плохой ввод возвращает понятную ошибку.
Наконец, потребуйте короткий раздел «как запустить локально» в выдаче, с перечислением нужных переменных окружения и безопасных дефолтов. Это убережёт от многих проектов, которые «не стартуют».
Пример подсказки: построение маленького приложения, которое остаётся поддерживаемым
Представьте, что вам нужно простое веб‑приложение с логином, страницей профиля и формой настроек. Без ограничений ИИ часто разбрасывает логику авторизации по страницам, смешивает вызовы к базе в UI и придумывает имена файлов на лету. С чёткими правилами вы получите чёткие границы и план файлов, который будет легче отлаживать.
Вот копируемый пример подсказки, который можно настроить:
Build a small app with:
- Login page
- Profile page (shows name + email)
- Settings page (update display name, toggle a feature flag)
Hard constraints (do not violate):
1) Folder structure:
- /src/routes = route definitions only
- /src/handlers = request/response logic only (no database queries)
- /src/services = business rules (auth, profile, settings)
- /src/data = database access only (queries, repositories)
- /src/config = configuration loader and typed config
2) Naming:
- Files: kebab-case (profile-handler.ts)
- Exports: camelCase functions, PascalCase types
- One main export per file
3) Code boundaries:
- Routes call handlers
- Handlers call services
- Services call data layer
- Data layer is the only place allowed to import the DB client
4) Config constraints:
- Read DATABASE_URL and AUTH_SECRET from environment variables
- Never hardcode secrets or sample keys
- Add FEATURE_SETTINGS_ENABLED default=false when missing
- Provide a single config object from /src/config
Deliverables:
- Start with a file tree
- Then output code file-by-file
- Finish with a summary table: file created/changed + 1 sentence why
Если хотите ещё более жёсткий вывод, добавьте: «Если нужно добавить новый файл, объясните, почему он относится в эту папку». Это заставит модель уважать границы вместо того, чтобы сбрасывать всё в одно место.
Типичные ошибки при добавлении ограничений
Ограничения призваны сделать вывод проще для чтения, изменения и исправления. Большинство проблем возникает, когда правила либо слишком расплывчаты, чтобы направлять модель, либо настолько строги, что конфликтуют с используемым фреймворком.
Ошибка 1: чрезмерное ограничение проекта
Легко написать правила, которые звучат аккуратно, но вынуждают делать неестественные вещи. Например, требовать кастомную структуру папок, которая противоречит конвенциям Next.js, или запрещать стандартный конфигурационный файл фреймворка только потому, что он кажется грязным. Тогда модель тратит усилия на обход правил вместо написания корректного кода.
Более безопасный подход: придерживайтесь дефолтов фреймворка, если нет серьёзной причины менять их. Добавляйте ограничения только там, где вы регулярно видите путаницу позже (границы между UI, сервисами и доступом к данным).
Ошибка 2: недостаточные ограничения с расплывчатыми словами
«Чистый код», «лучшие практики» и «enterprise‑ready» не дают модели чётких указаний. Замените их проверками, которые можно выполнить.
Примеры рабочих ограничений:
- «Выведите дерево файлов сначала, затем файлы кода в этом порядке.»
- «Используйте один стиль именования: camelCase для переменных, PascalCase для компонентов.»
- «Положите env‑переменные в
.env.exampleи читайте их только через модуль конфигурации.» - «Никаких новых библиотек без вашего одобрения и объяснения причины.»
- «Если вы перемещаете файлы, включите шаги миграции.»
Ещё одна проблема — позволять модели придумывать библиотеки или конфигурации, которые вы не просили. Вы просите авторизацию — она добавляет три пакета, два конфига и новый билд‑тул.
Не пропускайте шаги миграции при смене структуры папок. Маленькое переименование может сломать импорты, тесты и развёртывание. Попросите короткое «что изменилось» и команды для обновления путей. И всегда требуйте дерево файлов; без него вывод становится разбросанным и трудно собрать.
Быстрый чек‑лист и дальнейшие шаги
Прежде чем принимать код, сгенерированный ИИ (или вливать его в ветку), сделайте 5‑минутную проверку. Эти пункты ловят большинство «выглядит нормально сейчас, но будет больно потом» проблем:
- Дерево файлов соответствует вашим правилам (папки, слои, общий код) и нет случайных одноразовых директорий.
- Имена согласованы: одно и то же понятие не называется по‑разному в файлах, маршрутах и переменных.
- Секретов в коде нет: никаких API‑ключей, токенов, приватных URL или реальных учётных данных в файлах, комментариях или примерных конфигах.
- Конфигурация понятна: есть документированное место для env‑переменных, дефолты безопасны, и поведение не меняется молча между dev и prod.
- Проект запускается по простым шагам: новый человек может установить, настроить и запустить приложение без угадываний.
Если вы не можете уверенно ответить «да» на большинство пунктов — остановитесь. Небольшая уборка сейчас дешевле, чем отладка через месяц, особенно когда проблемы скрыты в путанице имён, разбросанной конфигурации или структуре папок, которая поощряет спагетти‑рост.
Если у вас уже есть запутанный прототип от инструментов вроде Lovable, Bolt, v0, Cursor или Replit, FixMyMess (fixmymess.ai) может провести бесплатный аудит кода, чтобы найти проблемы со структурой, именами, конфигурацией и безопасностью до начала исправлений. Так вы получите ясный план, а не ещё один раунд догадок.
Часто задаваемые вопросы
Почему код, сгенерированный ИИ, так быстро становится запутанным?
ИИ обычно оптимизирует «чтобы сейчас работало», поэтому может применять упрощения, которые кажутся приемлемыми до тех пор, пока не придётся что‑то менять. Без чётких правил по структуре, именованию и конфигурации каждая новая подсказка может давать другую схему, и код становится хрупким при изменениях.
Какие самые простые признаки того, что проект становится трудно поддерживать?
Ищите несоответствия в именах одного и того же понятия, файлы в случайных папках и значения конфигурации, захардкоженные в нескольких местах. Часто признаком является ситуация, когда небольшое изменение ломает не связанные части — это значит, что ответственности смешаны.
Когда стоит добавлять ограничения, а когда позволить модели импровизировать?
Добавляйте ограничения, когда проект может быть выпущен, будет итеративно развиваться или передан другому человеку. Для одноразовых демо или одноразовых скриптов можно быть мягче и допускать некоторую неаккуратность.
Почему структура папок, именование и конфигурация — это «большая тройка» ограничений?
Структура папок определяет, куда будет идти код в будущем, именование — как вы будете находить и переиспользовать вещи, а конфигурация — выживет ли приложение при развёртывании. Эти три аспекта трудно менять позже, потому что они затрагивают каждый файл и каждое изменение.
Какой самый быстрый способ поддерживать порядок в выводе ИИ с самого начала?
Попросите выводить краткое дерево файлов до того, как сгенерировать код, и ограничьте его 10–15 строками. Затем требуйте построчный вывод файлов с указанием имён — так вы увидите, попало ли что‑то не туда, прежде чем модель создаст десятки файлов.
Какие правила именования предотвращают дублирование и путаницу?
Выберите одно соглашение на категорию и придерживайтесь его: файлы в kebab-case, компоненты в PascalCase, функции в camelCase и последовательное именование маршрутов. Требуйте, чтобы имя файла соответствовало его основному экспорту и избегайте общего utils как мусорной папки, заменяя её на более конкретные имена.
Какие правила конфигурации предотвращают типичные проблемы при деплое?
Требуйте одного загрузчика конфигурации/модуля, чтения секретов только из переменных окружения и файла .env.example с заполнителями вместо реальных ключей. Также добавьте «fail fast» проверки для обязательных значений — молчаливые дефолты часто рушат прототипы в продакшене.
Как избежать чрезмерного ограничения проекта слишком большим числом правил?
Переусердствование случается, когда ваши правила противоречат дефолтам фреймворка, и модель тратит усилия на обход этих правил вместо правильного кода. Хорошая практика — следовать дефолтам фреймворка при конфликте и вводить ограничения только в тех областях, где вы регулярно видите путаницу.
Какие ограничения по качеству помогают, не замедляя разработку?
Попросите единый формат ошибок по всему приложению, валидацию на границах (маршруты/формы/вебхуки) и минимальный набор тестов для рисковых потоков (авторизация, создание/обновление). Эти меры не добавляют много кода, но сильно упрощают отладку и предотвращают регрессии.
Я унаследовал запутанный код, сгенерированный ИИ — что делать в первую очередь?
Сначала картируйте текущее дерево файлов и место, где хранятся конфигурация и секреты, затем выберите одно правило именования и примените его в критическом пути. Перенесите конфигурацию в одно место с примером .env.example и ясными шагами для запуска — это часто решает большинство проблем сразу. Если вы застряли с прототипом от Lovable, Bolt, v0, Cursor или Replit, FixMyMess (fixmymess.ai) может сделать бесплатный аудит и предоставить план исправлений.