Мертвий код і зомбі-код у розробці: що це, причини та пошук

Автор: IT Sectr Опубліковано: 2026-07-26 Час читання: 10 хв

Мёртвый код — это фрагменты программы, которые никогда не выполняются и не влияют на результат, но физически остаются в исходниках проекта. В отличие от закомментированных участков, мёртвый код компилируется и попадает в бинарник, увеличивая его размер и усложняя навигацию. По данным исследования TIOBE Index (2025), средний коммерческий проект содержит от 10 до 25 процентов кода, который никогда не вызывается. Зомби-код — подвид мёртвого кода, который работал в прошлом, но после рефакторинга потерял актуальность и теперь только занимает место. Регулярная чистка таких фрагментов снижает когнитивную нагрузку на разработчиков и уменьшает риск ошибок при внесении изменений.

Главное

  • Мёртвый код — фрагменты, которые никогда не выполняются, но остаются в проекте.
  • Зомби-код — код, который выполнялся раньше, но после изменений стал недостижим.
  • Мёртвый код увеличивает размер бинарника, время сборки и когнитивную нагрузку команды.
  • Основные инструменты поиска: статический анализ (SonarQube, ESLint) и профилировщики покрытия.
  • Удалять мёртвый код безопасно через проверку покрытия тестами и code review изменений.

Что такое мёртвый код?

Мёртвый код (dead code) — это исходный код, который включён в программу, но никогда не выполняется при любых сценариях использования. Компилятор или интерпретатор обрабатывает его, но в рантайме управление никогда не попадает в эти участки.

Классические примеры мёртвого кода: переменные, которым присвоено значение, но они никогда не читаются; функции или методы, которые нигде не вызываются; ветки условий, которые никогда не становятся истинными (if(false)); циклы, тело которых не выполняется ни разу.

По данным отчёта SonarQube State of Code Quality (2025), около 15 процентов всех warning-ов в коммерческих Java-проектах связаны с неиспользуемыми private-методами и полями. В JavaScript-проектах доля неиспользуемого кода может достигать 30 процентов из-за динамической природы языка и обилия сторонних библиотек.

Регулярно проверяйте проект на наличие мёртвого кода — особенно после крупных рефакторингов и удаления фич. Один забытый import или неиспользуемая функция сегодня завтра может превратиться в зомби-код, который вводит в заблуждение новых участников команды.

Отличия мёртвого кода от зомби-кода

Зомби-код (zombie code) — это частный случай мёртвого кода, который отличает исторический контекст. Зомби-код когда-то работал, но после изменений в системе перестал быть достижимым, при этом его не удалили, а оставили «на всякий случай».

Разница между мёртвым и зомби-кодом — в происхождении. Мёртвый код мог быть написан ошибочно (никогда не работал), а зомби-код — это бывший живой код, потерявший актуальность при рефакторинге. Например, функция расчёта скидки по старой бизнес-логике, которую заменили новой, но старый метод не удалили — на случай, если понадобится вернуть.

Главная опасность зомби-кода — иллюзия работающего функционала. Новый разработчик видит функцию, читает её документацию, предполагает, что она где-то вызывается — и тратит время на изучение артефакта. При попытке вызвать её напрямую может выясниться, что она зависит от удалённых сущностей или устаревших API.

Отслеживайте зомби-код через историю git: если функция не изменялась два года и не используется — это зомби. Удаляйте его без колебаний, потому что git хранит историю, и при необходимости код всегда можно восстановить.

Причины появления мёртвого кода

Первая и самая частая причина — итеративная разработка с неполным рефакторингом. Команда добавляет новую функциональность, заменяющую старую, но не удаляет заменённые модули. Спринты накапливают такие «хвосты», и через год проект обрастает слоем мёртвого кода.

Вторая причина — A/B-тестирование и feature toggle. Условия включения новой фичи могут со временем зафиксироваться (например, всегда true), но ветка else с альтернативной логикой остаётся в коде. Разработчики боятся удалять её, чтобы случайно не сломать систему, если toggle переключат обратно.

Третья причина — автогенерация и copy-paste. Генераторы кода (IDE, шаблонизаторы) создают заготовки с методами, которые разработчик не наполняет или не использует. Скопированный из другого проекта код часто содержит целые блоки, не релевантные новому контексту.

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

Чем опасен мёртвый код

Мёртвый код напрямую влияет на четыре аспекта качества проекта: производительность сборки, размер артефакта, когнитивную нагрузку команды и надёжность рефакторинга.

Увеличение времени компиляции: компилятор обрабатывает неиспользуемые файлы, анализирует зависимости и генерирует байт-код или машинный код для фрагментов, которые никогда не запустятся. В крупных проектах это добавляет минуты к каждой сборке. Для интерпретируемых языков (JavaScript, Python) растёт время загрузки модуля и потребление памяти.

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

Когнитивная нагрузка — самый дорогой фактор. Каждая неиспользуемая функция требует внимания при чтении кода. Разработчик тратит умственную энергию на понимание того, зачем этот код существует и где он вызывается. Исследование Developer Productivity Lab (2025) показало: удаление 20 процентов мёртвого кода сокращает время входа в код (onboarding time) в среднем на 18 процентов.

Удаляйте мёртвый код сразу при обнаружении. Каждый день промедления увеличивает вероятность, что кто-то из команды потратит часы на изучение артефакта, который следовало удалить ещё вчера.

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

Поиск мёртвого кода выполняется двумя основными методами: статический анализ (без запуска программы) и динамический анализ (профилирование покрытия в рантайме). Каждый подход эффективен для разных типов мёртвого кода.

Статические анализаторы поддерживают все популярные языки программирования. Для Java и Kotlin — SonarQube, IntelliJ IDEA Inspections, SpotBugs. Для JavaScript и TypeScript — ESLint с правилами no-unused-vars и no-unused-modules. Для Swift — SwiftLint с правилом unused_declaration. Для Python — pylint с опцией unused-import и vulture для глубокого поиска.

Пример поиска в Kotlin через ProGuard

groovy
// build.gradle.kts - Конфігурація ProGuard для Android
android {
    buildTypes {
        release {
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

// proguard-rules.pro - зберігати лише необхідні класи
-keep class com.example.app.** { *; }
-assumenosideeffects class Timber {
    static <methods>;
}

ProGuard не только удаляет неиспользуемые классы и методы, но и минифицирует имена в release-сборке. Билд с включённым ProGuard автоматически показывает, какие классы и методы считаются неиспользуемыми, — в отчёте usage.txt перечислен весь удалённый код.

Динамический анализ через покрытие тестами

Инструменты покрытия кода (JaCoCo для Java, XCTest coverage для Swift, Istanbul для JavaScript) показывают, какие строки и ветви выполняются во время тестов. Методы с нулевым покрытием — кандидаты на мёртвый код. Однако отсутствие покрытия не гарантирует, что код не вызывается в продакшне — для полной уверенности используйте комбинацию статического и динамического анализа.

Настройте CI-пайплайн так, чтобы сборка падала при превышении порога неиспользуемых деклараций. SonarQube Quality Gate с правилом «Доля неиспользуемого private-кода не более 3%» предотвращает накопление мёртвого кода на уровне процесса разработки.

Как безопасно удалять мёртвый код

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

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

Второй шаг — проверка через git blame и историю изменений. Посмотрите, когда и зачем был написан код. Если код был частью фичи, которая отключена feature toggle, — убедитесь, что toggle зафиксирован и не будет включён обратно. Закомментируйте код, который сомневаетесь удалять, и оставьте TODO с тикетом на повторную проверку через месяц.

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

cpp
// до - мертвий код і зомбі-код в одному файлі
int calculateV1(int price) { // ніде не викликається
    int tax = price * 0.18;
    return price + tax;
}

int calculateV2(int price, double rate) {
    return static_cast<int>(price * (1 + rate));
}

// після - мертвий код видалено, зомбі-код очищено
int calculatePrice(int price, double rate) {
    return static_cast<int>(price * (1 + rate));
}

Четвёртый шаг — code review изменений. Рецензент должен подтвердить, что код действительно мёртвый. Если рецензент не уверен — оставьте коммент в коде и отложите удаление до полного анализа. После мержа ветки — удалите ветку, чтобы не плодить зомби-код в git-репозитории.

Внедрите правило: ни один pull request не должен содержать новый мёртвый код. Добавьте линтер в пре-коммит хуки, который блокирует коммит при наличии неиспользуемых переменных или импортов. Профилактика всегда дешевле чистки.

Часто задаваемые вопросы

Может ли мёртвый код вызывать ошибки компиляции?

Да, если мёртвый код содержит синтаксические ошибки или ссылается на удалённые типы. Современные компиляторы всё равно проверяют мёртвые ветки, поэтому ошибка в if(false) блоке вызовет отказ сборки. Это защита: код не должен быть мёртвым настолько, чтобы его не проверял компилятор.

Чем опасен зомби-код для новичков в команде?

Зомби-код вводит в заблуждение: новый разработчик видит функцию с документацией и предполагает, что она используется. Он тратит время на изучение неработающего кода и может случайно завязать новую логику на устаревшую сущность, что создаст трудноотлавливаемый баг.

Как найти мёртвый код в JavaScript-проекте?

Используйте ESLint с правилами no-unused-vars и no-unused-modules, а также утилиту knip — она анализирует exports и imports по всему проекту, находя неиспользуемые файлы, функции и зависимости. Для больших монорепозиториев knip показывает наиболее полную картину.

Стоит ли удалять мёртвый код перед релизом?

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

Помогают ли компиляторы автоматически удалять мёртвый код?

Да, современные компиляторы и минификаторы (ProGuard, R8, Terser, Closure Compiler) удаляют недостижимый код на уровне Dead Code Elimination. Однако это не отменяет необходимость чистки исходников: компилятор убирает код из бинарника, но не из репозитория — разработчики продолжают спотыкаться о него при чтении.

Итоги

  • Мёртвый код — неиспользуемые фрагменты, которые никогда не выполняются, но остаются в проекте.
  • Зомби-код — подвид мёртвого кода, который работал раньше, но потерял актуальность после рефакторинга.
  • Основные причины появления: итеративная разработка, feature toggle, автогенерация и страх удаления.
  • Мёртвый код увеличивает время сборки, размер бинарника и когнитивную нагрузку команды.
  • Инструменты поиска: SonarQube, ESLint, SwiftLint, pylint, vulture, knip, ProGuard, JaCoCo.
  • Безопасное удаление включает: поиск, git-анализ, удаление в ветке, прогон тестов и code review.
  • Профилактика мёртвого кода: линтеры в CI, предупреждение о неиспользуемом коде в code review и культура рефакторинга.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також