Реддит и Хабр забиты историями о том, как кто-то «написал приложение за вечер с помощью ChatGPT, вообще не зная программирования». Маркетологи называют это вайбкодингом — ты просто описываешь свои намерения, а ИИ выдает готовый продукт.
Я проверил, и вот мой спойлер: на масштабе чуть большем, чем программа на 500 строк, это не работает.
Август 2025 года. Мне понадобилась утилита со сложной логикой: конвертер выгрузок Telegram (JSON) в чистый текст для LLM. Проект десктопный, с GUI, графиками и парсингом. Вместо того чтобы писать код руками, я провел эксперимент: стать техлидом для связки актуальных на тот момент моделей (Claude 4.0 + Gemini 2.5 + Cursor).
Я заранее дал им архитектуру. Они собрали первый MVP. А затем, чтобы этот «MVP» (нет) не сложился как карточный домик через неделю, мне пришлось четырежды инициировать глобальный рефакторинг, потратить 40 часов на борьбу с галлюцинациями вокруг Matplotlib и разгребать цикличные зависимости.
Эта статья — рефлексия и разбор полётов. Это история о том, почему в 2026 году главный навык инженера — это умение видеть деревья за лесом и вовремя сказать ИИ: «Нет, твоя архитектура никуда не годится, всё переделываем».
Разработку я начал не с main.py. Я скопировал структуру папок из своего старого проекта и попросил Claude: «Сделай так же, но реализуй полноценный Dependency Injection».
Нейросеть сгенерировала красивую файловую структуру. На бумаге всё выглядело как по учебнику: папки core/, presenters/, ui/, services/. Но при попытке добавить первую сложную фичу вылезла реальность — структурная связность была ужасающей.
Иллюзия разделения слоев: Файлы main_window.py (логика окна) и main_window_ui.py (вёрстка) импортировали друг друга и наследовались друг от друга. Разделить их было невероятно трудной задачей — они срослись на большинстве уровней, полностью завися друг от друга, действуя как единый скрипт.
Презентер-маршрутка: В MainPresenter нейросеть запихнула вообще всё: от логики чтения JSON до обработки кликов по координатам графика. Это был самый настоящий God Object, который по какой-то нелепой причине был назван презентером.
DI для галочки: Контейнер внедрения зависимостей существовал, но 80% сервисов всё равно создавались через прямое new Service(). ИИ не прокидывал их через конструкторы, он ни капли не заботился о долгосрочной поддержке всего этого ужаса.
Итог: Приложение компилировалось и работало, но изменение одной кнопки ломало три соседних сервиса и подсвечивало массовые гонки состояний. ИИ отлично сымитировал внешнюю форму чистой архитектуры, но сделал это только на уровне названий файлов. Без жёсткого контроля со стороны человека проект мгновенно скатился в процедурную лапшу.
Самые большие провалы случились с наиболее «кастомными» задумками приложения. Мне нужен был интерактивный график статистики сообщений в стиле KDE Filelight. Я дал Gemini референсный код этого проекта на C++ и попросил по духу адаптировать идею для Python с моими хотелками.
Ошибка №1: Выбор инструмента
И вот тут Gemini подложила мне свинью. Я спрашиваю: на чём рисовать будем? Она: «Matplotlib, так как там проще всего реализовать предложенную задумку». И я поверил... А это, оказывается, библиотека для учёных, а не для GUI (отсюда и тормоза в отрисовке), и даже когда я это осознал, то не хотел её выбрасывать, веря, что «ещё чуть-чуть — и мы сможем оптимизировать отрисовку графика». Мы потратили 40 часов, пытаясь заставить этот научный комбайн работать в десктопном приложении.
Ошибка №2: Отсутствие доменной модели
Чтобы синхронизировать клики по графику и календарь экспорта, ИИ привязал бизнес-логику (какие сообщения пойдут в итоговый текстовый файл) к визуальной структуре UI-дерева графика (год/месяц/день как визуальные узлы) самым топорным способом из возможных.
Вместо того чтобы создать простую абстракцию, ИИ реализовал логику так: мы генерируем древо на основе участков текста, но не «по-нормальному», а «все сообщения внутри 2024-xx-xx — узел 2024 года», а месяц — «все сообщения внутри 2024-10-xx», и всё это цеплялось не к абстрактной логике, где каждый день — отдельная ячейка, а «отдельный кусок текста — это узел». И вот, если отключить 2024 год на диаграмме, а затем включить «декабрь 2024 года» на ней же, то итоговый результат — это либо почти рандом, либо «ошибка».
Решение:
Мы потратили 40 часов на попытки заставить Matplotlib работать быстро и без багов: выстрадали логику соотнесения координат кликов курсора с визуальными сегментами, исправили рассинхрон стейтов, создали логику оптимизации количества сегментов для отрисовки. Но когда тормоза интерфейса стало слишком сложно игнорировать, мой внутренний перфекционизм пересилил страх перед сменой библиотеки. За пару часов мы портировали отрисовку на нативный QGraphicsScene.
Отдельно с ИИ мы переписали логику дат: вместо практически визуального «что экспортировать» появился явный набор выбранных дат (Set[QDate]), и бизнес-логика стала опираться на него же, а бонусом сам график превратился в тупую view, которая просто рисует этот набор.
Claude сделал неплохой стартовый набросок UI, но он выглядел, мягко говоря, криво — как проект студента первого курса IT. Это не мой уровень ожиданий.
Процесс доработки выглядел как диалог с очень быстрым, но безынициативным верстальщиком. Утрированный пример как это происходило:
Я: «Сделай три колонки».
ИИ: (Делает).
Я: «Превью снизу неудобно, перенеси наверх-справа, добавь разделитель».
ИИ: (Делает + ломает сигналы от свичей).
Я: «Markdown отрисовывается некрасиво стандартной библиотекой. Давай лучше заменим на HTML-рендеринг с кастомным CSS».
Вывод: ИИ не придумает UX. Он сделает ровно тот минимум, который вы попросите. Чтобы получить современный интерфейс, мне пришлось итеративно «лепить» его словами и в процессе постигать дзен отладки, когда из-за быстрого прототипирования код регулярно и вполне закономерно ломался.
На волне хайпа я попробовал запустить режим мультиагентов (это было ещё до финального рефакторинга, чтобы провести «стресс-тест»). У меня была конфигурация: один агент правит UI, второй работает по бизнес-логике, третий разрабатывает план дистрибуции под Flatpak и Windows.
Мой вердикт: для пет-проектов с плавающей архитектурой это полностью не работает.
После быстрого мерджа изменений от всех трёх агентов я смотрел на проект и совершенно не понимал: кто из них не справился, а кто выполнил работу только на 20%? Ты пишешь большое ТЗ на две страницы, агенты активно шуршат, а по итогу открываешь, смотришь: «да вроде всё осталось как было, UI тот же, но отпали иконки у кнопок и сломался парсер».
Это похоже на работу в большой неэффективной команде: результатов нет, а с кого спрашивать — не понятно, в отличие от работы с одним агентом. Я думаю, что мультиагенты — отличная задумка, если вам нужно получить 3 разных варианта решения одной проблемы и выбрать лучший. Вероятно, они сработают и на поздних стадиях, когда архитектура уже цельная и ошибиться трудно. Но делить между ними задачи на рыхлой базе MVP — бессмысленная трата времени.
Главный миф AI-кодинга: код пишется один раз. Реальность: рефакторинг с ИИ — это непрерывный процесс, где ваша роль эволюционирует по мере «взросления» кодовой базы.
За несколько месяцев я провёл четыре глобальных перестройки.
Стадия 1: Ручное управление (Микроменеджмент)
Прототип работал, но внутри был упомянутый монолит. Я дал команду: «Разбей MainPresenter, раздели ответственность».
Мои ожидания: ИИ заменит 10 файлов, и всё будет работать, я наконец добавлю фичу, о которой думал последний час.
Реальность: 4+ критические ошибки при первом же запуске. Отвалились стили, перестали открываться диалоговые окна, сломалась асинхронщина. Повторные генерации с прошлого сохранения показали ровно тот же результат... Мне пришлось вручную ревьюить каждое изменение, собирать трейсы ошибок и мелкими шажками, на пару с агентом, всё это чинить. Процесс занял несколько дней, а добавление новых фичей постоянно откладывалось, что раздражало ещё больше, чем бесконечный процесс рефакторинга. На данном этапе ИИ требовал полного личного внимания.
Стадия 2: Изоляция компонентов
Второй раз был сфокусирован на выносе сложных кусков, таких как календарь и настройки, в композитные виджеты. Опыт первого рефакторинга помог: я уже знал, где ИИ, скорее всего, схалтурит по глупости и каким образом сломает логику. За счёт этих знаний мы делали меньше итераций и двигались быстрее.
Стадия 3: Разделение слоев (Роль Архитектора)
На третий раз мы перешли к вычищению UI. База уже была в разы лучше, и я наконец мог давать высокоуровневые команды: «Вынеси всю логику парсинга Telegram JSON в отдельный слой Core. UI должен стать тупым и только дергать методы».
Количество циклов «правка–поломка–починка» ещё резче сократилось.
Стадия 4: Автономия (Роль Заказчика)
К четвертому рефакторингу база стала чистой. Я поставил задачу: «Закончи DI. Убери все костыли, убедись, что слои независимы».
И тут случилось неожиданное. Агент начал находить неочевидные баги сам. Тир-лист достижений:
Нашел само-инъекции (где DI-контейнер внедрял зависимости внутрь самого себя).
Выявил «дыры» в инкапсуляции, где слои обращались друг к другу напрямую.
Обнаружил классические гонки данных при быстром клике по UI и сам предложил решение с мьютексами и очередями событий.
Результат: ядро приложения стало настолько независимым, что я смог запустить конвертер в режиме CLI, вообще без импорта PyQt (без графической библиотеки).
Разработка с помощью LLM — это не генерация кода. Это итеративное управление качеством и техническим долгом, который генерируется со сверхзвуковой скоростью.
Критическое мышление остается на вас. ИИ всегда предложит самое популярное, но не всегда самое верное решение (Matplotlib). Ваша задача — сказать «нет» и спроектировать правильную модель.
Рефакторинг первичен. Сразу после прототипирования с той же ллм нужно действовать максимально внимательно и вручную контролировать первые изменения. И только когда каркас выстроен, нейросети можно доверять задачи «под ключ».
Главная проблема современных моделей в том, что у них напрочь отсутствует здравый смысл. Они поспешно уходят в цикличные попытки починить костыль, заменяя в нём гвозди на шурупы, вместо того чтобы вовремя сменить парадигму, когда это требуется.
Простейший пример: я прошу сделать так, чтобы приложение запоминало свой размер и позицию на экране. ИИ честно пишет код. Из-за асинхронщины и состояния гонки в 5+ местах (непонятно, какой именно сервис закроет окно последним и чьи данные верны) стейт не сохраняется. Что делает ИИ? Вместо того чтобы сказать: «Чувак, у тебя тут гонка данных, если мы не починим архитектуру закрытия, мы никогда не сможем сделать это по Clean Code», он тратит 20$ контекста на то, чтобы написать гениальную внешнюю систему перехвата этих значений перед смертью процесса.
Глядя на итоговый код Tkonverter, я понимаю одну вещь. Моя задача — управлять командой невероятно быстрых стажеров, за которыми нужен глаз да глаз. И, честно говоря, это один из самых сложных и интересных инженерных опытов в истории моих пет-проектов.
Во второй части: как я парсил 100-мегабайтные JSON из Telegram, боролся с лимитами контекста LLM и почему пришлось написать свой UI-тулкит.
Код: GitHub
© 2026 ООО «МТ ФИНАНС»
Источник


