Старший разработчик выявляет возможности для улучшения кода с помощью анализа на основе CPG.
Содержание¶
- Быстрый старт
- Как это работает
- Классификация запросов
- Двухфазная архитектура
- Три режима работы
- Обнаружение мёртвого кода
- 10 паттернов обнаружения
- Фильтрация по намерению
- Примеры обнаружения мёртвого кода
- Дублирование кода
- Обнаружение клонов через AST
- Анализ сложности
- Анализ влияния
- Влияние через граф вызовов
- Центральность по посредничеству
- Метрики технического долга
- Планирование рефакторинга
- Возможности выделения методов
- Приоритизированный список задач
- Использование CLI
- Примеры запросов
- Связанные сценарии
Быстрый старт¶
# Выберите сценарий рефакторинга
/select 05
Как это работает¶
Классификация запросов¶
При получении запроса о рефакторинге система классифицирует его в один из четырёх типов по ключевым словам (поддерживаются запросы на русском и английском):
| Тип запроса | Ключевые слова (RU) | Ключевые слова (EN) | Маршрутизация |
|---|---|---|---|
dead_code |
мёртвый код, неиспользуемый, недостижимый | dead code, unused, unreachable | DeadCodeDetector |
duplicates |
дубликат, клон, копирование | duplicate, clone, copy-paste | ASTCloneDetector |
complexity |
сложность, цикломатическая | complexity, cyclomatic, nesting | TechnicalDebtDetector |
general |
рефакторинг, улучшить, запах кода | refactor, improve, code smell | Полный конвейер |
Классификацию выполняет detect_refactoring_query_type(), анализирующий ключевые слова запроса и направляющий к наиболее подходящему детектору.
Двухфазная архитектура¶
Сценарий рефакторинга использует двухфазный конвейер обработки:
Запрос пользователя
|
v
[Фаза 1] На основе обработчиков (шаблонные ответы, без LLM)
|-- CodeCloneHandler → структурированный отчёт о клонах
|-- DeadCodeHandler → структурированный отчёт о мёртвом коде
|-- CodeSmellHandler → структурированный отчёт о запахах
|
v (если обработчик не может ответить)
[Фаза 2] Полный конвейер с LLM
|-- TechnicalDebtDetector.detect_all_smells()
|-- ImpactAnalyzer.analyze_bulk_impact()
|-- RefactoringPlanner.create_refactoring_plan()
|-- LLM генерирует ответ на естественном языке
Фаза 1 (handler-based) выдаёт мгновенные структурированные ответы на типовые запросы — без вызова LLM. Фаза 2 (LLM fallback) обрабатывает сложные или неоднозначные запросы, требующие синтеза на естественном языке.
Три режима работы¶
| Режим | Описание | Применение |
|---|---|---|
code_smells |
Обнаружение запахов кода, мёртвого кода, анализ сложности (по умолчанию) | Повседневное качество кода |
large_scale |
Массовый рефакторинг с ROI-анализом и приоритизацией | Планирование спринтов |
mass_migration |
Миграция символов/API, автоматическое переименование | Обновление фреймворков |
Режим mass_migration направляет обработку в mass_migration_workflow() — специализированный конвейер для переименования символов по всей кодовой базе. См. Массовый рефакторинг (S13) для операций массового переименования.
Обнаружение мёртвого кода¶
10 паттернов обнаружения¶
DeadCodeDetector выявляет мёртвый код через 10 специализированных паттернов, каждый с оценкой достоверности, отражающей надёжность обнаружения:
| Паттерн | Достоверность | Описание |
|---|---|---|
DEPRECATED_MARKER |
0.95 | Функции с явными маркерами устаревания |
UNREACHABLE_AFTER_RETURN |
0.85 | Код после безусловного return/break/continue |
INVARIANT_DEAD_CODE |
0.80 | Условия, которые всегда истинны или всегда ложны |
DEAD_CODE |
0.70 | Функции без вызывающих в графе вызовов |
EMPTY_STUB |
0.65 | Функции с пустым телом или заглушкой |
UNUSED_VARIABLE |
0.60 | Переменные, объявленные, но не используемые |
DEAD_CALLBACK |
0.55 | Функции обратного вызова, которые нигде не зарегистрированы |
SINGLE_CALLER_FUNCTION |
0.50 | Функции с единственным вызывающим (кандидаты на встраивание) |
ORPHAN_COMPONENT |
0.45 | Компоненты, отключённые от основного графа вызовов |
TEST_ONLY_FUNCTION |
0.40 | Нетестовые функции, вызываемые только из тестового кода |
Находки ранжируются по достоверности — паттерны с высокой достоверностью с большей вероятностью являются истинными срабатываниями и безопаснее для действий.
Фильтрация по намерению¶
Система определяет намерение по ключевым словам запроса и запускает только релевантные паттерны:
"Найти устаревшие функции" → DEPRECATED_MARKER
"Найти неиспользуемый код" → DEAD_CODE + UNUSED_VARIABLE + SINGLE_CALLER_FUNCTION
"Найти недостижимый код" → UNREACHABLE_AFTER_RETURN + INVARIANT_DEAD_CODE
"Найти мёртвый код" → Все паттерны по умолчанию
Английские запросы работают аналогично:
"Find deprecated functions" → DEPRECATED_MARKER only
"Find unused static functions" → DEAD_CODE + SINGLE_CALLER_FUNCTION
"Find unreachable code" → UNREACHABLE_AFTER_RETURN + INVARIANT_DEAD_CODE
Примеры обнаружения мёртвого кода¶
> Найти неиспользуемые статические функции
╭─────────────── Анализ мёртвого кода ────────────────────────╮
│ │
│ Неиспользуемые статические функции (вызовы не найдены): │
│ │
│ src/backend/utils/misc/help.c: │
│ - old_format_help() Строки: 45-89 │
│ - legacy_usage_message() Строки: 123-156 │
│ │
│ src/backend/catalog/pg_type.c: │
│ - deprecated_type_check() Строки: 789-834 │
│ │
│ Достоверность: ВЫСОКАЯ (статические функции, нет внешних ссылок) │
│ Рекомендация: Можно безопасно удалить после проверки │
│ │
╰──────────────────────────────────────────────────────────────╯
Дублирование кода¶
Обнаружение клонов через AST¶
ASTCloneDetector (src/analysis/clone_detector.py) выявляет дублированный код, сравнивая абстрактные синтаксические деревья, а не сырой текст. Это позволяет находить семантические клоны даже при различии имён переменных.
CodeCloneHandler (Фаза 1) выдаёт структурированные отчёты о клонах без LLM:
> Найти повторяющиеся фрагменты кода
╭─────────────── Обнаружение клонов ──────────────────────────╮
│ │
│ Кластеры дублирующегося кода: │
│ │
│ Кластер №1 (сходство 95%, 34 строки): │
│ - src/backend/access/heap/heapam.c:1234-1267 │
│ - src/backend/access/heap/heapam.c:1890-1923 │
│ Рекомендация: Выделить общую логику во вспомогательную │
│ функцию │
│ │
│ Кластер №2 (сходство 88%, 22 строки): │
│ - src/backend/executor/nodeSeqscan.c:45-66 │
│ - src/backend/executor/nodeIndexscan.c:78-99 │
│ - src/backend/executor/nodeBitmapscan.c:89-110 │
│ Рекомендация: Создать общую подпрограмму инициализации │
│ │
│ Всего клонов: 15 кластеров │
│ Дублируемых строк: ~450 │
│ │
╰──────────────────────────────────────────────────────────────╯
Анализ сложности¶
TechnicalDebtDetector выявляет функции с чрезмерной цикломатической и когнитивной сложностью:
> Найти функции с цикломатической сложностью выше 20
╭─────────────── Анализ сложности ────────────────────────────╮
│ │
│ Функции, превышающие порог (сложность > 20): │
│ │
│ exec_simple_query() сложность: 47 │
│ Расположение: src/backend/tcop/postgres.c:890 │
│ Рекомендация: Выделить аутентификацию, разбор │
│ и выполнение в отдельные функции │
│ │
│ ExecInitNode() сложность: 32 │
│ Расположение: src/backend/executor/execProcnode.c:156 │
│ Рекомендация: Использовать таблицу диспетчеризации │
│ вместо оператора switch │
│ │
│ Всего: 23 функции превышают порог │
│ │
╰──────────────────────────────────────────────────────────────╯
Анализ влияния¶
Влияние через граф вызовов¶
ImpactAnalyzer использует CallGraphAnalyzer для определения радиуса поражения любого рефакторинга — количество вызывающих, транзитивных зависимых и затронутых подсистем:
> Какие компоненты затронет рефакторинг heap_insert?
╭─────────────── Анализ влияния ──────────────────────────────╮
│ │
│ Целевая функция: heap_insert() │
│ Прямые вызывающие: 23 │
│ Транзитивные вызывающие: 156 │
│ │
│ Затрагиваемые подсистемы: │
│ - Исполнитель (12 вызовов) │
│ - Команда COPY (3 вызова) │
│ - Выполнение триггеров (4 вызова) │
│ - Обёртка внешних данных (4 вызова) │
│ │
│ Радиус поражения: ВЫСОКИЙ (156 транзитивных зависимых) │
│ Безопасных рефакторингов: 3 (функции с ≤5 вызывающими) │
│ │
╰──────────────────────────────────────────────────────────────╯
Центральность по посредничеству¶
DependencyAnalyzer вычисляет центральность по посредничеству (betweenness centrality) для каждой функции в графе вызовов — выявляя архитектурные узкие места, через которые проходит множество путей вызовов. Функции с высокой центральностью — рискованные цели для рефакторинга, так как изменения распространяются широко:
Оценка рисков по центральности:
- ExecProcNode() процентиль: 98% риск: КРИТИЧЕСКИЙ
- heap_insert() процентиль: 92% риск: ВЫСОКИЙ
- ExecScan() процентиль: 87% риск: ВЫСОКИЙ
- pg_parse_query() процентиль: 45% риск: НИЗКИЙ
Высокий процентиль центральности = через функцию проходит много кратчайших путей. Её рефакторинг затрагивает много подсистем.
Метрики технического долга¶
TechnicalDebtDetector.calculate_debt_metrics() вычисляет количественные метрики долга:
| Метрика | Описание |
|---|---|
total_effort_hours |
Оценка часов на исправление всех обнаруженных запахов |
debt_ratio |
Технический долг как доля от общего объёма кодовой базы |
estimated_value |
Денежная оценка стоимости устранения долга |
by_severity |
Разбивка: критический / высокий / средний / низкий |
by_category |
Разбивка: dead_code / complexity / duplication / … |
Эти метрики включаются в metadata каждого ответа по рефакторингу, позволяя отслеживать тренды по спринтам.
Планирование рефакторинга¶
Возможности выделения методов¶
> Найти возможности выделения методов в exec_simple_query
╭─────────────── Анализ выделения методов ────────────────────╮
│ │
│ Функция: exec_simple_query() │
│ Текущее количество строк: 234 │
│ │
│ Предлагаемые выделения: │
│ │
│ 1. Строки 45-78: Обработка аутентификации │
│ Предлагаемое имя: check_query_authorization() │
│ Параметры: query_string, session_state │
│ │
│ 2. Строки 89-134: Разбор запроса │
│ Предлагаемое имя: parse_and_analyze_query() │
│ Параметры: query_string │
│ Возвращает: ParsedQuery │
│ │
│ 3. Строки 156-198: Генерация плана │
│ Предлагаемое имя: generate_query_plan() │
│ Параметры: analyzed_query │
│ Возвращает: PlannedQuery │
│ │
│ Эффект: Снижение сложности с 47 до ~12 на функцию │
│ │
╰──────────────────────────────────────────────────────────────╯
Приоритизированный список задач¶
RefactoringPlanner генерирует приоритизированный список задач из всех находок:
Задачи рефакторинга (по приоритету):
1. [ВЫСОКИЙ] Удалить deprecated_type_check() — 0 вызывающих, безопасно удалить
2. [ВЫСОКИЙ] Выделить 3 метода из exec_simple_query() — сложность 47→12
3. [СРЕДНИЙ] Объединить дублирующие подпрограммы инициализации сканирования — 3 файла, 66 строк экономии
4. [НИЗКИЙ] Встроить вспомогательную handle_auth_step() — 1 вызывающий
Каждая задача включает оценку трудозатрат, уровень риска и ожидаемое улучшение.
Использование CLI¶
# Анализ рефакторинга через запрос
python -m src.cli query "Найти неиспользуемые функции в модуле executor"
# Глубокий анализ через промпт
python -m src.cli exec --prompt "Предложи возможности рефакторинга для функций с высокой сложностью"
# Обнаружение мёртвого кода
python -m src.cli query "Найти устаревший и недостижимый код"
# Обнаружение клонов
python -m src.cli query "Найти дублирующиеся фрагменты кода"
Примеры запросов¶
Мёртвый код: - «Найти неиспользуемые статические функции» - «Найти устаревшие функции» - «Найти недостижимый код после return» - «Найти пустые заглушки» - «Найти компоненты-сироты»
Дублирование: - «Показать повторяющиеся фрагменты кода» - «Найти скопированный код в executor»
Сложность: - «Найти функции с высокой цикломатической сложностью» - «Найти длинные функции, которые следует разбить» - «Найти классы-монолиты»
Анализ влияния: - «Какие компоненты затронет изменение heap_insert?» - «Предложи рефакторинг для exec_simple_query» - «Показать радиус поражения изменений ExecProcNode»
Связанные сценарии¶
- Производительность (S06) — Рефакторинг для повышения производительности
- Технический долг (S12) — Оценка и отслеживание долга
- Массовый рефакторинг (S13) — Масштабные миграции символов и операции массового переименования. S05 фокусируется на анализе и планировании (режим
code_smells); S13 выполняет автоматизированные массовые изменения (режимmass_migration) - Проверка кода (S09) — Проверка изменений после рефакторинга