Современный инструмент поиска мёртвого кода

Мне всегда было неудобно разбирать код, который вроде бы уже никому не нужен, но удалить его всё равно страшно. Метод лежит в репозитории годами. Поиск показывает пару тестов. Рядом — провайдер зависимостей, декоратор или регистрация роутера. И непонятно: это забытый кусок старой функции или часть работающего приложения?

Я сделал Deadtrace, потому что хотел получать объяснение: откуда код может быть вызван, что именно учтено и почему конкретный участок заслуживает внимания. Для меня хороший анализатор должен помогать принять решение, а не добавлять ещё один список предупреждений.

В этом гайде покажу, как найти кандидата на удаление в Python, сохранить результат и проверить его перед изменениями. На выходе будет небольшой, понятный материал для ревью.

Почему я считаю Deadtrace полезным

В приложении с FastAPI и Dishka вызовы не всегда выглядят как some_function(). Маршрут регистрируется отдельно, сервис приходит через DI, cleanup выполняется при завершении контекста. У тестов тоже свои способы подключать код. Я заложил в Deadtrace моделирование таких связей. Поддерживаемые механизмы и ограничения перечислены в README проекта.

Особенно мне нравится возможность вернуться к сохранённому объяснению. Когда обсуждаешь изменение с коллегой, хочется показать конкретную находку, а не пересказывать, что утилита напечатала вчера в терминале.

1. Установите инструмент отдельно от приложения

Я начинаю с установки через uv. На дату проверки гайда публичная alpha-версия — 0.1.0a6; её фиксирую, чтобы команды были воспроизводимыми. Способ установки сверял с документацией Deadtrace.

uv tool install --python 3.12 "deadtrace==0.1.0a6"
deadtrace --version

Затем перейдите в корень своего Python-проекта. Сам сканер статический и не запускает исследуемое приложение.

2. Сначала посмотрите общую картину

deadtrace scan .
deadtrace doctor .

Я сначала читаю ограничения. Важно понимать, какие точки входа анализатор увидел и где модель остаётся неполной. Это экономит время: не приходится спорить с выводом, который опирается на неверное представление о запуске приложения.

Например, если код загружает внешняя система, я явно описываю эту связь через keep-контракт по README. Причину сохранения кода стоит записать так, чтобы другой человек смог её проверить.

3. Сохраните отчёт и разберите одну находку

deadtrace scan . --format json --output deadtrace-report.json --require-complete
deadtrace explain YOUR-FINGERPRINT --report deadtrace-report.json

Вместо YOUR-FINGERPRINT вставьте идентификатор из своего отчёта. Я предпочитаю начинать с одной небольшой находки: прочитать объяснение, открыть код и сопоставить его с реальным способом запуска.

Отдельно смотрю на код, до которого добираются только тесты. Тест может продолжать проверять старое поведение даже после того, как из приложения исчез последний потребитель. Это хороший повод разобраться, зачем мы всё ещё поддерживаем такой участок.

Если проверка полноты завершилась ошибкой, сначала разбираю причину. Полученный список не превращается от этого в разрешение на удаление.

4. Сделайте маленький рефакторинг

Мой рабочий маршрут простой:

  1. Объяснить, почему кандидат больше не нужен.
  2. Проверить внешние потребители и динамические подключения.
  3. Удалить один понятный участок в отдельной ветке.
  4. Запустить тесты приложения и проверить затронутый сценарий.
  5. Оставить в описании изменения ссылку на отчёт и результат проверок.

Так ревью становится предметным. Видно и основание для изменения, и способ убедиться, что приложение продолжает работать.

5. Зафиксируйте разобранный долг

Когда первая порция находок рассмотрена, можно создать baseline:

deadtrace baseline create deadtrace-report.json --output deadtrace-baseline.json --reason "Reviewed before adoption"
deadtrace scan . --format json --baseline deadtrace-baseline.json --fail-on-new

Я использую baseline как запись принятого решения. Он фиксирует уже рассмотренные находки; новые требуют отдельного ревью. Такой подход помогает постепенно разгребать репозиторий, не превращая первую уборку в бесконечную задачу.

Что попробовать прямо сейчас

Возьмите небольшой проект, сохраните отчёт и выберите одну находку. Запишите три предложения: что найдено, почему это могло остаться в коде и как вы проверите изменение. Удалять её для прохождения гайда необязательно.

Я горжусь тем, что в Deadtrace можно обсуждать основания вывода. Это именно тот инструмент, которого мне не хватало при работе с живыми Python-приложениями. Попробовать его и предложить улучшение можно в репозитории Deadtrace.

Дальше можно проверить пользовательский сценарий с Testence. Ниже — три вопроса; после входа портал сохранит ответы и прогресс.

Проверка знаний

Читайте свободно. Войдите, чтобы отвечать и сохранять прогресс.

Находка Deadtrace означает, что код можно сразу удалить?

Зачем сохранять JSON-отчёт?

Что фиксирует baseline?