При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью изменить логику типовой конфигурации. Если ваша задача требует внедрения кода не в начало или конец метода, а в его середину, перед вами встает выбор: как сделать это максимально безопасно для будущих обновлений. Рассмотрим основные подходы, разберем их плюсы и минусы, а также изучим современные инструменты платформы, которые решают эту задачу изящно.
Традиционный и самый очевидный способ, который обсуждают участники форума, — это использование аннотации &Вместо. На первый взгляд, это кажется простым: мы полностью копируем процедуру из основной конфигурации в расширение, вносим нужные правки в середине текста и работаем. Однако этот путь таит в себе серьезные опасности, которые проанализируем ниже:
&Вместо, возникнет конфликт, и система выполнит только одно из них.Выясним, какие существуют альтернативы, позволяющие избежать этих рисков.
Начиная с версии платформы 8.3.15, появился механизм, который радикально изменил подход к редактированию типового кода. Аннотация &ИзменениеИКонтроль позволяет платформе отслеживать изменения в основной конфигурации и сигнализировать, если типовой код изменился. Разберем по шагам, как это работает.
Вместо полного замещения вы используете специальные теги в коде расширения. Проанализируем пример, где нам нужно вставить проверку в середину типовой процедуры расчета скидки:
&ИзменениеИКонтроль("РассчитатьСкидкиНаСервере")
Процедура Расшир_РассчитатьСкидкиНаСервере(ПараметрыРасчета)
// Типовой код до наших правок
СуммаБезСкидки = ПараметрыРасчета.Сумма;
#Вставка
// Наша проверка в середине метода
Если СуммаБезСкидки > 100000 Тогда
ПараметрыРасчета.ДополнительныйПроцент = 5;
КонецЕсли;
#КонецВставки
// Продолжение типового кода
КонечныйРезультат = СуммаБезСкидки * (1 - ПараметрыРасчета.Процент/100);
КонецПроцедуры
Почему это лучше? При обновлении системы платформа проверит, соответствует ли текст процедуры в основной конфигурации тому, что было на момент создания расширения. Если 1С изменит хотя бы одну запятую в типовом блоке, расширение выдаст ошибку при проверке, и вы сразу поймете, что нужно актуализировать ваш код. Это избавляет от необходимости вручную сравнивать модули после каждого обновления.
Часто вставить код в середину требуется из-за какого-то условия (Если... Тогда). В некоторых случаях мы можем "обмануть" алгоритм, изменив входные данные в обработчике &Перед. Рассмотрим ситуацию, когда в середине процедуры проверяется некий флаг в структуре параметров.
Разберем пример изменения поведения через предобработку:
&Перед("ВыполнитьПроверкуДокумента")
Процедура Расшир_ВыполнитьПроверкуДокумента(ДокументСсылка, ПараметрыПроверки)
// Если мы хотим, чтобы типовое условие в середине процедуры
// "Если ПараметрыПроверки.ПропускатьОшибки Тогда" сработало,
// мы принудительно устанавливаем этот флаг здесь.
ПараметрыПроверки.Вставить("ПропускатьОшибки", Истина);
КонецПроцедуры
Этот способ считается максимально "чистым", так как мы не дублируем код процедуры вообще, а лишь подготавливаем данные так, чтобы типовой алгоритм отработал нужным нам образом.
Если ваша конфигурация разработана на базе Библиотеки Стандартных Подсистем (БСП), стоит проверить, нет ли в нужной вам процедуре вызова "переопределяемого" модуля. Разработчики 1С часто внедряют в "тяжелые" процедуры точки расширения.
Проанализируем структуру кода типовой конфигурации. Часто можно встретить вызовы вида:
// Типовой код
...
МодульВариантыОтчетовПереопределяемый.ПередВыводомОтчета(Параметры);
...
В этом случае вам вообще не нужно использовать расширение для исходного модуля. Найдите в дереве конфигурации ОбщийМодуль с суффиксом Переопределяемый, добавьте его в расширение и напишите код в соответствующей процедуре. Это "законный" и наиболее стабильный способ модификации логики.
Если процедура, в середину которой вы хотите попасть, вызывается в процессе записи, проведения или отмены проведения документа, эффективнее использовать Подписки на события. Хотя они выполняются либо строго до, либо строго после основного действия, часто логику "середины" можно вынести в отдельную подписку, которая сработает в нужный момент транзакции.
Рассмотрим преимущества подписок:
Важно помнить, что использование &Вместо для огромных процедур общих модулей негативно сказывается на производительность. Платформа вынуждена компилировать и держать в памяти дубликат кода. При использовании &ИзменениеИКонтроль нагрузка сохраняется, но вы получаете контроль качества. Самыми быстрыми и стабильными остаются методы &Перед, &После и подписки на события.
Подведем итог:
&ИзменениеИКонтроль вместо &Вместо.&Перед так, чтобы середина отработала иначе.Используя эти методы, мы сможем создавать расширения, которые не только решают бизнес-задачи, но и остаются легкими в поддержке на протяжении многих лет.