Знакома ли вам ситуация? Вы открываете файл контроллера на 2000 строк. Там перемешаны SQL-запросы, HTML-разметка, бизнес-логика и комментарии на ломаном английском. В голове начинает играть тревожная музыка, а внутренний голос шепчет: «Закрой это немедленно, пока оно не сломалось».
В психологии это называется «когнитивная перегрузка». Мозг отказывается одновременно обрабатывать такое количество переменных. Раньше программистам приходилось часами разбирать распечатки кода, как детективы, пытаясь восстановить логику.
Сегодня всё иначе. Правильный промпт-инжиниринг превращает хаос в структурированный текст. Когда вы подаёте нейросети сложный код с чёткой инструкцией, это как надеть очки дополненной реальности. Вы перестаёте бояться и начинаете контролировать ситуацию.
В этой статье — 6 фундаментальных паттернов промптинга, которые помогут разработчику справиться с любой задачей:
- «Хирург-архитектор» — глубокий рефакторинг на Python
- «Терпеливый ментор» — разбор непонятного TypeScript
- «QA-параноик» — генерация надёжных тестов на React
- «Полиглот-транслятор» — миграция с PHP на Python
- «Жестокий ревьюер» — аудит безопасности кода на Go
- «Говорящий с базами данных» — оптимизация медленных SQL-запросов
Паттерн 1: «Хирург-архитектор» (глубокий рефакторинг)
Многие разработчики пишут промпты вроде: «Почини этот код». Это как сказать врачу: «Сделайте мне хорошо». ИИ поправит синтаксис, но оставит архитектурный хаос нетронутым.
Чтобы получить качественный результат, нужно задать роль, ограничения и целевую архитектуру.
### Инструкция ###
Ты – Staff Software Engineer уровня FAANG с 15 годами опыта в бэкенде.
Твоя задача – провести безжалостный рефакторинг приведенного ниже Python-кода (написанного на FastAPI).
Проблема: этот код – типичный “all-knowing object” и нарушает принципы SOLID.
Маршрут обрабатывает запросы к БД напрямую через SQLAlchemy, делает бизнес-логику внутри роутера, шлет имейл и возвращает ответ.
Что нужно сделать:
1. Раздели этот код на 3 слоя: router, service (бизнес-логика), repository (доступ к данным).
2. Используй dependency injection (DI).
3. Добавь Pydantic-схемы для входных и выходных данных, чтобы гарантировать типизацию.
4. Обязательно используй асинхронные сессии БД.
В ответе выдай только обновленный код.
### Код для рефакторинга ###
```py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from models import User, Order
from database import get_db
import smtplib
from email.message import EmailMessage
router = APIRouter()
@router.post("/process_order")
def process_order(user_id: int, item_id: int, quantity: int, price: float, db: Session = Depends(get_db)):
# 1. Проверяем юзера
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(status_code=404, detail="User not found")
# 2. Проверяем баланс (бизнес-логика)
total_cost = quantity * price
if user.balance < total_cost:
raise HTTPException(status_code=400, detail="Not enough balance")
# 3. Снимаем деньги и создаем заказ (Микс бизнес-логики и работы с БД)
user.balance -= total_cost
new_order = Order(user_id=user_id, item_id=item_id, quantity=quantity, status="PROCESSING")
db.add(new_order)
db.commit()
db.refresh(new_order)
# 4. Шлем имейл (внешний сервис, жестко привязанный)
try:
msg = EmailMessage()
msg.set_content(f"Ваш заказ {new_order.id} на сумму {total_cost} в обработке!")
msg['Subject'] = 'Статус заказа'
msg['From'] = 'noreply@store.com'
msg['To'] = user.email
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()
except Exception as e:
print(f"Failed to send email: {e}")
return {"status": "success", "order_id": new_order.id, "remaining_balance": user.balance}
```
Анализ промпта «Хирург-архитектор»
Ролевой промпт — «ты Senior Staff Engineer» — настраивает модель на генерацию промышленного кода, отсекая примитивные решения.
Чёткие ограничения предотвращают избыточность: мы явно указали архитектуру (router, service, repository), требование DI и асинхронности. Это исключает «джуновские» костыли.
Результат — готовая трёхслойная структура, тестируемая и соответствующая best practices. Вы не просто чините код, вы проектируете систему.
Паттерн 2: «Терпеливый ментор» (разбор непонятного кода)
Иногда вы сталкиваетесь с кодом, будто написанным человеком, ненавидящим человечество. Например, TypeScript с цепочками опциональных свойств, регулярками и вложенными reduce.
### Роль и задача ###
Ты – ментор, технически подкованный Senior Frontend Developer. Я – Junior-разработчик.
Пожалуйста, объясни мне этот кусок TypeScript-кода так, чтобы я полностью понял, что он делает под капотом.
Требования к ответу:
1. Начни с краткого саммари (в двух предложениях) – какова глобальная цель функции?
2. Сделай пошаговый разбор логики работы функции.
3. Объясни, что произойдет в крайних случаях (edge cases): например, если на вход придет null, пустой массив или объект без нужных ключей.
4. Если код написан плохо, предложи более читаемый современный вариант (например, избегая лишних reduce, если можно использовать map/filter или опциональную цепочку ?.).
### Код для разбора ###
```typescript
type ComplexData = {
meta?: {
nodes?: Array<
{
id: string;
value: number | string;
metadata?: Record;
}
>;
}
};
function extractAndCompute(data: ComplexData | null): number {
return (data && data.meta && data.meta.nodes)
? data.meta.nodes.reduce((acc, curr) => {
if (curr && typeof curr.value === 'string' && curr.value.match(/^\d+$/)) {
acc += parseInt(curr.value, 10);
} else if (curr && typeof curr.value === 'number') {
acc += curr.value;
} else if (curr && curr.metadata && curr.metadata['fallbackValue']) {
acc += Number(curr.metadata['fallbackValue']) || 0;
}
return acc;
}, 0)
: 0;
}```
Анализ промпта «Терпеливый ментор»
Этот промпт превращает ИИ из генератора кода в наставника. Вместо «сделай» — вы просите «объясни».
Разделение на саммари, пошаговый разбор и edge cases заставляет модель не просто прочитать код, а выполнить его мысленно с разными входными данными.
Особенно важно объяснение регулярки ^\d+$: она отсекает строки вроде "10px", что легко упустить. ИИ предлагает заменить цепочку проверок на опциональную цепочку (?) и упростить логику.
Паттерн 3: «QA-параноик» (генерация непробиваемых тестов)
Разработчики не любят писать тесты. Но ИИ — обожает. Главная проблема: если написать «Напиши тесты», вы получите только «happy path». Нужны тесты, которые ловят баги.
### Инструкция ###
Действуй как параноидальный QA Automation Engineer, который обожает находить баги и покрывать код тестами на 100%.
Я использую фреймворк Vitest и библиотеку React Testing Library (@testing-library/react).
Напиши исчерпывающий набор unit-тестов для следующего React-компонента.
Твои тесты должны:
1. Строго следовать паттерну arrange-act-assert (AAA) с комментариями для каждого этапа.
2. Покрывать не только “happy path”, но и крайние случаи:
- Что если API вернет 500-ю ошибку?
- Что если пользователь быстро кликнет по кнопке дважды?
- Проверку того, что во время загрузки кнопка переходит в состояние disabled.
3. Замокать глобальный fetch API (встроенными средствами Vitest) и очищать моки после каждого теста (afterEach).
Выдай только код тестов.
### Компонент ###
```tsx
import React, { useState } from 'react';
interface CheckoutProps {
cartId: string;
onSuccess: (orderId: string) => void;
onError: (errorMsg: string) => void;
}
export const CheckoutButton: React.FC= ({ cartId, onSuccess, onError }) => {
const [isLoading, setIsLoading] = useState(false);
const handleCheckout = async () => {
if (isLoading) return;
setIsLoading(true);
try {
const response = await fetch(`/api/checkout/${cartId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error(`Server responded with status ${response.status}`);
}
const data = await response.json();
onSuccess(data.orderId);
} catch (error: any) {
onError(error.message || 'Something went wrong');
} finally {
setIsLoading(false);
}
};
return (
);
};
```
Анализ промпта «QA-параноик»
Промпт задаёт контекст: Vitest и React Testing Library. Это исключает генерацию тестов под Jest, если проект на Vite.
Паттерн arrange-act-assert заставляет ИИ структурировать тесты. Вы видите: подготовка моков (arrange), клик (act), проверка состояния (assert).
Модель генерирует тесты на ошибки API, двойной клик, состояние загрузки. Это реальная защита продакшена. Хороший тест — не тот, что зелёный, а тот, что красный, когда код сломан.
Паттерн 4: «Полиглот-транслятор» (миграция кода и переводы)
Миграция с одного языка на другой — это не копирование. PHP и Python имеют разные парадигмы, стандарты и библиотеки.
### Инструкция ###
Твоя задача – перевести (мигрировать) старый PHP-код на современный Python (версия 3.11+).
Правила миграции:
1. Сохрани оригинальную бизнес-логику 1 к 1. Не удаляй функционал!
2. Используй возможности современного Python: типизацию (type hints), `dataclasses`, f-строки.
3. Убери все PHP-специфичные грязные хаки и используй стандартные питоновские подходы (например, list comprehensions или генераторы словарей).
4. Добавь docstrings Google-формата для всех созданных функций.
5. Напиши краткое объяснение того, какие функции стандартной библиотеки Python заменили встроенные функции PHP (например, как ты обработал работу с датами или массивами).
### Код на PHP ###
```php
// Скрипт расчета бонусов сотрудников на основе CSV-файла
function calculateEmployeeBonuses($csvFilePath, $bonusPercentage = 10) {
if (!file_exists($csvFilePath)) {
throw new Exception("Файл не найден.");
}
$file = fopen($csvFilePath, 'r');
$employees = [];
$headers = fgetcsv($file); // Пропускаем заголовок
while (($row = fgetcsv($file)) !== false) {
$id = $row[0];
$name = $row[1];
$baseSalary = floatval($row[2]);
$joinDate = $row[3]; // Формат YYYY-MM-DD
// Если человек работает больше 5 лет, бонус удваивается
$currentDate = new DateTime();
$joinDt = new DateTime($joinDate);
$diffYears = $currentDate->diff($joinDt)->y;
$actualBonusPercent = $diffYears >= 5 ? ($bonusPercentage * 2) : $bonusPercentage;
$bonusAmount = ($baseSalary * $actualBonusPercent) / 100;
$employees[] = [
'id' => $id,
'name' => $name,
'salary' => $baseSalary,
'bonus' => $bonusAmount,
'total' => $baseSalary + $bonusAmount
];
}
fclose($file);
// Сортировка по размеру бонуса по убыванию
usort($employees, function($a, $b) {
return $b['bonus'] <=> $a['bonus'];
});
return $employees;
}
?>```
Анализ промпта «Полиглот-транслятор»
Указание версии Python 3.11+ предотвращает генерацию устаревшего кода. Запрет «грязных хаков» исключает PHP-стиль в Python.
ИИ использует dataclass, type hints, csv.DictReader, f-строки и sorted() вместо usort. Он корректно обрабатывает разницу в годах, учитывая, что в Python нет diff()->y.
Важно: модель объясняет, какие функции заменили PHP-аналоги. Это помогает разработчику понять логику миграции и избежать багов.
Паттерн 5: «Жестокий ревьюер» (код-ревью и аудит безопасности)
Вы написали код. Линтер молчит, тесты зелёные, но вы чувствуете подвох. Вместо того чтобы отвлекать коллегу, можно запустить «прожарку» нейросетью.
### Инструкция ###
Действуй как безжалостный Staff Security Engineer / Senior Reviewer на языке Go. Твоя задача — провести жесткое код-ревью и аудит безопасности.
Ищи следующие проблемы:
- Состояние гонки данных (race conditions).
- Утечки памяти (goroutine leaks / memory leaks).
- Уязвимости безопасности (path traversal, SQLi и т. д.).
- Плохую обработку ошибок.
Формат ответа:
Выведи Markdown-таблицу со столбцами: Уязвимость/проблема | Степень серьезности | Объяснение.
После таблицы предложи исправленный вариант кода (только исправленный код, без лишней воды).
Будь предельно критичен, не хвали код.
### Код для аудита (уязвимый Go-сервер) ###
```go
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
var visitorCount int
func handler(w http.ResponseWriter, r *http.Request) {
// Увеличиваем счетчик посетителей
visitorCount++
// Получаем параметр "file" из query
fileName := r.URL.Query().Get("file")
if fileName == "" {
fmt.Fprintf(w, "Welcome! You are visitor number %d.", visitorCount)
return
}
// Читаем запрошенный файл
basePath := "/var/www/uploads/"
fullPath := basePath + fileName
data, err := ioutil.ReadFile(fullPath)
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
return
}
w.Write(data)
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("Server is running on port 8080...")
http.ListenAndServe(":8080", nil)
}
```
Анализ промпта «Жестокий ревьюер»
Инструкция «Будь предельно критичен, не хвали код» отключает вежливость ИИ, навязанную RLHF. Мы получаем честный, технический разбор.
Модель находит две критические уязвимости:
1. Path traversal: запрос вида ../../etc/passwd позволяет читать системные файлы. Решение — filepath.Clean() и проверка пути.
2. Гонка данных: visitorCount++ без синхронизации. Решение — sync/atomic.
Это уровень SAST-инструмента, но с объяснениями и исправлениями.
Паттерн 6: «Говорящий с базами данных» (оптимизация SQL)
Медленные SQL-запросы — главная боль. Простой промпт «Оптимизируй SQL» бесполезен. Нужен контекст: план выполнения, размер таблиц.
### Инструкция ###
Ты – Senior Database Administrator (DBA), специализирующийся на PostgreSQL.
Этот SQL-запрос работает катастрофически медленно. Таблица `orders` содержит 10 миллионов строк, `users` – 2 миллиона.
Ниже я привожу:
1. Сам проблемный запрос.
2. План выполнения запроса (EXPLAIN ANALYZE).
Твоя задача:
1. Проанализировать вывод EXPLAIN ANALYZE и указать точное узкое горлышко, например seq scan, nested loop или сортировка в памяти.
2. Переписать SQL-запрос для максимальной оптимизации (используй CTE, оконные функции или JOIN’ы, если подзапросы тормозят).
3. Предложить команды `CREATE INDEX`, которые полностью покроют этот запрос (используй композитные или частичные индексы, если необходимо).
### Медленный SQL-запрос ###
```sql
SELECT
u.id,
u.username,
(SELECT SUM(o.total_price) FROM orders o WHERE o.user_id = u.id AND o.status = 'COMPLETED' AND o.created_at >= '2025-01-01') as total_spent
FROM
users u
WHERE
u.is_active = true
ORDER BY
total_spent DESC NULLS LAST
LIMIT 50;
```
### Лог EXPLAIN ANALYZE ###
```
Limit (cost=1000000.45..1000001.25 rows=50 width=44) (actual time=14523.456..14523.512 rows=50 loops=1)
-> Sort (cost=1000000.45..1005000.45 rows=2000000 width=44) (actual time=14523.444..14523.471 rows=50 loops=1)
Sort Key: ((SubPlan 1)) DESC NULLS LAST
Sort Method: external merge Disk: 45000kB
-> Seq Scan on users u (cost=0.00..55000.00 rows=2000000 width=16) (actual time=0.045..5421.123 rows=1850000 loops=1)
Filter: is_active
Rows Removed by Filter: 150000
SubPlan 1
-> Aggregate (cost=12.45..12.46 rows=1 width=8) (actual time=0.004..0.004 rows=1 loops=1850000)
-> Seq Scan on orders o (cost=0.00..12.44 rows=1 width=4) (actual time=0.001..0.003 rows=2 loops=1850000)
Filter: ((user_id = u.id) AND ((status)::text = 'COMPLETED'::text) AND (created_at >= '2025-01-01'::date))
Rows Removed by Filter: 4
Planning Time: 0.123 ms
Execution Time: 14525.888 ms
```
Анализ промпта «Говорящий с базами данных»
ИИ видит loops=1850000 и external merge Disk: 45000kB — это признак коррелированного подзапроса, выполняемого для каждой строки. Это как доставка миллиона посылок по одной.
Решение: переписать через CTE. Сначала агрегировать заказы, затем присоединить к пользователям. Это сокращает время с 14 секунд до долей секунды.
ИИ предлагает создать:
- Частичный индекс: CREATE INDEX idx_orders_completed_active ON orders(user_id) WHERE status = 'COMPLETED';
- Композитный covering-индекс: CREATE INDEX idx_orders_covering ON orders(user_id, created_at) INCLUDE (total_price);
Это уровень опытного DBA. Такой промпт экономит часы работы и нервы.
Сводная таблица: техники промптинга для разработчиков
Какие приёмы мы использовали:
- Назначение роли: «Ты Staff Engineer» — переключает ИИ на промышленный уровень кода.
- Цепочка рассуждений: «Сначала саммари, потом разбор» — снижает галлюцинации.
- Few-shot prompting: примеры формата ответа — закрепляют стиль.
- Негативные ограничения: «Не хвали», «Убери PHP-хаки» — блокируют нежелательные паттерны.
- Глубокий контекст: вставка EXPLAIN ANALYZE — позволяет ИИ опираться на реальное поведение системы.
Итоги: промпты как новый язык интерфейса
Эра «Напиши мне функцию для сортировки» прошла. Современные промпты снимают колоссальную когнитивную нагрузку.
Вместо того чтобы распутывать чужие мысли, вы делегируете рутину ИИ. Вы становитесь не просто кодером, а архитектором и ревьюером.
Сохраните эти 6 паттернов. Адаптируйте под свои задачи. Используйте каждый раз, когда сталкиваетесь с препятствием.
Keep coding, keep prompting!