<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Блог UDE (Русский)</title><description>Строим публично: архитектурные заметки, инженерные решения и обновления продукта.</description><link>https://blog.flude.guide/</link><atom:link href="https://blog.flude.guide/rss-ru.xml" rel="self" type="application/rss+xml"/><item><title>Программирование без знания языка: как ИИ уволил Doxygen</title><link>https://blog.flude.guide/ru/blog/ai-gone-rogue/</link><guid isPermaLink="true">https://blog.flude.guide/ru/blog/ai-gone-rogue/</guid><description>Как мы пытались парсить XML, почему ИИ внезапно потянул за собой tree-sitter и почему контроль важнее гениального кода.</description><pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;В прошлой части мы остановились на том, что выбросили HTML-выдачу Doxygen в мусорное ведро. План «быстро поправить стили» полностью провалился, потому что невозможно адаптировать структуру из вложенных таблиц родом из девяностых под современный дизайн. Идея второго прототипа звучала солидно: отключить генерацию HTML, взять сырой структурированный XML от того же Doxygen и написать для него нормальный парсер.&lt;/p&gt;
&lt;p&gt;Рабочим языком, как и в прошлый раз, выбрали Python. Он идеально подходит для создания утилит, обработки текста и автоматизации рутины. К тому же вся современная экосистема вокруг искусственного интеллекта строится именно на нем. Логика была проста: если мы хотим активно использовать нейросети для помощи в написании кода, лучше сразу писать на языке, который они знают лучше всего.&lt;/p&gt;
&lt;p&gt;Пришло время раскрыть небольшой секрет, о котором я специально умолчал в первой части: я не знаю Python. Чужой код я плюс-минус понимаю, но сам на нём никогда ничего не писал.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.flude.guide/images/xml_python_mess_1785770351765.jpg&quot; alt=&quot;XML и Python&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Архитектор, который не умеет кодить&lt;/h2&gt;
&lt;p&gt;Это был чистый эксперимент в стиле «программирование без знания языка». Я решил выступить в роли системного архитектора и постановщика задач. ИИ должен был выполнять всю техническую работу: писать готовый код, рефакторить функции и собирать всё воедино.&lt;/p&gt;
&lt;p&gt;Поначалу всё шло подозрительно гладко. Мы накидывали логику разбора гигантских XML-файлов. Я открывал сгенерированный Doxygen файл, видел там узлы, классы, параметры методов, и просто писал в чат: «Найди все элементы с нужными тегами, вытащи оттуда тип, имя и описание, а затем сложи это в JSON». Благодаря прямому доступу ИИ к терминалу мне даже не пришлось копировать код руками. Нейросеть сама писала скрипты, сразу их запускала и выдавала готовый результат.&lt;/p&gt;
&lt;p&gt;Файл наполнялся функциями, скрипт рос. Мне казалось, что мы строим отличную систему. Я даже не вчитывался в код — зачем, если я и так вижу, что документация собирается всё лучше и лучше? Так продолжалось до тех пор, пока один диалог полностью не изменил ход разработки.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.flude.guide/images/ai_manager_coding_1785770359271.jpg&quot; alt=&quot;ИИ пишет код&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Когда ИИ внезапно попросил компилятор&lt;/h2&gt;
&lt;p&gt;В какой-то момент мы обсуждали переносимость нашего движка (мы уже начали называть его UDE) на другие платформы. Я хотел убедиться, что парсер заведется у любого разработчика на любой операционной системе без сложных дополнительных настроек.&lt;/p&gt;
&lt;p&gt;ИИ выдал будничный ответ:
&lt;em&gt;«Конечно, проблем не возникнет. Только для полной переносимости нам потребуется настроить скачивание clang в процессе инсталляции пакета».&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Я смотрел на монитор в полном недоумении. Какой ещё &lt;code&gt;clang&lt;/code&gt;? Мы разбираем XML-документацию для Python-обертки. При чём здесь компилятор языка C? Я так прямо и спросил у нейросети, не сошла ли она с ума.&lt;/p&gt;
&lt;p&gt;ИИ тут же извинился и выдал новую формулировку:
&lt;em&gt;«Прошу прощения, я имел в виду библиотеку tree-sitter. Нам понадобится компилировать её биндинги».&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.flude.guide/images/ai_tree_sitter_1785770368693.jpg&quot; alt=&quot;Tree-sitter и AST&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Инсайт из потери контроля&lt;/h2&gt;
&lt;p&gt;И тут до меня дошло: ИИ больше не парсил XML от Doxygen. Ему это надоело.&lt;/p&gt;
&lt;p&gt;В процессе наших долгих обсуждений архитектуры нейросеть незаметно для меня подключила парсер абстрактных синтаксических деревьев (AST). ИИ сам решил, что читать оригинальный исходный код C++ и Python напрямую через &lt;code&gt;tree-sitter&lt;/code&gt; гораздо надёжнее, чем возиться с костыльной XML-выдачей сторонней утилиты. Он просто исключил Doxygen из цепочки, пока я думал, что мы всё ещё парсим теги.&lt;/p&gt;
&lt;p&gt;Был ли написанный им код хорошим? Понятия не имею, ведь я совершенно не умею писать на Python и не способен оценить архитектурные решения. Алгоритм мог оказаться потрясающе оптимизированным и изящным, либо представлять собой нестабильный набор костылей, работающий исключительно за счет случайного стечения обстоятельств.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.flude.guide/images/black_box_danger_1785770378035.jpg&quot; alt=&quot;Черный ящик кода&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Проблема заключалась в абсолютной потере контроля. Если ИИ в фоновом режиме втихую меняет архитектуру и тянет за собой тяжелые библиотеки парсинга, а ты даже не можешь прочитать его код — проект обречён. Получается классический «черный ящик». Любой минорный баг заставит тебя часами выпытывать у нейросети причины поломки. То же самое касается и нетипичных комментариев в исходниках.&lt;/p&gt;
&lt;p&gt;Этот инцидент подарил нам важнейшее открытие. Мы поняли, что ИИ действительно способен писать собственные прямые парсеры для любых языков программирования, вытаскивая структуру классов и параметры прямо из живого кода. Нам больше не нужны сторонние утилиты.&lt;/p&gt;
&lt;p&gt;Однако, чтобы такой сгенерированный код работал стабильно, его необходимо жёстко контролировать. Нам требовался строгий набор автоматических проверок. Такая система, которая гарантировала бы работоспособность парсера независимо от того, понимаю я написанный код или нет.&lt;/p&gt;
&lt;p&gt;Так мы выкинули наш второй, вполне рабочий прототип в корзину. И начали всё заново, уже в третий раз. Но теперь по совершенно другим правилам — с тестированием на каждом шагу. Об этом я расскажу в следующей части.&lt;/p&gt;
&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;Также читайте нас:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://blog.flude.guide/ru/&quot;&gt;Блог UDE&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://t.me/ude_blog_ru&quot;&gt;Telegram-канал&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content:encoded><category>story</category><category>architecture</category><category>ai</category></item><item><title>Как не надо строить документацию: история одного парсера HTML</title><link>https://blog.flude.guide/ru/blog/how-not-to-build-docs/</link><guid isPermaLink="true">https://blog.flude.guide/ru/blog/how-not-to-build-docs/</guid><description>Как мы пытались обмануть Doxygen, переделать его разметку под наши стандарты и почему это привело нас к созданию собственного движка.</description><pubDate>Mon, 03 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Мы сели писать собственный движок документации от безысходности. Изначально никто не планировал разрабатывать масштабный UDE. У нас была простая утилитарная задача — задокументировать свежую обёртку на Python. Как обычно, самые монструозные костыли начинаются с безобидных скриптов на пару строк.&lt;/p&gt;
&lt;h2&gt;Внезапный Python&lt;/h2&gt;
&lt;p&gt;Наш основной SDK написан на C++. Чтобы им можно было пользоваться из других языков, создаются обертки. Дошла очередь до Python. Разработчики выдали готовый API, который теперь нужно было публиковать на портале документации.&lt;/p&gt;
&lt;p&gt;Мы давно сидели на Doc-o-Matic. Старый, тяжелый, проверенный временем генератор. Одно плохо: код на Python он категорически не понимал. Программа годами не обновлялась, техподдержка давно умерла, поэтому рассчитывать на патчи не приходилось. У нас есть жесткие корпоративные требования к дизайну портала. Ни один из стандартных генераторов им не соответствовал, а задокументировать код было необходимо.&lt;/p&gt;
&lt;p&gt;Мы посмотрели в сторону Doxygen. Утилита вытаскивает структуру из чего угодно. Правда стандартный HTML на выходе выглядит как привет из девяностых. Тут-то нам в голову и пришла гениальная мысль.&lt;/p&gt;
&lt;h2&gt;«Мы просто немного причешем стили»&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;«Doxygen генерирует готовые страницы. Давайте натравим скрипт, подменим пару CSS, и всё будет готово за пару дней».&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.flude.guide/images/html_parsing_nightmare.jpg&quot; alt=&quot;Хаос парсинга HTML&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Оказалось, мы катастрофически недооценили масштаб проблемы. План был прост: перехватить выдачу, подсунуть в свою структуру и пойти пить кофе. Но чем глубже мы лезли в сгенерированный DOM, тем хуже становилось. Doxygen абсолютно игнорировал современные подходы к верстке (вместо понятных тегов мы разгребали завалы таблиц и инлайн-стилей).&lt;/p&gt;
&lt;p&gt;Отступать было поздно. Прототип требовался уже вчера, поэтому пришлось стиснуть зубы и дописывать скрипт. Постепенно он обрастал десятками регулярных выражений, становясь всё более хрупким.&lt;/p&gt;
&lt;h2&gt;Боковое меню и JS-некромантия&lt;/h2&gt;
&lt;p&gt;Самое дикое началось на этапе навигации. У нас в компании строгое правило UI: абсолютно все страницы должны лежать в левом боковом меню (чтобы разработчик видел всю картину). Doxygen с этим подходом не согласен. Он строит меню динамически из глубоко вложенных массивов, размазанных по нескольким сгенерированным файлам JavaScript.&lt;/p&gt;
&lt;p&gt;Нам с ИИ пришлось физически вычитывать эти JS-файлы как обычный текст. Мы парсили массивы, вытаскивали оттуда иерархию классов и руками перестраивали HTML-дерево страницы. Это уже походило на цифровую некромантию.&lt;/p&gt;
&lt;h2&gt;Семь раз отмерь, один раз распарси&lt;/h2&gt;
&lt;p&gt;Прототип в итоге завелся. Снаружи всё выглядело прилично и по стандартам. Но внутри же наш скрипт представлял собой карточный домик на изоленте. Выходит минорный апдейт Doxygen — и весь портал рассыпается с ошибками.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.flude.guide/images/blueprint_planning.jpg&quot; alt=&quot;Сначала думай, потом делай&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Мы потратили уйму времени на попытку срезать угол. Вместо этого можно было спокойно продумать нормальную архитектуру и реализовать ее. Нам стоило сразу вытаскивать абстрактное синтаксическое дерево, или хотя бы просто парсить чистый XML от Doxygen.&lt;/p&gt;
&lt;p&gt;Стало очевидно: нужен свой независимый движок. Мы снова подключили ИИ, чтобы он по-быстрому накидал нормальный парсер для чтения XML от Doxygen. Но и тут всё пошло не так. О том, что бывает, когда оставляешь ИИ без присмотра, расскажу в следующей части.&lt;/p&gt;
&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;Также читайте нас:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://blog.flude.guide/ru/&quot;&gt;Блог UDE&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://t.me/ude_blog_ru&quot;&gt;Telegram-канал&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content:encoded><category>story</category><category>architecture</category></item><item><title>UDE: От исходного кода к качественной документации</title><link>https://blog.flude.guide/ru/blog/ude-source-to-docs/</link><guid isPermaLink="true">https://blog.flude.guide/ru/blog/ude-source-to-docs/</guid><description>Почему связки вроде Doxygen+DoxyBook2+Hugo не справляются с большими проектами, и как UDE решает эту проблему.</description><pubDate>Wed, 22 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;1. Отправная точка: исходный код и комментарии&lt;/h2&gt;
&lt;p&gt;Основа любой качественной API-документации — это комментарии в исходном коде. В больших проектах (например, на C++) они являются единым источником истины. Без них автоматическая генерация документации попросту невозможна.&lt;/p&gt;
&lt;p&gt;Вопрос лишь в том, как превратить эти комментарии в современный, удобный и быстрый сайт для разработчиков.&lt;/p&gt;
&lt;h2&gt;2. Как это решается сегодня — и где система ломается&lt;/h2&gt;
&lt;p&gt;Самый популярный инструмент для C++ — это &lt;strong&gt;Doxygen&lt;/strong&gt;. Однако его родной формат вывода (HTML или XML) не подходит для современных генераторов статических сайтов (SSG), таких как Hugo, Docusaurus или VitePress, которые ожидают на входе Markdown.&lt;/p&gt;
&lt;h3&gt;Связка Doxygen + DoxyBook2 + Hugo&lt;/h3&gt;
&lt;p&gt;Чтобы обойти это ограничение, часто используют промежуточные конвертеры: Doxygen генерирует XML → DoxyBook2 конвертирует XML в Markdown → Hugo собирает сайт.&lt;/p&gt;
&lt;p&gt;Это рабочий вариант, но у него есть серьезные ограничения:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Отсутствие масштабируемости.&lt;/strong&gt; Конвертер читает весь XML-граф в память целиком. На SDK масштаба десятков тысяч классов и методов этот процесс упирается в память и неоправданно долгое время обработки.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Сложность кастомизации.&lt;/strong&gt; Настроить вывод под разные форматы оформления одновременно — сложная задача, так как инструменты не проектировались для высокой гибкости.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. Решение от UDE: единый конвейер&lt;/h2&gt;
&lt;p&gt;UDE полностью перестраивает процесс, убирая лишние этапы конвертации и оптимизируя работу с данными.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.flude.guide/images/cpp_to_docs_pipeline.jpg&quot; alt=&quot;Пайплайн UDE&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Архитектура UDE строится на четком разделении этапов:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Collector&lt;/strong&gt; извлекает данные напрямую из исходного кода.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Parser&lt;/strong&gt; переводит их в нормализованную языково-нейтральную модель — &lt;strong&gt;IR (Intermediate Representation)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Renderer&lt;/strong&gt; мгновенно собирает Markdown/HTML в формате, который понимает целевой SSG, без всяких промежуточных XML-костылей.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Преимущества такого подхода очевидны: нет лишнего шага конвертации, а из единой точки (IR) можно рендерить документацию в любых нужных форматах и стилях.&lt;/p&gt;
&lt;h2&gt;4. Скорость и предсказуемость&lt;/h2&gt;
&lt;p&gt;Для больших проектов критически важно время сборки. В UDE эта проблема решается с помощью инкрементального кэширования.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.flude.guide/images/incremental_cache.jpg&quot; alt=&quot;Инкрементальный кэш&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Вместо загрузки всего графа сущностей каждый раз, UDE пересчитывает только то, что &lt;strong&gt;реально изменилось&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Кросс-платформенность.&lt;/strong&gt; Пайплайн работает абсолютно идентично локально на Windows и в CI на Linux.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Doc-as-code.&lt;/strong&gt; Конфигурация того, что документировать, версионируется вместе с кодом и собирается в том же CI.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5. UDE и ручные руководства (DevGuide)&lt;/h2&gt;
&lt;p&gt;API-справочник, сгенерированный из кода, отвечает на вопрос «как устроены функции и классы». Но он не может рассказать, «в каком порядке их вызывать для решения конкретной бизнес-задачи». Для этого нужны DevGuide — написанные вручную статьи и туториалы.&lt;/p&gt;
&lt;p&gt;UDE не пытается заменить этот ручной труд. Вместо этого он обеспечивает идеальную интеграцию: генерируемый API-справочник остается полным и всегда актуальным, органично соседствуя с ручными гайдами на страницах современных SSG.&lt;/p&gt;
&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;Также читайте нас:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://blog.flude.guide/ru/&quot;&gt;Блог UDE&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://t.me/ude_blog_ru&quot;&gt;Telegram-канал&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content:encoded><category>architecture</category></item></channel></rss>