TL;DR
AI-генерация кода ускоряет разработку, но создает “jelly code” — хрупкие решения без архитектурной целостности. Основные проблемы: накопление технического долга, потеря контекста и инвертированный 80/20 rule. Эффективное использование требует строгого code review и компенсирующих практик.
Введение: магия и реальность AI-кодинга
Мы все видели демки, где ChatGPT за 30 секунд генерирует работающий CRUD с графиками и dark mode. Но через полгода такие codebase превращаются в maintenance nightmare. Проблема не в качестве кода как такового, а в его архитектурной согласованности и долгосрочной поддерживаемости.
Jelly Code: хрупкость под капотом
AI генерирует код, который выглядит рабочим, но содержит структурные проблемы:
// Типичные артефакты AI-генерации
function processData(data) {
// 1. Избыточные проверки
if (data && data.items && Array.isArray(data.items) && data.items.length > 0) {
return data.items.map(item => {
// 2. Дублирование логики (уже есть в utils/)
const formatted = `${item.name}-${item.id}`.toLowerCase();
// 3. Неиспользуемый импорт (см. выше)
return formatted;
});
}
// 4. Неявное поглощение ошибок
return [];
}
Характерные маркеры jelly code:
- Over-defensive programming — избыточные проверки вместо четких контрактов
- Context loss — дублирование логики между файлами
- Dead code — неиспользуемые импорты и переменные
- Shallow testing — passing tests с over-mocking
Инвертированный 80/20 принцип
С AI классическое правило переворачивается:
- Первые 80% фичи: 20% времени (AI magic)
- Последние 20%: 300% времени (debugging и интеграция)
Пример из реального проекта:
// AI-сгенерированный хук для API
const useFetchData = (url: string) => {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(setData);
}, [url]);
return data;
};
// Проблемы:
// 1. Нет обработки ошибок
// 2. Нет abort controller
// 3. Нет кэширования
// 4. Нет debounce для частых вызовов
Стратегии работы с AI-кодом
1. Code Review как архитектурный контроль
Не проверяем “работает ли”, а оцениваем:
- Соответствие project guidelines
- Отсутствие дублирования
- Качество абстракций
// Плохо (AI-стиль)
function getUser() {
return fetch('/user').then(r => r.json());
}
// Хорошо (human-refactored)
const api = {
async fetchJson(endpoint, opts) {
const res = await fetch(`/api/v1${endpoint}`, opts);
if (!res.ok) throw new ApiError(res.status);
return res.json();
}
};
2. Компенсирующие практики
- Mutation testing (StrykerJS) для проверки тестов
- Architecture linting (ESLint + custom rules)
- Visual regression для UI-компонентов
# Пример проверки тестов
npx stryker run --mutator typescript
3. Контекстное документирование
AI генерирует JSDoc, но теряет бизнес-контекст:
/**
* @param {number} price - The product price
* @returns {number} - Discounted price
*/
function applyDiscount(price) {
// Почему 15%? Какие продукты исключены?
return price * 0.85;
}
Где AI действительно полезен
- Boilerplate generation:
# Next.js page scaffold
npx ai-gen "create Next.js page with dynamic routes,
getStaticProps and TS support"
- Тесты для стабильных API:
// Vitest + MSW
test('GET /api/user returns 200', async () => {
server.use(rest.get('/api/user', (req, res, ctx) => {
return res(ctx.json({ id: 1, name: 'Test' }));
}));
const res = await fetch('/api/user');
expect(res.status).toBe(200);
});
- Learning spike:
// Вариант 1: Zustand
const useStore = create(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
}));
// Вариант 2: Jotai
const countAtom = atom(0);
const useCount = () => useAtom(countAtom);
Заключение: баланс скорости и качества
AI — мощный инструмент, но не silver bullet. Ключевые принципы:
- Генерируй для обучения, а не для копипасты
- Инвестируй в компенсирующие практики пропорционально использованию AI
- Сохраняй бизнес-контекст там, где это критично
Как проверить здоровье codebase: представьте, что вам нужно переписать его с нуля за месяц. Если понимание кода займет больше времени — вы перегрузили систему AI-генерацией без должного контроля.