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

С другой стороны, все чаще можно услышать жалобы от разработчиков, особенно с грейдом 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.
И последнее, о чем нельзя не сказать — это безопасность. Токены, ключи, пользовательские данные, изоляция окружений, утечки через промпты и контекст. Когда вы отдаёте ИИ весь проект — вы отдаёте ему все. Никто не даст гарантии, что завтра при дообучении модели ваши конфиденциальные данные не окажутся в открытом доступе или в ответах чужим пользователям. Но это тема для отдельного разговора.

Комментарии (0)