- BrainTools - https://www.braintools.ru -
Когда речь заходит о модернизации легаси-систем, главная проблема обычно не в том, чтобы написать новый код. Самое больное место — это понять, как вообще всё устроено и что с этим делать дальше.
Здесь на помощь приходит ИИ. Его можно использовать не только как «генератор кода», а как инструмент для восстановления архитектурных идей старых систем. Это здорово экономит время на предварительном проектировании и снижает общую трудоёмкость.
Большинство коммерческих AI-сервисов сегодня отлично справляются с «случайной сложностью» разработки: генерация кода уже почти рутина и во многом автоматизирована. Но настоящий профит в модернизации — это работа с концептуальным уровнем.
Например, статический анализ помогает системно собрать контекст: как устроен код, как связана база данных. Эти данные можно скормить большой языковой модели, и она уже умеет делать полезные выводы.
А ещё LLM можно использовать для суммаризации: прогоняете через неё легаси-код — на выходе получаете более-менее внятный список бизнес-требований.
Фред Брукс в своей знаменитой работе “No Silver Bullet” [1] («Нет серебряной пули») ещё в 80-х сформулировал неприятную мысль: кратного роста продуктивности разработки не будет, пока мы не научимся справляться с существенной сложностью (essential complexity). Под ней он понимал не сам процесс написания кода, а проработку взаимосвязанных компонентов системы. Код — это уже, по сути, «тривиальный» финальный штрих.
Сегодня у нас есть Copilot [2], aider [3] и cline [3] и куча других AI-ассистентов, которые без проблем превращают текстовое описание в рабочий код. Но если вспомнить Брукса, получается, что они закрывают в основном зону «случайной сложности»: помогают с рутиной, но почти не трогают то, что реально больно — спецификацию, проектирование и тестирование концептуальной конструкции.
Мы же хотим поговорить о другом. В этой статье делимся опытом [4], как большие языковые модели (LLM) могут помогать не только с кодогенерацией, но и с восстановлением и уточнением архитектурных концепций, лежащих в основе ПО. Покажем, как это снижает фундаментальную сложность и реально повышает шансы вытянуть крупные проекты модернизации.
Если где-то и видно, насколько тяжело даётся концептуализация ПО, то это в легаси-системах. Они продолжают жить в проде, часто критичны для бизнеса, но при этом давно устарели и знакомы всё меньшему числу инженеров.
Главная их беда — «концептуальный дрейф»: когда бизнес развивается в одну сторону, а софт остаётся в другой. С каждым изменением вмешиваться в систему становится сложнее, и компании приходится либо мириться с расхождениями, либо как-то закрывать их костылями в процессах. В какой-то момент цена таких решений превращается в бизнес-риск, и тогда приходит время модернизации.
И вот тут проявляется самое узкое место — восстановление исходных концепций системы. Без понимания того, зачем и как всё было сделано, модернизация легко превращается в минное поле: можно сломать скрытую функциональность или потерять клиентов, завязанных на «невидимые» особенности системы. Именно поэтому реконструкция архитектурных идей легаси — ключевой этап и самая непростая задача при таких проектах.

Представим e-commerce компанию, которая сначала работает только с розницей. Потом появляется отдельное подразделение для оптовиков — со своими правилами скидок и выставления счетов. Звучит логично [5], но вот где возникает проблема: если система для опта напрямую завязана на розничную реализацию, то вся «независимость» двух бизнес-единиц остаётся лишь на бумаге. По сути, функции оптового направления будут работать через правила, придуманные для розницы — и это классический пример концептуального дрейфа.
Когда дрейф заходит далеко, модернизировать вертикальные срезы сложного ПО становится адски трудно. Концепции разрастаются, переплетаются и прячутся так глубоко, что их поиск превращается в квест. Хорошая новость в том, что современные методы на базе LLM реально упрощают задачу: они помогают восстанавливать концептуальные конструкции и, как следствие, заметно ускоряют проекты модернизации.
В разработке ПО цель всегда одна и та же — сократить цикл поставки, не превратив продукт в сборник багов. Мы попробовали применить ИИ на разных этапах модернизации и сфокусировались на том, что обычно выпадает из поля зрения [6] коммерческих инструментов — проектирование.
Если использовать набор методов в связке и автоматизировать их, получается быстро прототипировать и сравнивать разные решения, например архитектурные варианты. Понятно, что серьёзный проект модернизации не обойтись без экспертов: они должны проверять и адаптировать результаты, которые предлагает ИИ. Но практика показывает — с ИИ процесс становится менее рискованным и гораздо более предсказуемым.
Главная задача проектного этапа модернизации — убедиться, что выбранный подход рабочий, и можно смело переходить к планированию и разработке, не закапываясь потом в переделках из-за упущенной информации. Обычно здесь уходит куча времени: нужно раскопать исходный код легаси-системы, спроектировать целевую архитектуру и собрать бизнес-требования. Всё это трудоёмко, связано между собой и почти всегда становится «бутылочным горлышком» модернизации.
Мы решили проверить, как LLM могут помочь в восстановлении концепций — и быстро уперлись в три серьёзные проблемы:
Какой контекст вообще нужен и где его взять?
Как организовать этот контекст так, чтобы он был полезен и людям, и самой модели?
Как обеспечить итеративное улучшение документов с требованиями?
Дальше мы расскажем о решениях, которые вместе складываются в единый пайплайн и закрывают все три задачи.
Что такое трассировка?
Чтобы понять, как собрать полезный контекст кода для задач модернизации, мы посмотрели, как инженеры обычно изучают незнакомые кодовые базы с помощью современных IDE и статических анализаторов. Всё достаточно приземлённо: поиск по ключевым словам и регуляркам, навигация по соглашениям об именовании, диаграммы для визуализации структуры, плюс стандартные инструменты редактора — «go-to-definition» и «find-all-references», чтобы быстро прыгать по связям.
Найти точку входа в проект, как правило, несложно — архитекторы и инженеры, работающие с высокоуровневой структурой, справляются с этим быстро. Настоящая боль [7] начинается дальше: нужно разобраться в связях, которые определяют функциональность и архитектуру системы. Именно этот процесс оказался самым затратным по времени и усилиям.
Поэтому мы сосредоточились на разработке метода трассировки кода, который позволяет собрать этот контекст и уже в таком виде скормить его LLM.
Трассировка — это по сути систематический обход AST (абстрактного синтаксического дерева), на выходе которого мы получаем дерево связей, описывающее нужный для модернизации контекст кода. Чтобы запустить процесс, задаём начальную точку и критерий остановки — они зависят от стратегии переписывания.
Простой пример: у нас приложение с формами. Стратегия может быть такой — «заморозить» слой форм и базу данных, а переписать только бизнес-логику между ними. Тогда полезная трассировка стартует с класса формы и идёт до узлов, где есть доступ к БД. Чтобы не утонуть в коде, глубину обхода ограничиваем.
Мы попробовали разные инструменты для парсинга и трассировки. Компиляторные тулчейны дают API под конкретные языки, а такие штуки, как tree-sitter [8] или ANTLR [9], позволяют парсить кучу языков через единый API. В итоге мы остановились на Roslyn: его API возвращает детальные сведения о типах для VB и C#.NET. Наш обходчик AST сохранял всё необходимое — тип текущего символа, его исходный код и связи с другими элементами.
Сбор контекста кода
Мы пробовали разные способы подачи контекста кода в LLM. AST хранит данные о каждом символе — вплоть до конкретного оператора присваивания. В итоге получается слишком много деталей, которые не всегда нужны.
Опираясь на прошлые исследования [10] по обобщению кода с помощью LLM, мы сделали гипотезу: модели будут лучше суммировать, если давать им исходный код, а не сырые AST. Для проверки мы сравнили два варианта:
Markdown-форматированный контекст — где имена методов и классов размечены заголовками уровня H3.
AST в ASCII-стиле — вложенная структура, напоминающая дерево директорий в консоли.
Результат получился интересный: markdown давал более полные и связные суммаризации, в то время как AST приводили к техническим, но излишне детализированным ответам, где терялась общая картина.
Сбор контекста БД
Во время обхода AST мы дополнительно отслеживали зависимости от базы данных. Для этого с помощью ANTLR анализировали код на наличие SQL-запросов. Если встречался SQL, вытаскивали имена таблиц и хранимых процедур и привязывали их к соответствующим узлам AST. После завершения трассировки полученный список сравнивали с дампом схемы базы — так формировался отдельный markdown-файл с контекстом БД, где были только те таблицы и процедуры, к которым реально обращался код. В формате это выглядело похоже на контекст кода: каждая таблица или процедура имела заголовок H3 и соответствующую схему или SQL.
Чем хороша трассировка
Системный подход к трассировке сильно выигрывает у ручного перебора. Архитекторы, с которыми мы работали, могли тратить недели, переходя по ссылкам в коде и пытаясь собрать целостную картину системы. Автоматическая трассировка делает то же самое за минуты, при этом результат получается структурированным, воспроизводимым и гораздо менее зависимым от «человеческой усталости».
Визуализация трассировки
Архитекторы и инженеры часто просили визуализации по результатам трассировки — просто читать дерево кода и список таблиц тяжело, гораздо удобнее видеть картинку. Поэтому мы сделали экспорт трейсов в PlantUML: генерировали диаграммы последовательностей и ER-диаграммы прямо из собранного контекста.
Мы пробовали генерировать PlantUML-код напрямую через LLM, но столкнулись с проблемами. Даже при относительно скромных контекстах (~50k токенов) модели теряли детали и путались в синтаксисе. В итоге получались диаграммы с ошибками или неполными связями.
Интересное наблюдение: сам PlantUML-код оказался ценным контекстом для LLM. Разметка диаграммы классов явно задаёт связи, и модель уже не нужно «догадываться», как именно соотносятся разные фрагменты кода. То же самое с ER-диаграммой — она даёт компактную сводку по слою хранения, от которого зависит приложение, и делает ответы модели заметно более технически точными.
Поэтому мы добавили PlantUML-разметку (классовые и ER-диаграммы) прямо в кодовый и базовый контекст, который передаём в LLM.
Восстановление бизнес-требований
Чтобы решить центральную проблему восстановления концепций, мы просили LLM составить документ с бизнес-требованиями (BRD), используя собранный контекст кода и базы данных. Следуя лучшим практикам промпт-инженеринга [11], мы разработали универсальный промпт, полезный как для технических, так и для нетехнических пользователей. Результаты включали общий обзор, функциональные требования, описание пользовательского интерфейса и список ссылок. Ниже приведено их краткое содержание.
|
Компонент вывода |
Значимость |
|
Общий обзор |
Краткое описание назначения кода и его роли в более крупном приложении, включая короткое описание целей самого приложения. |
|
Функциональные требования |
Описание бизнес-правил, вычислений и обработки данных. |
|
Пользовательский интерфейс |
Описание элементов интерфейса, которые задействованы, и их места в пользовательском пути. |
|
Ссылки |
Перечень классов, таблиц и хранимых процедур, которые участвуют. |
Когда мы начали активно общаться с инженерами, которые регулярно сталкиваются с модернизацией ПО, стало ясно: у каждого проекта — своя специфика и, соответственно, свои ожидания от результатов.
Например, в одних случаях задача — полностью «пересобрать» функциональность старой системы в новой среде. Здесь ключевой артефакт — это набор функциональных тест-кейсов, чтобы убедиться, что ничего не потерялось. В других проектах цель — наоборот, изменить поведение [12] системы или добавить новую функциональность. Там уже важнее BRD (Business Requirements Document), который помогает разложить варианты движения к целевому состоянию, а функциональные тесты уходят на второй план.
Отдельная проблема — размеры контекста. У нас они легко переваливали за 150k токенов, что больше лимита даже у топовых моделей. Чтобы обойти это ограничение, мы сделали стратегию итеративных подсказок:
Сначала считали количество токенов в контексте.
Разбивали его на части примерно по 50k токенов.
Просили модель последовательно суммировать каждую часть.
Для подсчёта использовали библиотеку tiktoken [13], но на практике работает и простое приближение: «1 токен ≈ 4 символа». Критически важно было не порезать код или SQL-запросы внутри — для этого мы использовали markdown-разделители, чтобы модель понимала границы фрагментов.
После того как все части контекста были обработаны, мы собирали их в единый ответ с помощью специального «сводного» промпта. В нём задавались пошаговые рассуждения, чек-лист обязательных разделов и просьба проверить полноту каждого блока. Если у вас есть возможность делать единый запрос со всем контекстом сразу — начинайте именно так. А с выходом моделей с расширенным контекстом (например, Gemini Flash [14] или Llama 4 [15]) и ростом их «умения рассуждать» есть шанс, что в будущем вся эта история с итеративными подсказками просто не понадобится.
В реальных проектах мы заметили, что первоначальный BRD почти всегда рождает уточняющие вопросы. Причём сами ответы на них зачастую оказываются не менее ценными, чем исходный документ — они дополняют или даже меняют его.
Мы пробовали подключать RAG (retrieval-augmented generation), но быстро столкнулись с проблемой: чтобы релевантность поиска была высокой, его приходилось долго и кропотливо настраивать. А запросы у пользователей слишком разные. Инженерам и архитекторам нужны были прямые ссылки на код, бизнес-аналитикам и продакт-менеджерам — смысловое описание. Сделать универсальное решение оказалось почти нереально, поэтому мы сосредоточились на нескольких самых популярных задачах и оптимизировали процесс именно под них.
Задача 1: объединение двух BRD
Когда нужно было слить два BRD (например, добавить новые результаты трассировки в уже готовый документ), мы использовали ту же стратегию итеративных подсказок для работы с большими контекстами. На этапе синтеза модель просто дополняла исходный BRD деталями из новой трассы.
Минус подхода — цена: она растёт линейно с объёмом кода и данных из БД, собранных трассировкой. Плюс накладывается стоимость самого шага синтеза. Но зато такой метод позволяет модели сосредоточиться на каждом фрагменте и максимально сохранить нюансы из обеих трасс, а это для архитекторов важнее экономии токенов.
Задача 2: поиск дополнительного релевантного контекста
Были ситуации, когда в исходную трассировку попадал не весь код, и пользователи хотели найти дополнительные куски. Для этого мы экспериментировали с простым RAG: разбивали весь репозиторий до уровня методов, строили эмбеддинги через CodeBERT [16] и складывали их в векторную базу. Пользователи могли искать фрагменты кода, связанные с нужным процессом или поведением [17], а система возвращала топ-результаты — потенциальные точки входа.
Проблема в том, что результаты приходили без окружения, из-за чего их было трудно оценивать. К тому же общая релевантность поиска оставляла желать лучшего. Мы пришли к выводу: в таком виде это слишком ненадёжно, чтобы строить полноценный автоматический RAG, который сам извлекает и отправляет фрагменты кода в LLM.
Задача 3: Точечные запросы по текущей трассировке
Для точечных запросов к коду мы тестировали два подхода: итеративные запросы ко всему контексту (см. задачу 1) и индексацию во векторной базе (см. задачу 2). Итеративный вариант давал более полные и глубокие ответы, но стоил дороже. Поиск через векторку работал быстрее и дешевле, но терял часть деталей. Мы верим, что по мере появления моделей с действительно длинным контекстом практика «скармливать всё одним промптом» станет куда удобнее и выгоднее.
Сочетание системных методов — вроде статического анализа — с возможностями суммаризации через LLM открывает новые сценарии для модернизации. Автоматизация и верификация результатов анализа дают экспертам уверенность, а генерация документации с помощью моделей снимает огромный пласт рутины.
Бонусом это ещё и расширяет команду: подключать к проектам можно специалистов с разным бэкграундом, потому что вся картина системы становится прозрачнее. Но в итоге всё упирается в одно: пока команда не разберётся в концепциях, на которых держится легаси, никакая модернизация не будет по-настоящему успешной. А вот с ИИ этот барьер преодолеть заметно проще.
Сложно тащить проект на себе, когда команда пассивна. Непонятно, куда двигаться в профессии менеджера проектов. Страшно, что очередной «чёрный лебедь» похоронит все сроки. Если эти боли вам знакомы — приходите на бесплатные уроки, обсудим:
3 сентября в 19:00 — Как разбудить пассивных сотрудников и внедрить коллективную ответственность по стандартам PMP [18]
16 сентября в 19:00 — Кто такой менеджер проектов в 2025: роль, навыки и путь в профессию [19]
25 сентября в 19:00 — Управление рисками: как подготовиться к непредсказуемому и выжить [20]
Освоить эффективные методики управления проектами в IT можно на курсе «Руководитель IT проектов». [21]
Автор: kmoseenk
Источник [22]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/19037
URLs in this post:
[1] “No Silver Bullet”: https://www.cs.unc.edu/techreports/86-020.pdf
[2] Copilot: https://www.microsoft.com/en-us/microsoft-copilot/personal-ai-assistant
[3] aider: https://aider.chat/
[4] опытом: http://www.braintools.ru/article/6952
[5] логично: http://www.braintools.ru/article/7640
[6] поля зрения: http://www.braintools.ru/article/9711
[7] боль: http://www.braintools.ru/article/9901
[8] tree-sitter: https://github.com/tree-sitter/tree-sitter
[9] ANTLR: https://www.antlr.org/
[10] прошлые исследования: https://arxiv.org/abs/2312.00413
[11] лучшим практикам промпт-инженеринга: https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-the-openai-api
[12] поведение: http://www.braintools.ru/article/9372
[13] tiktoken: https://github.com/openai/tiktoken
[14] Gemini Flash: https://deepmind.google/technologies/gemini/flash/
[15] Llama 4: https://www.llama.com/models/llama-4/
[16] CodeBERT: https://github.com/microsoft/CodeBERT
[17] поведением: http://www.braintools.ru/article/5593
[18] Как разбудить пассивных сотрудников и внедрить коллективную ответственность по стандартам PMP: https://otus.pw/z9Ib/
[19] Кто такой менеджер проектов в 2025: роль, навыки и путь в профессию: https://otus.pw/x3OT/
[20] Управление рисками: как подготовиться к непредсказуемому и выжить: https://otus.pw/p6UB/
[21] на курсе «Руководитель IT проектов».: https://otus.pw/MVgH/
[22] Источник: https://habr.com/ru/companies/otus/articles/943266/?utm_source=habrahabr&utm_medium=rss&utm_campaign=943266
Нажмите здесь для печати.