Токсичный рефакторинг: когда хорошие намерения приводят к проблемам

29.04.26

Разработка - Рефакторинг и качество кода

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

Я хочу рассказать о рефакторинге, а если быть точным – о его токсичных проявлениях. Думаю, что каждый сталкивался с ситуацией, когда хорошие намерения по улучшению качества кода приводили к проблемам и негативным последствиям.

Напомню, что такое рефакторинг. Это процесс улучшения кода без изменения его поведения. Часто приводят аналогию с уборкой в комнате: мы убираем вещи, приводим в порядок пространство, но сама комната остается той же – четыре стены, двери, окна.

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

 

Признаки качественного рефакторинга

Качественный рефакторинг подразумевает глубокое понимание основных паттернов и техник, описанных Мартином Фаулером. Их достаточно много – несколько десятков. Из наиболее известных и используемых можно выделить извлечение метода, перемещение метода и замену условных конструкций в коде.

Второй признак – соблюдение принципа эквивалентности преобразований. Это означает, что любое изменение кода должно быть обратимым. Рефакторинг должен выполняться без привнесения новой функциональности. Это важно.

Третий признак – сохранение исходного поведения кода. Код до преобразования и после него должен вести себя одинаково. Ничего кардинально меняться не должно.

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

 

Когда к качеству рефакторинга есть вопросы

 

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

 

Рефакторинг очень старого кода

 

Первый пример – рефакторинг очень старого кода, legacy-кода. Какие здесь возникают проблемы:

  • Высокий риск внесения ошибок, потому что в legacy-коде могут быть неочевидные зависимости и нюансы, которые накопились за годы эксплуатации базы. Разбираться с бизнес-логикой в таком коде часто сложно и затруднительно.

  • Большие затраты по времени и ресурсам. Если нет планов дальше развивать этот legacy-код, лучше его не трогать. Такие усилия будут пустыми.

  • Важно помнить, что любое изменение старого кода может нарушить баланс, достигнутый за годы промышленной эксплуатации. Здесь хорошо подходит философия «работает – не трогай».

 

Предрелизный рефакторинг

 

Второй пример – предрелизный рефакторинг.

  • Перед релизом система должна находиться в стабильном состоянии. Вся новая функциональность уже присутствует в базе, критические баги исправлены, все протестировано. Если после этого начинать рефакторинг, стабильность системы нарушается, появляется элемент неопределенности.

  • Непредсказуемые последствия. Даже мелкие правки могут привести к проблемам. Правка в одном модуле через неявные зависимости может сломать систему в совершенно другом месте конфигурации.

  • Добавляется психологическое давление: команда нацелена на выпуск стабильной версии, приближается дедлайн, и срабатывает человеческий фактор. Даже мелкая правка может привести к ошибке.

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

 

Рефакторинг ради рефакторинга

 

Следующий пример – рефакторинг ради рефакторинга. Это ловушка перфекциониста. Часто разработчики делают рефакторинг, чтобы упростить себе жизнь: сделать код красивее, попробовать новую технологию или внедрить новый паттерн. Все это происходит без реальной необходимости, просто потому что захотелось.

Здесь важно помнить принцип YAGNI («You aren't gonna need it» – «Вам это не понадобится»). В ситуации рефакторинга ради рефакторинга код усложняется, а принцип нарушается. По сути, время тратится впустую.

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

Как избежать ловушки перфекционизма?

  • Важно понимать, что цель – улучшить код, но не стремиться к идеалу во что бы то ни стало. Это особенно важно на больших проектах. Доводить код до идеального состояния сложно, избыточно и дорого.

  • Необходимо понимать, какое решение является плохим, какое – приемлемым, а какое – идеальным. Оптимальный вариант – приемлемый код, в котором разработчик хорошо ориентируется, понимает, где может возникнуть ошибка, и в случае необходимости быстро вносит правки. Исправил и система снова работает корректно. Идеальный код – это тоже хорошо. Как говорит Линус Торвальдс: «Это хороший вкус к программированию», он элегантен, минималистичен и в нем нет ничего лишнего. Однако доведение кодовой базы до такого состояния – долгий процесс, и не всегда им стоит заниматься.

  • Вместо вопроса «что я могу улучшить еще?» полезнее задать вопрос «Могу ли я остановиться в своих рефакторинговых изысканиях?». Умение вовремя остановиться – важное профессиональное качество. В этом помогают code-review и соблюдение принципа KISS («Keep it simple, stupid» – «Делай проще, тупица»).

 

Рефакторинг без тестирования

 

Рефакторинг без тестирования означает внесение изменений без какой-либо проверки.

  • Основной риск в этом случае – привнесение в код скрытых ошибок. При отсутствии тестов остается надеяться на случай.

  • Существует риск потери части функциональности: можно случайно изменить или удалить важную бизнес-логику.

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

  • Возникает и косвенная проблема – страх вносить изменения и подрыв доверия к кодовой базе со стороны разработчиков. В таких условиях разработчики начинают выбирать более безопасные решения: рефакторинг игнорируется, усиливается перестраховка. Вместо доработки существующего кода добавляется новый, что приводит к дублированию.

 

Рефакторинг про запас

 

Рефакторинг про запас – это попытка угадать будущие потребности системы. В код закладывается дополнительная функциональность, которая на текущий момент не требуется. Понадобится ли она в будущем, неизвестно.

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

  • Возрастает риск принятия неоптимальных архитектурных решений, поскольку новые требования заказчика могут вступить в противоречие с заранее заложенной функциональностью.

  • Вместо решения реальных проблем время тратится на оптимизацию гипотетических сценариев.

 

 

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

 

Выделение функциональности в универсальный мегаметод

 

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

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

  • Это приводит к сложностям с пониманием, сопровождением, добавлением функциональности и тестированием кода. Для тестирования требуется проверять все возможные комбинации условий, что крайне трудоемко. Перед добавлением новой функциональности необходимо анализировать все существующие ветви, что при наличии мегаметода становится нетривиальной задачей.

  • Возникает высокая цикломатическая и когнитивная сложность из-за избытка условий.

 

 

Пример мегаметода достаточно показателен. Он очень длинный, и на изображении приведена лишь его часть.

Какие подходы можно использовать:

  • Разделение ответственности. Общую функциональность лучше выделять в небольшие методы.

  • Каждый метод должен выполнять только одну конкретную задачу.

  • Небольшое дублирование кода иногда лучше, чем преждевременная или избыточная абстракция. Здесь важно правильно понимать принцип DRY («Don’t Repeat Yourself» – «Не повторяйся»). Его не стоит воспринимать буквально. Главное – не допускать дублирования бизнес-логики. Повторяющийся синтаксис в отдельных случаях допустим.

 

Рефакторинг программного интерфейса

 

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

Какие основные проблемы могут возникнуть:

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

  • Вторая проблема – несоответствие документации и описания контракта программного интерфейса. Документация может устаревать и переставать отражать реальное поведение кода, поскольку разработчики не всегда своевременно вносят в нее изменения.

  • Еще одна проблема – радикальное изменение поведения метода. Это нарушение принципа наименьшего удивления. Разработчики привыкают к определенному поведению программного интерфейса, и его неожиданное изменение становится сюрпризом. В результате могут возникать ошибки в бизнес-логике.

 

 

Пример нарушения обратной совместимости: в методе программного интерфейса было изменено значение по умолчанию необязательного параметра. Раньше оно было равно «истина», теперь – «ложь». Для разработчиков это поведение оказалось неожиданным. В коде возникли ошибки при использовании метода, а описание контракта никто не обновил.

 

Рефакторинг без понимания бизнес-логики

 

Рефакторинг без понимания бизнес-логики приводит к ряду проблем:

  • Нарушение критических бизнес-правил. Код может выглядеть как плохой, но на практике в нем могут быть заложены особые условия: специальные скидки для клиентов, специфические правила округления, например с точностью до 18–20 знаков после запятой.

  • Нарушение требований регуляторов. Например, в сферах доверительного управления, инвестиций и ценных бумаг существует строгий порядок обработки данных. Рефакторинг без понимания этих требований может привести к нарушениям.

  • Усложнение поддержки. Со временем реальный код может разойтись с техническим заданием и бизнес-процессами, которые описаны в документации.

Чтобы избежать проблем, перед рефакторингом необходимо анализировать бизнес-логику. Если понимания нет, следует обратиться к предметному эксперту или бизнес-аналитику. Важно также наличие автотестов, которые покрывают хотя бы основные сценарии.

 

 

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

 

Отдельные задачи под рефакторинг

 

Отдельные задачи под рефакторинг – это вопрос накопления технического долга. Рассмотрим возникающие проблемы:

  • Казалось бы, планирование работы с техническим долгом – хорошее начинание. Однако такие задачи изначально оказываются внизу бэклога и имеют низкий приоритет, так как проигрывают конкуренцию более приоритетным бизнес-задачам. Это может быть оптимизация системы, добавление новой критически важной для бизнеса функциональности, исправление критических багов. Все это отодвигает задачу рефакторинга все ниже и ниже.

  • Отсутствие видимого прогресса. Для бизнеса отдельная задача на рефакторинг является невидимой работой. Она не дает быстрых и наглядных результатов. Эффект от рефакторинга проявляется в долгосрочной перспективе. Например, количество ошибок в коде может уменьшиться за счет снижения сложности и упрощения структуры. Однако сразу этот результат заметен не будет.

  • Накапливание технического долга. Увеличивается объем потенциальной работы для команды. Это происходит потому, что новый код пишется поверх старого. Старый код остается неотрефакторенным, а новый добавляется поверх него. В результате объем потенциальной работы возрастает.

 

 

Как можно избежать этих проблем:

  • Первое и самое важное – сделать рефакторинг частью выполнения основной задачи. Перед началом работы стоит проанализировать текущую ситуацию, исходное состояние системы и архитектуру, а затем внести необходимые правки по ходу выполнения задачи.

  • Незабвенное правило бойскаута: код после изменений должен быть чуть лучше, чем до них.

  • Если отказаться от отдельной задачи на рефакторинг не получается, можно выделять специальные дни для работы с техническим долгом. Это может быть один день в спринт или несколько часов в неделю.

  • Приоритизация технического долга. Еще один важный момент – не весь код и не весь технический долг одинаково важны. Необходимо проанализировать, в каких местах возникает наибольшее количество ошибок. Такие участки кода должны получать наивысший приоритет для рефакторинга.

 

Отсутствие единого стандарта рефакторинга

 

Отсутствие единого стандарта рефакторинга – ситуация «лебедь, рак и щука». Каждый разработчик действует по-своему, исходя из собственного опыта и насмотренности.

  • В результате возникает несогласованность среди разработчиков. Одному разработчику нравятся большие методы максимально допустимого размера, другому – множество мелких методов. Это приводит к спорам и росту напряженности в команде.

  • Проблемы при проведении код-ревью. Ревьюер начинает уделять больше внимания стилистическим особенностям кода, чем изменениям функциональности.

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

В качестве решения можно предложить создание внутренних стандартов. Их можно разрабатывать самостоятельно, но разумно опираться на стандарты разработки фирмы 1С. В таких стандартах стоит зафиксировать правила именования и организации кода. Полезно включить примеры хорошего и плохого рефакторинга с точки зрения команды.

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

Также важно использование современных инструментов анализа качества кода, таких как АПК, SonarQube, BSL LS, Phoenix BSL.

Примеры отсутствия стандарта хорошо заметны на практике. Например, можно встретить пять разных вариантов именования временных таблиц в запросах.

ВТ_Остатки
втОстатки
ВтОстатки
ВрТабОстатки
Остатки

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

 

Рефакторинг несущественных деталей задачи

 

Рефакторинг несущественных деталей задачи – еще одна распространенная проблема. Разработчик берет бизнес-задачу, но вместо работы над основным требованием сосредотачивается на второстепенных деталях. Начинается рефакторинг мелочей, наведение красоты, улучшение оформления.

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

Что в результате:

  • Происходит затягивание сроков, срыв дедлайнов.

  • Команда тратит больше времени и усилий, чем планировалось.

  • Потеря фокуса. Мелкие детали отвлекают от более важных задач.

  • Привнесение новых ошибок.

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

Приведу два примера из практики.

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

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

 

Так когда же рефакторить?

 

После рассмотрения большого количества примеров может показаться, что рефакторить вообще не стоит. Однако это не так.

  • Рефакторинг наиболее уместен при разработке новой функциональности. В этот момент проводится анализ того, как новый код будет интегрироваться в существующую систему. Перед началом разработки полезно выполнить своеобразную уборку рабочего места. После завершения разработки, когда все технические решения приняты и реализованы, допустим небольшой рефакторинг, но обязательно до начала тестирования, чтобы не вносить ошибки после его прохождения.

  • Рефакторинг уместен и при исправлении ошибок, так как ошибки часто являются следствием сложного и запутанного кода.

  • Во время код-ревью ревьюер может указать на потенциальные проблемы, а автор кода – устранить их. В целом код-ревью является эффективным инструментом для выявления мест, где требуется рефакторинг.

  • Также стоит помнить о правиле трех (Rule of Three). Если один и тот же код встречается три раза и возникает желание его отрефакторить, то именно на третий раз это действительно стоит сделать.

 

Рефакторить или нет?

 

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

«Рефакторинг должен быть таким же привычным, как чистка зубов. Но если делать это топором, последствия будут болезненными» (М. Фаулер).

 

*************

Статья написана по итогам доклада (видео), прочитанного на конференции INFOSTART TEAMLEAD&CIO EVENT.

Инфостарт Tech Event 2026

Инфостарт A&PM Event 2026

Вступайте в нашу телеграмм-группу Инфостарт

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Рефакторинг и качество кода Разработчик 1С 8.3 1С 8.5 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 Бесплатно (free)

Знакомая последовательность. Внешний отчет на СКД: модуль объекта на две тысячи строк, девять текстов запросов, три набора данных со связями. Переделываю под другую базу, собираю ERF, прогоняю пакетную проверку конфигуратором, чисто. Отдаю. Через двадцать минут приходит скриншот: «Переменная не определена». Правлю, пересобираю, отдаю. Через двадцать минут второй: «Не задано значение параметра». Два круга через живого человека ради двух ошибок, каждая из которых воспроизводится на той же машине за три секунды. Если знать, чем ее воспроизводить. Воспроизводит ее COM-коннектор, и дальше вся статья про то, как из него собрать проверку, которая умеет падать.

28.09.2026    294    KonMa    0    

2

Рефакторинг и качество кода Разработчик 1С 8.3 1С:Управление торговлей 11 Россия Бесплатно (free)

8 приёмов за 10 минут: перестаньте прокручивать общий модуль на три тысячи строк как ленту в соцсети. Outline, #Область и фильтр - и вы уже в нужной процедуре, а не на строке «где-то внизу».

25.09.2026    1551    aleksandrboldyusov    6    

15

Перенос данных 1C Рефакторинг и качество кода Разработчик 1С 8.3 Бесплатно (free)

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

24.09.2026    402    nedomolkov.ivan    0    

0

Рефакторинг и качество кода Обновление 1С Разработчик 1С 8.3 Бесплатно (free)

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

22.09.2026    568    1c-izh    0    

5

Рефакторинг и качество кода Тестирование QA Разработчик Бесплатно (free)

Штатная страховка внутри цепочки обработки умеет прятать дефекты того шага, который стоит перед ней. У нас так и вышло: валидатор чинил результат постфактум, на выходе всё выглядело корректно, и никто не видел, что предыдущий шаг молча теряет данные. Вылезло это только на независимой проверке чужими глазами. Разбираю, чем инвариант отличается от сценарного теста и почему обычное умножение вытащило дефект из красивой метрики 0,997. Отдельно про 13 дублей, которые приехали из источника ещё до всякой обработки, и про две находки, которые оказались вообще не моими: они жили в эталонной реализации, откуда я списывал логику. Вторая часть про лимит выхода модели: почему обрезка ответа по длине это тихий ноль в мониторинге и как смена формата на дельты уронила выход до 4 951 токена. Есть отклонённые гипотезы и честный список того, чего мы так и не померили.

21.09.2026    468    nedomolkov.ivan    2    

1

WEB-интеграция Рефакторинг и качество кода Системный администратор Разработчик 1С 8.3 Бесплатно (free)

Я сел проверять внутренний поисковый сервис по коду: можно ли доверять ему в автоматическом режиме. Сверка с обычным текстовым поиском по файлам дала 261 из 261, 264 из 264 и 182 из 182 совпадений, разбор структуры файла - 318 функций из 318. Стопроцентная точность. Этот же замер и вскрыл, что опираться на сервис нельзя: искал он безупречно, только совсем не в том месте, которое я ему называл. Внутри разбор трёх дефектов, сложившихся в один тихий отказ: аргумент, проглоченный без ошибки; умолчание, выставленное когда-то наугад; снимок данных, у которого в ответе не указан возраст. Плюс регулярное задание, которое вся команда считала работающим и которого не существовало никогда. Перенос на 1С прилагается: готовый цикл проверки, после которого HTTP-сервис перестаёт молча принимать мусор.

21.09.2026    465    nedomolkov.ivan    0    

0

Логистика, склад и ТМЦ Рефакторинг и качество кода Разработчик Аналитик Руководитель проекта 1С 8.3 Бесплатно (free)

Кладовщик получает задачу: на складе проверки лежат две штуки. Идёт в зону, а там всё на месте и никакой задачи в складской системе нет. Так работала автоматическая сверка остатков между учётной и складской системами: разницу она переносила документом, а комментарий к этому документу восемь месяцев отправлял людей искать несуществующий ноль. Робота разобрали до кода. Обе сравниваемые величины оказались синтетическими: слева физический срез с вычетами по активности и окнами в 60 минут и 12 часов, справа учётный остаток на конец дня минус трёхчасовой хвост непроведённых ордеров. Порог срабатывания стоял в нуле, поэтому робот исправно оформлял собственный шум измерения: за 60 дней он сам создал 62,7% оборота технического склада, а 2 081 артикул из 2 102 приезжал туда и уезжал обратно. Внутри обе формулы, замер лага отгрузки, снятая гипотеза и честная граница данных.

21.09.2026    479    nedomolkov.ivan    2    

0
Для отправки сообщения требуется регистрация/авторизация