На текущий момент все еще есть люди, которые активно не используют нейросети в своих проектах, так же как существуют команды, продолжающие работать по-старому - полагаясь на опыт и ручные процессы, избегая интеллектуальных инструментов.
С другой стороны, все чаще можно услышать жалобы от разработчиков, особенно с грейдом middle и выше: их буквально заваливают навайбкоженными пулл-реквестами сомнительного качества, которые приходится по несколько раз реджектить, прежде чем они дойдут до адекватного состояния.
При этом среди самих разработчиков нередко встречаются два диаметрально противоположных взгляда на ИИ: одни убеждены, что он вот‑вот заменит всех и уже превзошел человека, другие считают его временным хайпом, вредительством или пузырем, который скоро лопнет.
Но реальность в том, что ИИ — ни угроза и ни пузырь. Это необратимая часть индустрии: он уже встроился в профессию, и путь назад закрыт. Разработчики будут использовать его все активнее, в том числе и для вайб-кодинга.
Однако ключевая проблема скрывается не в ИИ, а в людях.
Сгенерированный код сам по себе не плохой и не хороший, но менее опытные или невнимательные разработчики нередко безоговорочно доверяют результату. Ограничившись поверхностной проверкой, они отправляют такой код в репозиторий, закладывая основу для будущих ошибок и деградации качества.
Чтобы получить максимальный КПД от ИИ в вашем проекте, попробуйте взглянуть на сам проект как на промпт к LLM. Что происходит, когда промпт слабо детализирован, контекст неполный, а ограничения отсутствуют? Ответ очевиден: модель генерирует код слабого качества, с произвольным стилем, непредсказуемой cтруктурой и множеством домыслов.
Ниже, два простых примера для наглядной демонстрации. Одна и та же задача превращается в «грязный вайб‑кодинг» при «плохом» запросе и в приемлемый код — при «хорошем».
Плохой промпт
Напиши метод сервиса на NestJS + TypeORM, который вернёт активных пользователей с их последними заказами и с фильтром по статусу пользователя.
Структура таблиц:users(id, name, status, is_active)orders(id, user_id, created_at, total)
Результат
async getActiveUsersWithLastOrder(status: string) {
return this.userRepository
.createQueryBuilder("user")
.leftJoinAndSelect("user.orders", "order")
.where(`user.status = '${status}'`)
.andWhere("user.is_active = 1")
.orderBy("order.created_at", "DESC")
.getMany();
}
Что здесь не так:
SQL-инъекция на ровном месте - status подставляется в строку
user.is_active и order.created_at - колонки БД, а не свойства User и Order
Это выглядит как рабочий запрос, но за ним скрываются баги, рассинхрон с моделью и дыра в безопасности.
Хороший промпт
Напиши метод сервиса NestJS, который вернет активных пользователей с их последними заказами и фильтром по статусу пользователя, используя TypeORM 0.3x.
Сущности:@Entity('users')
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
name: string;
@Column()
status: string;
@Column({ default: true })
isActive: boolean;
@OneToMany(() => Order, (order) => order.user)
orders: Order;
}
@Entity('orders')
export class Order {
@PrimaryGeneratedColumn('uuid')
id: string;
@ManyToOne(() => User, (user) => user.orders)
@JoinColumn({ name: 'user_id' })
user: User;
@Column()
createdAt: Date;
@Column('numeric')
total: number;
}
Критерии:
- методgetActiveUsersWithLastOrder(status: string): Promise
- фильтрация поuser.statusиuser.isActive = true
- использоватьQueryBuilder
- обязательная параметризация
- никаких snake_case - только свойства сущностей
Результат
async getActiveUsersWithLastOrder(status: string): Promise<User[]> {
const users = await this.userRepository
.createQueryBuilder("user")
.leftJoinAndSelect("user.orders", "order")
.where("user.isActive = :active", { active: true })
.andWhere("user.status = :status", { status })
.orderBy("order.createdAt", "DESC")
.getMany();
}
Плохой промпт
Сделай Angular-компонент, который отображает список пользователей с их статусом и суммой последнего заказа.
Результат
@Component({`
selector: 'app-users',`
template: `
<div *ngIf="users && users.length">`
<div *ngFor="let user of users">`
<h3>{{ user.name }}</h3>`
<p>Status: {{ user.status }}</p>`
<p>Last order total: {{ user.lastOrderTotal }}</p>`
</div>
</div>`
})
export class UsersComponent {
@Input() users: any[];
}
Что здесь не так
@Input()вместо современных сигналовinput()ngIfиngForвместо@ifи@for(Angular 17+)any[]- отсутствие типобезопасностикомпонент не standalone, без OnPush
Хороший промпт
Angular v21, Strict Mode.
Нужен standalone-компонент UsersComponent, который отображает список пользователей с их статусом и суммой последнего заказа.
Формат данных:interface UserWithLastOrder {
id: string;
name: string;
status: string;
lastOrderTotal: number | null;
}
Требования:
- входной сигнал c даннымиusers
- ChangeDetectionStrategy: OnPush
- аккуратная разметка
- использование современных синтаксических конструкций@ifи@for
Результат
@Component({
selector: 'app-users',
standalone: true,
imports: [CurrencyPipe],
template: `
@if (users()?.length > 0) {
<div class="user-list">
@for (user of users(); track user.id) {
<div class="user-card">
<h3 class="user-name">{{ user.name }}</h3>
<p class="user-status">Статус: {{ user.status }}</p>
@if (user.lastOrderTotal !== null) {
<p class="user-last-order">
Последний заказ: {{ user.lastOrderTotal | currency:'USD' }}
</p>
} @else {
<p class="user-last-order user-last-order--empty">
Заказов ещё не было
</p>
}
</div>
}
</div>
} @else {
<p class="user-empty">Нет пользователей, удовлетворяющих фильтру.</p>
}`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UsersComponent {
users = input<readonly UserWithLastOrder[]>([]);
}
На этих тривиальных примерах можно заметить, что чем больше ограничений, контекста и критериев вы задаете в промпте — тем выше качество результата. Модель не додумывает за вас, не изобретает структуру проекта и не навязывает собственный стиль — она работает строго в рамках тех условий, которые вы формулируете. Если рамки расплывчаты, результат будет таким же. Если рамки четкие — вы получаете точный, предсказуемый, почти production‑ready код.
И здесь проявляется один важный момент: ИИ не повышает культуру разработки сам по себе — он лишь масштабирует и ускоряет ту, что уже существует в команде.
Если в команде слабые требования, отсутствует структура или нет общего стиля — нейронка будет генерировать хаос быстрее любого разработчика. Но справедливо и обратное: если процессы выстроены, правила формализованы, а договорённости прозрачны, то LLM становится уверенным ускорителем.
И если мы начинаем смотреть на проект как на большой промпт, сразу возникает естественный вопрос: как дать этому промпту нужный контекст и как правильно ограничить его рамки? Ответ прост и ничего выдумывать не нужно — все давно придумано. Достаточно убедиться, что эти ограничения и правила действительно работают в вашем проекте. Тогда и снизится количество пулл‑реквестов навайбкоженных нейросеткой с содержимым сомнительного качества.
Многие из вас работают не только с браузерными ИИ, где уже давно можно загружать файлы проекта в рабочее пространство (например, использовать "Проекты" в ChatGPT или создавать собственные Custom GPTs), но и применяют полноценные AI-IDE вроде Cursor, способные видеть весь проект целиком. И в такой среде особенно важно, чтобы ваш проект умел бить робота по рукам, когда тот пытается сгенерировать код ненадлежащего качества. Чем жестче и яснее очерчена среда разработки, тем меньше пространство для ошибок, импровизаций и хаотичных решений со стороны ИИ.
Итак, вот список того, без чего в 2025 году крайне сложно начинать проект, если в нем предполагается активное использование LLM-инструментов.
Качественный README и базовая архитектурная документация
Даёт ИИ общую картину: стек, структуру проекта, основные принципы и используемые технологии. Хороший README - дешёвый, но чрезвычайно эффективный способ задать рамки и контекст для ИИ.Четко определенная структура директорий
Компоненты, сущности, сервисы, shared-логика, инфраструктура - все должно лежать на своих местах. Структура - это физические границы для модели.Наличие эталонных примеров в кодовой базе
Если в проекте 10 файлов написаны хорошо и 1 файл написан плохо - ИИ будет воспроизводить плохой, поэтому очень важно иметь "эталонные" файлы: образцовые сервисы, правильно оформленные компоненты, идеальные модули, идеально структурированные тесты и т.д., тогда ИИ будет копировать лучшее из проекта.Единый engineering-guideline
Набор правил, объясняющий как именно пишется код в этом проекте: паттерны, принципы, структура решений, стандарты логирования и ошибок, что можно и нельзя в компонентах/сервисах, правила разбиения логики на модули и т.д. Для робота - это фактически ТЗ на стиль мышления.Документированные антипаттерны и правила "что нельзя делать"
В проекте должно быть явно зафиксировано, какие практики запрещены: запрет raw SQL в проектах с ORM, запрет inline-стилей, запрет смешивания слоёв (например, бизнес-логики в контроллерах), запрет прямых вызовов небезопасных API, запрет "магических значений", неправильного управления состоянием или других вредных паттернов, встречавшихся в команде раньше.Единый кодстайл и автоматическое форматирование
Prettier, ESLint/Stylelint, правила по именованию файлов и DTO. Если стиля нет - ИИ создаёт свой собственный.Strict mode и жёсткие правила проверки кода
Независимо от используемого языка или фреймворка, строгие режимы проверки кода - это естественный "коридор", который ограничивает импровизации LLM и не позволяет ему генерировать двусмысленный, чрезмерно гибкий или опасный код. Строгие правила поведения, проверок, типизации, null-safety, исключений и контрактации позволяют модели действовать предсказуемо и структурно.CI-пайплайн, который не пропускает мусор
Lint, test, type-check, build. Если PR не проходит проверки - он даже не попадает на ревью.Тесты и достаточное покрытие
LLM понимает корректное поведение через тесты. Они задают контракты, определяют границы и автоматически отсекают неверные решения. Модель видит установленный test coverage и будет стремиться писать код так, чтобы тесты проходили - иначе PR не примут, и он не дойдет до ревью, потому что система контроля качества его отбросит автоматически.Ограничение размера пулл-реквестов
Маленькие PR = легче контролировать качество, легче ловить ошибки и легче удерживать ИИ в рамках. Внедрите культуру небольших PR, ориентированных на одну задачу. Это упрощает ревью и для человека, и для анализа ИИ.
ИИ уже стал естественной частью разработки — нравится это кому‑то или нет. Он ускоряет работу, убирает рутину, помогает переключаться между задачами и даже может выступать полноценным собеседником при проектировании архитектуры. Но вместе с этим он усиливает любые слабости проекта и команды: плохие практики, отсутствие стиля, отсутствие договоренностей, слабые проверки качества.
Вайб‑кодинг неизбежен, но качество результата определяется не нейросетью, а средой, в которой она работает.
Если проект оформлен как четкий промпт — со структурой, правилами, тестами, ограничениями, примерами и инженерной дисциплиной — модель работает в этих рамках так же добросовестно, как и кожаный разработчик. Если рамок нет — модель неизбежно превращает хаос в ещё больший хаос.
Будущее разработки — это не конкуренция «человек vs ИИ», а умение использовать ИИ как инструмент, встроенный в инженерную культуру. И чем выше эта культура, тем меньше вам придётся переделывать и реджектить, и тем больше времени останется на настоящую работу: проектирование, анализ, принятие решений и построение качественного ПО.
Команды, которые уже сегодня формируют для LLM ясные правила, структуру и инженерную дисциплину, завтра получают предсказуемый процесс разработки, стабильное качество и меньшее количество бессмысленных правок.
Команды же, которые игнорируют эти требования, неизбежно тратят все больше времени не на создание продукта, а на разбор хаотичных изменений и исправление последствий вайб‑кодинга. В долгосрочной перспективе разница становится критичной.
P. S.
И последнее, о чем нельзя не сказать — это безопасность. Токены, ключи, пользовательские данные, изоляция окружений, утечки через промпты и контекст. Когда вы отдаёте ИИ весь проект — вы отдаёте ему все. Никто не даст гарантии, что завтра при дообучении модели ваши конфиденциальные данные не окажутся в открытом доступе или в ответах чужим пользователям. Но это тема для отдельного разговора.