Разработка в расширениях часто позиционируется как идеальный способ кастомизации конфигураций 1С, позволяющий «оставить систему на полной поддержке». Однако на практике бесконтрольный перенос логики в расширения с использованием перехватчиков &Вместо (Rather) превращается в тяжелый технологический долг. При очередном обновлении типового решения (например, такой сложной конфигурации, как «1С:Управление холдингом») разработчики сталкиваются с тем, что расширение начинает работать некорректно или вовсе блокирует запуск системы.
В этой статье мы подробно проанализируем, почему массовое использование директивы &Вместо является опасным антипаттерном, разберем возможные стратегии решения этой проблемы и выясним, как сократить время обновления подобной базы со 100 часов до пары часов с помощью современных инструментов платформы и автоматизации.
Давайте разберем технические причины, по которым слепое переопределение методов в расширениях через &Вместо приводит к критическим сбоям при обновлениях:
&Вместо полностью блокирует выполнение оригинального кода. Если вендор в новом релизе исправил критическую ошибку в данном модуле или добавил заполнение нового важного реквизита (без которого другие модули будут падать), ваша система об этой логике не узнает, так как расширение выполнит старый код.&Вместо, применится только одно из них (обычно последнее по приоритету), а остальные доработки просто проигнорируют вызов.Рассмотрим две глобальные стратегии решения этой проблемы, которые помогут нам выйти из тупика.
Многие разработчики боятся снимать конфигурацию с полной поддержки, считая, что это усложнит жизнь. Но давайте сравним трудозатраты в долгосрочной перспективе.
При наличии 100 измененных общих модулей в расширении ручной анализ каждого изменения при каждом обновлении может занимать до 100 часов рабочего времени программиста. Если же вернуть изменения в основную конфигурацию (поставив ее на поддержку с возможностью изменения), то последующие обновления будут занимать всего 2–3 часа. Проверено практикой опытных разработчиков!
Выясним причину такой колоссальной разницы: стандартный механизм сравнения и объединения конфигураций 1С, дополненный внешними программами трехстороннего слияния текста (такими как Kdiff3 или P4Merge), автоматически объединяет до 95% изменений в коде. Система сама понимает, где вендор добавил свой код, а где вы внесли свои изменения, и аккуратно совмещает их.
Разберем по шагам алгоритм перехода к этой стратегии:
&Вместо.
// {{Доработка_ИмяПроекта
// Здесь размещается наш измененный код
// }}Доработка_ИмяПроекта
Теперь при выходе очередного обновления вы просто запускаете стандартное сравнение и объединение с новой конфигурацией поставщика. Внешний диффер автоматически сольет ваши доработки с новым кодом вендора. Вам останется лишь визуально проконтролировать редкие конфликтные ситуации.
Если корпоративная политика или условия поддержки категорически запрещают изменять основную конфигурацию, нам придется полностью переписать архитектуру расширения, сделав его устойчивым к обновлениям. Для этого мы откажемся от опасного &Вместо в пользу современных инструментов контроля кода.
Проанализируем современные встроенные механизмы платформы, которые призваны решить эту проблему:
Эта аннотация (появившаяся в платформе версии 8.3.15) призвана полностью заменить «слепое» замещение методов. Вместо полного перекрытия метода мы заимствуем код процедуры, а платформа контролирует его целостность на уровне текста. Внутри метода мы используем специальные инструкции разметки.
Посмотрим на пример правильного использования аннотации &ИзменениеИКонтроль:
&ИзменениеИКонтроль("ЗаполнитьДанныеДокумента")
Процедура ЗаполнитьДанныеДокумента(ДокументСсылка, ПараметрыЗаполнения)
// Платформа контролирует этот код. Если вендор изменит его, расширение не применится.
#Удаление
ДокументСсылка.Статус = Справочники.Статусы.Черновик;
#КонецУдаления
#Вставка
// Наша новая безопасная логика
ДокументСсылка.Статус = Справочники.Статусы.На Согласовании;
ДокументСсылка.Ответственный = ПараметрыЗаполнения.ТекущийПользователь;
#КонецВставки
КонецПроцедуры
Если при обновлении оригинальный метод в типовой конфигурации изменится хотя бы на один символ, платформа сразу выдаст ошибку применимости расширения при запуске конфигурации. Это предотвратит скрытые рантайм-сбои и сразу укажет разработчику, в каких именно модулях логика вендора разошлась с доработками.
Стараемся по максимуму уходить от переопределения логики. Если нам нужно просто выполнить код до или после работы типового механизма, используем соответствующие аннотации. Это позволяет коду расширения работать «поверх» типового, не ломая его внутреннюю структуру.
Рассмотрим пример добавления логики после выполнения типового метода с передачей контекста:
&После("РассчитатьСкидку")
Процедура Расширение_РассчитатьСкидку(СтрокаДокумента, ПараметрыРасчета)
// Типовой расчет уже отработал. Добавляем дополнительную скидку для спец-клиентов:
Если ПараметрыРасчета.СпецКлиент Тогда
СтрокаДокумента.СуммаСкидки = СтрокаДокумента.СуммаСкидки + (СтрокаДокумента.Сумма * 0.05);
КонецЕсли;
КонецПроцедуры
Если модулей в расширении действительно много, ручной анализ каждого из них превращается в рутину. Давайте разберем стек технологий, который автоматизирует этот процесс:
Знач / ByVal) в расширении параметрам в основной конфигурации. Теперь ошибки сигнатур выявляются еще до запуска базы данных пользователями.diff3cf анализирует перехваченные методы и формирует интерактивный HTML-отчет, где наглядно показано, какие типовые методы изменились в новом релизе и как это сопоставляется с кодом вашего расширения.Чтобы будущие обновления конфигурации не вызывали головную боль, давайте сформулируем «золотые правила» разработки расширений:
&После или &ИзменениеИКонтроль) пишите как можно меньше кода. Создайте собственный общий модуль расширения и вызывайте его функции. Таким образом, при обновлении вам нужно будет контролировать только одну строчку вызова, а вся бизнес-логика останется изолированной.Свойство(), чтобы не вызвать ошибку обращения к несуществующему ключу при изменении структуры вендором.Подведем итоги: Массовый перенос 100 общих модулей в расширение через &Вместо — это архитектурная ошибка, требующая исправления. Лучшим решением для долгосрочного сопровождения базы является перенос этих доработок обратно в основную конфигурацию с настройкой автоматического слияния Kdiff3. Если это невозможно, необходимо провести рефакторинг расширения, заменив все директивы &Вместо на контролируемые аннотации &ИзменениеИКонтроль, &Перед и &После.