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

Почему старые функции задерживаются
Команды обычно не держат устаревшие функции потому, что они им нравятся. Они оставляют их, потому что удалять страшно, а не трогать кажется безопасным. Эта интуиция дорого обходится.
Функция может уже не быть важной для пользователей, но всё равно каждую неделю добавлять работы. Тесты падают, когда рядом меняется код. В ответах поддержки всплывает поведение, которым никто уже не должен пользоваться. В биллинге, правах доступа и онбординге появляются странные исключения, которые никто не хочет трогать. Эту работу легко не заметить, потому что она разбросана повсюду. Один переключатель лежит в админке. Одна ветка остаётся в API. Одна миграция всё ещё защищает настройку двухлетней давности.
Feature flags делают ситуацию хуже. Временный переключатель превращается в постоянную ветку. Потом никто не хочет его убирать, потому что никто не уверен, что от него ещё зависит.
AI-ассистенты для кода добавляют ещё одну проблему. Когда команда просит модель собрать новый сценарий, модель читает текущую кодовую базу и копирует то, что находит. Если в репозитории всё ещё есть старые флаги, мёртвые ветки и устаревшие правила, новый код часто повторяет их. Старые пути расползаются в новой работе, и одна забытая функция потом превращается ещё в три задачи на очистку.
Есть и бизнес-цена. Презентации для продаж, сценарии демо и ответы поддержки часто продолжают обещать старую возможность задолго после того, как команда перестала верить в эту функцию. Клиенты слышат «да, у нас это есть» и ожидают помощи с тем путём, который продукт уже не хочет поддерживать. Такой разрыв приводит к трению, возвратам и неловким звонкам.
Считайте удаление функции обычной продуктовой работой. Это не провал. Функция либо выполнила свою задачу, либо нет. В любом случае команда должна решить, когда она заканчивается, кто её убирает и что значит «полностью удалена». Без этого рутина превращается в археологию.
Сначала задайте правила удаления
AI делает дешёвым добавление ещё одного экрана, сценария или вспомогательной подсказки. Эта скорость полезна, но она же заставляет команды тащить дальше вещи, которые им уже не нужны. Лучшее время планировать удаление — ещё до первого релиза.
Начните с одного владельца. Один человек должен отвечать за решение оставить, доработать или убрать функцию. Если это решение принадлежит всем, значит, оно не принадлежит никому. В небольшой компании владельцем может быть product lead. В стартапе это часто основатель или CTO.
Затем запишите обещание для пользователя одной простой фразой. «Этот экспорт помогает финансовым пользователям скачивать ежемесячные счета меньше чем за две минуты» — понятно. «Улучшить опыт отчётности» — нет. Размытые обещания трудно измерять и почти невозможно выводить из продукта.
До запуска задайте несколько простых правил:
- Назначьте дату ревью, например через 30, 60 или 90 дней после релиза.
- Определите, что именно завершает жизнь функции: низкое использование, высокая стоимость поддержки или лучшая замена.
- Решите, как долго флаг функции может жить после выката или отключения.
- Поставьте ограничения для связанных данных, документации и оставшегося кода.
Эти границы особенно важны, когда команда каждый день использует генерацию кода. Люди часто оставляют старые ветки, потому что они «ещё могут пригодиться». В большинстве случаев — нет. Старые флаги путают тесты. Старые правила по данным усложняют миграции. Старые документы учат поддержку и продажи повторять обещания, которые продукт уже не выполняет.
Храните правило удаления там, где его действительно увидят. Заметка, спрятанная в личном документе, не помогает. Поместите её в спецификацию функции, задачу на релиз или чеклист запуска. Одной общей записи достаточно, если команда правда ей пользуется.
Поймите, когда функцию пора завершить
Функция не должна жить только потому, что кто-то выпустил её шесть месяцев назад. В продуктах, построенных с AI-инструментами, старые пути задерживаются дольше, потому что добавить ещё один экран, ещё одну настройку или ещё одно исключение слишком легко. Сложнее всего — решить, когда перестать тащить это дальше.
Смотрите сразу на три сигнала: реальное использование, нагрузку на поддержку и время на сопровождение. Функция с низким трафиком всё ещё может заслуживать жизни, если несколько платящих клиентов зависят от неё каждую неделю. Но если её открывает лишь малая доля пользователей, поддержка снова и снова отвечает на одни и те же вопросы, а инженеры постоянно чинят вокруг неё хрупкий код, цена уже выше, чем кажется.
Новые релизы часто создают тихие дубли. Команда запускает более чистый сценарий, но оставляет старый, потому что не хочет расстраивать несколько пользователей. Через несколько месяцев обоим сценариям нужны исправления, документация, тесты и подсказки. Эту двойную цену легко игнорировать, когда AI помогает быстро выкатывать изменения.
Прежде чем удалять функцию, спросите людей, которые видят поведение клиентов вблизи:
- Поддержка подскажет, кто всё ещё зависит от неё и создаёт ли она повторные тикеты.
- Продажи или customer success скажут, упоминается ли она в активных сделках.
- Финансы или операционная команда подскажут, зависят ли от неё биллинг, экспорт или условия контракта.
Если счёт, отчёт или контракт всё ещё зависят от функции, сначала исправьте эту зависимость. Иначе вы не удаляете функцию. Вы ломаете обещание.
Финальное решение должен принять один человек. В небольшой SaaS-команде это часто основатель, product lead или fractional CTO. Мнение группы полезно. Общая ответственность обычно только затягивает процесс.
Назначьте дату решения, запишите причину и выберите понятный путь. Оставить, потому что ещё существует конкретная потребность клиента, или убрать до того, как мёртвые пути ещё глубже расползутся по кодовой базе.
Удаляйте функцию по порядку
Частичное удаление обычно создаёт больше проблем, чем аккуратное отключение. Старые подсказки продолжают срабатывать, скрытые задачи всё ещё запускаются, а поддержка отвечает на вопросы о том, что команда собиралась убрать ещё в прошлом месяце.
Сначала заморозьте старый путь. Не выкатывайте улучшения, мелкие доработки или новые сгенерированные помощники для него. Единственная работа, которая там уместна, — это отключение и временный фикс, если он нужен, чтобы текущие пользователи были в безопасности до даты отключения.
Сообщите пользователям, что изменится, когда это произойдёт и что им нужно сделать заранее. Говорите прямо. Если им нужно выгрузить данные, перейти на заменяющий сценарий или обновить интеграцию, скажите об этом заранее и повторите это внутри продукта, а не только в письме.
Аккуратное удаление обычно идёт в таком порядке:
- Сначала уберите точки входа. Спрячьте пункты меню, кнопки, упоминания в онбординге и публичную документацию, чтобы новые пользователи перестали находить функцию.
- Затем отключите логику за этими точками входа. Выключите маршруты, флаги, вебхуки и API-действия, которые ещё принимают трафик.
- Удалите скрытый слой. Уберите фоновые задачи, подсказки, инструкции для агентов, правила маршрутизации, запланированные задачи и алерты, связанные с функцией.
- Удалите код и тесты одним проходом. Фронтенд-части, backend-обработчики, схемы, моки и тестовые фикстуры должны уйти вместе.
- Приведите в порядок всё вокруг кода. Обновите документацию, события аналитики, дашборды, макросы поддержки, внутренние runbook и заготовленные ответы.
Порядок важен. Если вы сначала удалите backend-код, но оставите интерфейс, пользователи упрются в тупик. Если спрячете интерфейс, но оставите автоматизацию, система продолжит тратить деньги и засорять логи шумом.
Командам, которые полагаются на AI-инструменты, нужен ещё один навык: ищите не только по имени файла, но и по поведению. Функция может жить внутри шаблонов подсказок, скриптов оценки, правил защиты и сгенерированных тестов, которые не используют то же название, что и экран продукта.
Если всё сделано хорошо, удаление функции кажется почти скучным. В этом и есть цель. Никаких призраков в интерфейсе, никаких неожиданных задач в 2 ночи и никаких старых обещаний, висящих в коде.
Очистите то, что ваши AI-инструменты всё ещё помнят
Чаще всего грязь — не сама функция. Проблема в том, что вокруг неё остаётся материал, который ваши инструменты снова и снова тащат в кодовую базу.
Команды часто удаляют видимые экраны и API-маршруты, а потом останавливаются. Через неделю ассистент снова пишет тот же валидатор, восстанавливает старую подсказку или добавляет поле, которое принадлежало уже закрытому сценарию. Это происходит потому, что функция всё ещё живёт в инструкциях, шаблонах, комментариях и скопированных фрагментах.
Начните с широкого поиска. Ищите название функции, старые названия полей, текст подсказок и связанные с ней бизнес-правила. Проверьте миграции, тестовые фикстуры, события аналитики, админские подписи и исходные данные. AI-инструменты копируют из мест, которые люди забывают.
Короткий проход закрывает большую часть хвостов:
- Удалите файлы подсказок, заметки для агентов и внутренние документы, где всё ещё упоминается старый сценарий.
- Уберите комментарии, которые подсказывают будущим инструментам сохранять или расширять это поведение.
- Проверьте генераторы, скрипты подготовки и подсказки для задач на наличие удалённых файлов или полей.
- Обновите стартовые шаблоны, чтобы новые страницы, тесты и схемы шли по актуальному пути.
- После следующего релиза быстро проверьте, что вернулось обратно.
Комментарии значат больше, чем многие думают. Если в комментарии написано «пользователи могут снова открыть архивные проекты» после того, как вы убрали эту опцию, ассистент может принять эту строку за требование и восстановить часть сценария. То же самое относится к старым описаниям задач, вставленным в подсказки.
Шаблоны создают ту же проблему. Если в стартовой странице всё ещё есть скрытое устаревшее поле, каждая новая функция может унести этот багаж дальше. Исправьте шаблон один раз — и утечка сразу замедлится.
Следующий аудит не обязан быть полным ревью. Проверьте один недавний merge, один сгенерированный экран и одну подсказку, использованную после удаления. Если вы всё ещё видите названия, правила или файлы от старой функции, очистите их там и добавьте это место в чеклист удаления.
Пример для небольшого SaaS
Небольшой SaaS-стартап предлагал ручную выгрузку отчётов. Клиенты открывали дашборд, выбирали диапазон дат и нажимали «Download CSV». Позже команда добавила плановые отчёты по email, потому что большинству людей всё равно нужен был один и тот же отчёт каждую неделю.
Это помогло, но и создало знакомый беспорядок. Команда оставила старый сценарий загрузки «на всякий случай», а их кодовый ассистент продолжал генерировать вокруг него новые проверки, кнопки и запасные пути. Сложность была не в том, чтобы построить замену. Сложность была в том, чтобы решить, когда закончится старое обещание.
Команда записала это решение ещё до релиза новой версии. Они не сказали: «Мы, возможно, удалим ручную выгрузку позже». Они установили правило: ручные выгрузки закончатся 30 июня. Эту дату поместили в заметку о продукте, в ответы поддержки и во внутренний тикет на очистку.
Запуск был простым:
- 1 июня они показали уведомление внутри экрана отчёта.
- Уведомление сообщало, что плановые отчёты по email заменят ручные выгрузки 30 июня.
- Поддержка отправила то же сообщение аккаунтам, которые пользовались выгрузкой каждую неделю.
- 1 июля команда убрала кнопку, endpoint, тесты и подсказки, где упоминался старый сценарий.
У одного клиента всё ещё требовалось больше времени. Финансовый менеджер каждую пятницу переносил CSV-файлы в старую таблицу, и на изменение процесса ушло ещё две недели. Команда не оставила старую функцию для всех. Они оформили временную выгрузку через поддержку с жёсткой датой окончания.
Это важно. Короткое исключение управляемо. Исключение без конца превращается в постоянный мусор.
После даты отключения команда удалила не только видимую кнопку. Они убрали задачу на скачивание, старый help text, события аналитики, макросы поддержки и подсказки для программирования, где всё ещё упоминалась CSV-выгрузка. Как только эти хвосты исчезли, новый код перестал воскрешать мёртвые пути.
Результат был простой, но полезный: меньше вопросов в поддержку, меньше крайних случаев в тестировании и меньше кода, который нужно сопровождать при каждом изменении продукта.
Ошибки, которые удерживают мёртвые пути
Функция редко умирает в момент, когда исчезает кнопка. Команды убирают интерфейс, а потом оставляют API-маршрут, фоновые задачи, столбцы базы данных, алерты и правила биллинга. Пользователи уже не видят функцию, но код всё ещё запускается, ломается и путает следующего человека, который полезет в эту область.
Feature flags создают тот же бардак. Флаг кажется временным, поэтому никто не считает его долгом. Через шесть месяцев половина команды уже забыла, какая сторона должна победить, тесты покрывают оба пути, а AI-инструменты для кода продолжают сохранять обе ветки, потому что код всё ещё говорит, что они важны.
Ситуация ухудшается, когда подсказки, внутренние документы и старые тикеты всё ещё описывают закрытую функцию как активную. Модель видит старое требование, находит похожий паттерн в репозитории и добавляет мёртвый путь обратно во время рефакторинга. Это не столько проблема инструмента, сколько проблема устаревшей инструкции.
Пару привычек особенно трудно вытравить:
- Продукт убирает функцию, а инженерная команда лишь прячет точку входа.
- Команды оставляют флаги открытыми, потому что никто не владеет финальной датой решения.
- Продажи и поддержка всё ещё упоминают старый сценарий в демо, заметках или шаблонных ответах.
- Подсказки и документы по настройке всё ещё учат ассистентов генерировать код для старого поведения.
- Владелец разбит между продуктом, инженерией и операционкой, поэтому никто не доводит последние 10 процентов.
Пункт про продажи и поддержку важнее, чем большинство команд ожидает. Если эти команды всё ещё обещают старое поведение, инженеры не решаются убирать последний backend-путь. Они оставляют один маршрут «на всякий случай», и этот маршрут становится оправданием для новой задержки. Вскоре у продукта есть две правды: что показывает интерфейс и о чём компания всё ещё говорит.
Разбитое владение — обычно корень проблемы. Один человек должен отвечать за весь список отключения: код, подсказки, документацию, аналитику, макросы поддержки, дашборды и флаги. В командах, которые сильно завязаны на AI, в этот список стоит включить ещё инструкции для агентов, шаблоны генерации кода и заметки в репозитории, которые модели используют как контекст.
Относитесь к удалению как к релизу, а не как к побочной задаче. Мёртвые пути остаются живыми, когда все думают, что их последнюю часть уберёт кто-то другой.
Проверки перед тем, как считать работу завершённой
Одна последняя проверка экономит много раздражающей уборки потом. Функция не исчезла, пока исчезла кнопка. Она исчезла тогда, когда код, подсказки, отчёты и привычки команды перестали на неё указывать.
Начните с обычного текстового поиска. Ищите название функции, старые ярлыки, внутренние прозвища и любой связанный с ней флаг. Проверьте код приложения, подсказки, тестовые файлы, help-документацию, шаблонные ответы поддержки, примечания к релизам и внутренние записи. Продукты, построенные с AI-инструментами, часто повторяют одну и ту же инструкцию в нескольких местах, так что одна пропущенная подсказка может удержать старый путь в живых.
Помогает короткий чеклист:
- Найдите все упоминания функции, включая старые формулировки, которые команда использовала в начале.
- Несколько дней смотрите логи и алерты и убедитесь, что старый путь остаётся тихим.
- Откройте экраны биллинга, аналитики, экспорта и админки, чтобы поймать сломанные ссылки.
- Попросите одного коллегу использовать продукт как клиент и пройти весь сценарий до конца.
- Запишите, когда вы удалили функцию и почему.
Логи подскажут, пытается ли продукт всё ещё использовать мёртвый код. Если старое событие всё ещё срабатывает, что-то всё ещё указывает на закрытый путь. Это может быть фоновая задача, скрытая настройка или подсказка, которая всё ещё просит старое поведение.
Потом проверьте не только приложение, но и бизнес-часть. Тарифы, счета, дашборды использования, CSV-экспорты и события аналитики часто продолжают хранить старые названия задолго после исчезновения функции. Клиенты замечают такие хвосты быстро, потому что они выглядят как баги или нарушенные обещания.
Проверка коллегой стоит десяти минут. Выберите человека, который не удалял эту функцию. Попросите его зарегистрироваться, пройтись по продукту и выполнить задачу так, как сделал бы клиент. Свежий взгляд замечает странные дыры, устаревший текст и маршруты, на которые вы уже перестали обращать внимание.
Запишите дату удаления и причину в одном месте, к которому команда будет возвращаться. Через полгода эта заметка остановит споры вроде «Мы это случайно не убили?». Она также поможет, когда AI-инструменты предложат вернуть код, который больше не нужен.
Сделайте вывод функций из продукта привычкой
Начинайте со спецификации, а не с тикета на уборку. В каждой новой спецификации функции должны быть понятный конец, дата ревью и точное обещание пользователям. Если это обещание перестаёт быть важным, у функции должен быть спланированный путь выхода, а не медленный дрейф в мёртвый код.
Затем сделайте вывод из продукта рутиной. Ежемесячное ревью работает лучше, чем гигантская очистка раз в год, потому что команда ещё помнит, зачем функция появилась, кто её просил и что вокруг неё уже ломалось. Каждый месяц выбирайте одну старую функцию и решайте, оставить её, уменьшить или убрать полностью.
Помогает простое правило:
- Добавляйте правила удаления в каждую продуктовую спецификацию.
- Раз в месяц проверяйте одну стареющую функцию.
- Убирайте обещание, кодовый путь, тесты, документацию и аналитику вместе.
- После каждого удаления обновляйте подсказки, правила и примеры.
- Фиксируйте решение в одном общем месте.
Четвёртый шаг важнее, чем кажется большинству команд. Если ваши AI-инструменты всё ещё читают старые подсказки, устаревшие примеры или старые архитектурные заметки, они будут снова и снова воссоздавать мёртвые пути. После каждого удаления обновляйте инструкции, которые используют ваши кодовые агенты, чистите старые фрагменты из внутренней документации и убирайте тесты, описывающие поведение, которое вам больше не нужно.
Для этого не нужен большой процесс. Одного короткого ревью, одного владельца и одного письменного решения часто достаточно. Небольшая SaaS-команда может экономить часы каждый месяц, просто перестав возвращать старую логику в следующем сгенерированном pull request.
Если ваша команда постоянно тащит старые функции вперёд, внешняя помощь может ускорить процесс. Oleg Sotnikov на oleg.is работает со стартапами и небольшими компаниями над архитектурой продукта, AI-процессами для кода и поддержкой в формате Fractional CTO. Короткий разбор может помочь ужесточить правила удаления и остановить возврат старых подсказок, документов и кодовых путей.
Часто задаваемые вопросы
Что такое правило удаления функции?
Это короткая заметка в спецификации, где сказано, какое обещание даёт функция, кто за неё отвечает, когда команда вернётся к ней и что означает её завершение. Лучше записать это до запуска, чтобы удаление воспринималось как обычная продуктовая работа, а не как спор в последний момент.
Когда стоит решать, остаётся функция или уходит?
Решайте это до релиза и ещё раз возвращайтесь к функции через 30, 60 или 90 дней после запуска. Ранняя дата не даёт команде месяцами тащить за собой малоценный код только потому, что никто не назначил день решения.
Кто должен отвечать за вывод функции из продукта?
Дайте финальное решение одному человеку — обычно это основатель, product lead или CTO. Другие команды могут дать вводные, но один владелец должен довести отключение до конца: в коде, документации, ответах поддержки, аналитике и флагах.
Какие признаки говорят, что функцию пора завершить?
Смотрите сразу на три вещи: использование, нагрузку на поддержку и время на сопровождение. Если функцией пользуются немногие, поддержка всё время отвечает на одни и те же вопросы, а инженеры постоянно чинят её вокруг, она уже стоит дороже, чем приносит пользы.
Сколько времени можно держать feature flags?
Относитесь к флагам как к временному инструменту, а не как к месту хранения. Назначьте дату завершения ещё до запуска и уберите флаг вскоре после релиза или отключения, иначе тесты, ветки и сгенерированный код будут продолжать поддерживать оба пути.
Какой порядок самый безопасный для удаления функции?
Сначала спрячьте точки входа, чтобы новые пользователи перестали находить функцию. Затем отключите маршруты, задачи, вебхуки и подсказки, которые скрываются за экраном, а уже после этого уберите код, тесты, документацию и дашборды одним проходом.
Почему AI-инструменты воскрешают старые функции?
Модели копируют то, что читают. Если в репозитории всё ещё лежат старые подсказки, комментарии, шаблоны или тестовые фикстуры, следующее сгенерированное изменение может частично восстановить закрытый сценарий.
Что нужно чистить кроме кода приложения?
Ищите шире, чем только интерфейс и API. Удалите старый текст подсказок, инструкции для агентов, макросы поддержки, события аналитики, исходные данные, админские подписи, заметки о релизе и любой шаблон, который всё ещё учит старому поведению.
Как быть с клиентами, которые всё ещё зависят от старого сценария?
Сообщите пользователям заранее, дайте дату отключения и предложите понятную замену. Если одной учётке нужен короткий переходный период, оформите это как ручное исключение с жёсткой датой окончания, а не оставляйте старую функцию живой для всех.
Когда имеет смысл привлекать внешнюю помощь?
Привлекайте внешнюю помощь, когда команда снова и снова откладывает удаление, флаги остаются открытыми месяцами, или AI-инструменты постоянно возвращают мёртвые пути. Короткий разбор у опытного CTO может навести порядок в владельцах, правилах очистки и гигиене подсказок до того, как беспорядок расползётся.