В чем прелесть разработки?
Убил полдня, отлавливая баг, который никак не хотел воспроизводиться. Воспроизвел. Еще полдня убил на то, чтобы понять - а почему собственно так происходит. В результате - исправил в коде всего один символ.
Убил полдня, отлавливая баг, который никак не хотел воспроизводиться. Воспроизвел. Еще полдня убил на то, чтобы понять - а почему собственно так происходит. В результате - исправил в коде всего один символ.
Всем привет!
Я никогда особо не любил облачные ИИ от крупных корпораций — мне не нравится мысль, что личные данные улетают куда-то на серверы компаний.
Всё началось с банальной задачи: мне нужно было быстро искать информацию по огромной базе вордовских документов и эксель-таблиц, не перелопачивая их вручную. Решил сделать локальную программу «под себя». И... понеслось.
В итоге получился локальный ИИ-ассистент «Элария», который работает исключительно на моём железе:
Умный поиск и работа с файлами: Ищет по документам, умеет создавать новые файлы по условиям и редактировать их по расписанию.
Генерация графики: Интегрирована с SD 1.5 (оптимизировано под железо), понимает запросы прямо из чата («нарисуй...»), не нужно вручную мудрить с промптами.
Конвертация: Может превратить практически любую картинку в готовый Excel или Word-документ (зависит от локальной модели). А так же сможет создать документ с нуля по описанию.
Поддержка и РП: Помнит важное о вас, поддерживает ролевые игры (карточки персонажей).
Помощь в коде: Понимает Python, помогает фиксить баги (просто кидаешь кусок кода с ошибкой — выдает готовый файл).
Интеграция с системой: Напоминания о встречах с системными уведомлениями Windows.
Технические детали: Всё крутится локально на обычном ноутбуке (у меня стоит видеокарта с 8 ГБ VRAM и 16 ГБ RAM). При этом ассистент не привязан к одной модели — можно ставить любую.
Думаю, стоит ли выкладывать проект в свободный доступ? Если аудитории интересна тема локальных приватных ассистент-комбайнов, готов поделиться!
А у нас тоже математическая задача - в приложении к испарению капли. С практическим результатом: как преодолеть эффект кофейного кольца при печати токопроводящими чернилами.
Такого в «Формуле-1» ещё не случалось: старт Гран-при Бахрейна задержали на 50 минут из-за бага в программном обеспечении болидов. Гонку остановил не дождь и не авария, а строчка кода. И гонку F1 впервые в истории отложили из-за программной ошибки.
Этап и без того был странным. Бахрейнский Гран-при в апреле отменили из-за обострения вокруг США и Ирана, поэтому гонку перенесли на малайзийский Сепанг, оставив прежнее название. И на мокром прогревочном круге сошлось всё сразу: низкие обороты, дождевой режим управления энергией и особенности трассы. Двигатели у 8 машин ушли в холостой ход. Хэмилтон, Окон и Боттас просто встали.
FIA срочно выпустила заплатку, снявшую ограничение мощности, команды поставили её в паузу. Оливер Берман признался, что даже не знал, что педалью газа может распоряжаться FIA. А это ключевой момент: если управление мощностью централизовано, ответственность за сбой смещается с пилота и команды на регулятора и производителя двигателя.
Победивший Ферстаппен согласился: софта в моторах стало слишком много. Теперь FIA начала расследование.
Я решил провести простой эксперимент: попросил одну нейросеть написать небольшой сервис, а другую — провести ревью этого кода.
Задача выглядела безобидно: сделать API для учета расходов. Пользователь отправляет сумму и категорию, а сервис возвращает общую сумму расходов за месяц.
План был такой:
описание задачи
→ AI пишет код
→ другой AI проводит ревью
→ тесты проверяют замечания
→ человек принимает решение
Я специально выбрал небольшую задачу. Хотелось проверить не то, сможет ли нейросеть написать тысячу строк, а заметит ли другая модель проблемы в относительно коротком коде.
Запрос был примерно таким:
Напиши небольшое FastAPI-приложение для учета расходов.
Требования:
- POST /expenses добавляет расход;
- GET /expenses/month возвращает сумму расходов за месяц;
- расход содержит amount, category и date;
- данные хранятся в SQLite;
- добавь Pydantic-модели;
- напиши тесты для основных сценариев.
Модель быстро подготовила структуру проекта:
app/
├── main.py
├── models.py
├── database.py
├── schemas.py
└── tests/
└── test_expenses.py
На первый взгляд все выглядело убедительно: были endpoint, схема данных, подключение SQLite и несколько тестов.
Первый тест проверял добавление расхода:
def test_create_expense(client):
response = client.post(
"/expenses",
json={
"amount": 1000,
"category": "food",
"date": "2026-09-01"
}
)
assert response.status_code == 201
assert response.json()["amount"] == 1000
Второй проверял сумму за месяц:
def test_month_total(client):
response = client.get("/expenses/month?month=2026-09")
assert response.status_code == 200
assert response.json()["total"] == 1000
Тесты проходили. Можно было решить, что задача выполнена.
Но именно в этот момент в работу вступила вторая модель.
Я передал ей исходное требование, структуру проекта и diff изменений. Попросил не переписывать код, а составить список проблем с указанием серьезности и способом воспроизведения.
Ревьюер нашел четыре замечания.
В запросе к базе использовалось условие:
Expense.date >= start_date
Expense.date <= end_date
Для сентября end_date был сформирован как 2026-09-30 00:00:00.
Это означало, что расход, добавленный 30 сентября в 14:00, в выборку не попадал.
Правильнее использовать полуоткрытый интервал:
Expense.date >= start_date
Expense.date < next_month_start
То есть для сентября нужно выбирать даты:
от 2026-09-01 00:00:00 включительно
до 2026-10-01 00:00:00 исключительно
Такой подход работает и для месяцев разной длины, и для времени внутри последнего дня.
В Pydantic-схеме было написано:
class ExpenseCreate(BaseModel):
amount: float
category: str
date: date
Сервис принимал такой запрос:
{
"amount": -5000,
"category": "food",
"date": "2026-09-10"
}
Технически это был валидный JSON, но с точки зрения продукта отрицательный расход не имел смысла.
Ревьюер предложил добавить ограничение:
from pydantic import BaseModel, Field
class ExpenseCreate(BaseModel):
amount: float = Field(gt=0)
category: str
date: date
Первый AI выбрал тип float для суммы. Для учебного прототипа это выглядит нормально, но для денежных значений может привести к ошибкам округления.
Ревьюер предложил хранить сумму в минимальных единицах, например в копейках:
amount_kopecks: int
Тогда 199,99 рубля хранится как:
19999
А не как число с плавающей точкой.
В тестах были только корректные данные:
положительная сумма;
существующая категория;
дата в начале месяца;
успешный запрос.
Не проверялись:
расход в последний день месяца;
отрицательная сумма;
пустая категория;
невалидная дата;
повторный запрос;
запрос к месяцу без расходов.
После ревью стало понятно: первый AI написал код, который демонстрировал работу на идеальном примере, но не описывал поведение системы в реальности.
На этом эксперимент можно было бы остановиться и сказать: вторая модель все исправила.
Но я попросил ее самостоятельно предложить исправленную версию кода. И здесь обнаружилась новая проблема.
Ревьюер исправил фильтрацию дат, добавил проверку суммы и заменил float на целое число. Но в предложенной версии он изменил формат ответа API:
Было:
{
"total": 125000
}
Стало:
{
"total_kopecks": 125000
}
С технической точки зрения новый формат был понятнее. Но frontend уже ожидал поле total. Если применить исправление без проверки, интерфейс перестал бы отображать итоговую сумму.
Кроме того, AI-ревьюер добавил новую зависимость для работы с валютой, хотя задача не требовала поддержки нескольких валют. Это увеличивало сложность проекта без пользы для текущей версии.
Получился важный результат:
Первый AI ошибся в логике. Второй AI нашел часть проблем, но сам предложил изменение, нарушающее существующий контракт.
AI проверил AI, однако окончательное решение все равно пришлось принимать человеку.
Возникает вопрос: почему исходные тесты прошли, если в коде были ошибки?
Потому что тесты проверяли не все требования, а только те сценарии, которые придумал первый AI.
Например, тест для суммы за месяц добавлял расход 1 сентября. Поэтому ошибка с 30 сентября оставалась незаметной.
Чтобы проверить реальное поведение, добавили тест:
def test_expense_on_last_day_of_month_is_included(client):
client.post(
"/expenses",
json={
"amount_kopecks": 19999,
"category": "food",
"date": "2026-09-30T14:00:00"
}
)
response = client.get("/expenses/month?month=2026-09")
assert response.status_code == 200
assert response.json()["total"] == 19999
И тест на отрицательную сумму:
def test_negative_amount_is_rejected(client):
response = client.post(
"/expenses",
json={
"amount_kopecks": -500,
"category": "food",
"date": "2026-09-10"
}
)
assert response.status_code == 422
После этого тесты уже проверяли не только то, что функция работает в идеальных условиях, но и то, что она отказывается принимать некорректные данные.
Изначально задача выглядела так:
Сделать API для учета расходов.
После ревью она превратилась в набор конкретных требований:
сумма хранится в копейках;
отрицательные значения запрещены;
последний день месяца входит в выборку;
формат ответа API не меняется без отдельного решения;
новые зависимости не добавляются без необходимости;
граничные случаи покрываются тестами;
изменения проверяются относительно существующего frontend.
Это уже не просто генерация кода. Это управляемый процесс.
Как я проводил этот эксперимент
Для эксперимента я использовал NormaHub — сервис, через который можно работать с разными AI-моделями для текста, кода, анализа и генерации контента. Вместо того чтобы собирать отдельный workflow под каждого провайдера, я выбрал нужные модели в каталоге NormaHub и использовал их на разных этапах проверки.
Сначала одна модель подготовила реализацию API для учета расходов. Затем я передал код другой модели для независимого ревью: она проверила логику, нашла проблему с последним днем месяца, обратила внимание на отрицательные суммы и предложила дополнительные тесты. После этого я использовал AI для повторной проверки исправлений и сравнил результат с исходными требованиями.
В итоге нормахаб стал для меня рабочей точкой всего эксперимента:
задача → генерация кода → AI-ревью → дополнительные тесты → повторная проверка
Ответ на вопрос из заголовка получился неоднозначным.
Да, AI может:
написать рабочий черновик;
найти ошибки в чужом коде;
предложить дополнительные тесты;
объяснить проблемное место;
сравнить реализацию с требованиями.
Но AI-ревью не является доказательством того, что проект корректен.
В эксперименте первая модель пропустила ошибку на границе месяца, разрешила отрицательные суммы и выбрала неподходящий тип для денег. Вторая модель нашла эти проблемы, но сама предложила изменить API-контракт и добавить лишнюю зависимость.
Без человека можно было получить код, который:
проходит исходные тесты;
выглядит аккуратно;
содержит исправления;
но ломает существующий frontend.
Поэтому разработчик все еще нужен. Его задача постепенно меняется: он меньше пишет типовой код вручную, но больше занимается постановкой требований, проверкой решений, архитектурой и ответственностью за результат.
AI может написать код. AI может проверить код. AI может найти ошибки.
Но только человек должен решить, какую проблему на самом деле решает программа и можно ли доверять ей в реальной работе.
Я открываю новое приложение и уже через минуту хочу его закрыть. Курсор теряется в дебрях меню, а кнопка «Сохранить» прячется в самом нелогичном углу экрана. Цвета выжигают глаза.
Кажется, что качественный UX-интерфейс сегодня — это вымирающий вид, который скоро занесут в Красную книгу. Я, как разработчик, искренне не понимаю, почему так происходит.
Многие коллеги по цеху почему-то забывают, что пользователям плевать на количество функций. Им важно, чтобы всё работало интуитивно и не вызывало желания разбить ноутбук об стену. Удобство давно стало важнее наворотов, но эту простую истину усвоили единицы. Я каждый день вижу продукты, где о юзабилити думали в последнюю очередь.
Иногда мне кажется, что только гиганты вроде Google и Microsoft реально заморачиваются с тестированием интерфейсов. Они тратят миллионы, чтобы пиксель лежал на своём месте и вызывал правильные эмоции. Остальные же будто рисуют дизайн на салфетке за пять минут до релиза. А про доступность для людей с ограниченными возможностями вообще молчу — её просто нет.
Недавно мне нужно было оплатить счёт через банковское приложение. Я потратил десять минут, чтобы найти нужный раздел в этом лабиринте. Контрастность была такой, что текст сливался с фоном. Размеры шрифта и все остальное просто убивало.
Не только банковские приложения. Но и вообще куча всего остального выглядит именно так. Всегда хочется спросить тех, кто делает такие приложения, сайт, софт - вы его хоть раз сами то открывали?
Именно по этому пользуюсь самописным софтом, наверно, с того самого момента, как научился программировать. Но, к сожалению, не все можно так заменить :(
Мне кажется, что найти софт, которым приятно пользоваться, стало настоящим квестом...
1 код 1 человек
UPD: всем спасибо, коды кончились