Как вставить свой код в середину процедуры или функции через расширение в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Проблема использования аннотации &Вместо

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

  1. Трудности при обновлении: Если поставщик (например, фирма 1С) изменит логику этой процедуры в новом релизе, ваше расширение продолжит исполнять старый код, который вы скопировали. Это может привести к критическим ошибкам в данных, так как важные типовые изменения будут проигнорированы.
  2. Дублирование кода: Вы вынуждены хранить в расширении сотни строк чужого кода ради одной своей строки. Это увеличивает объем конфигурации и сложность поддержки.
  3. Конфликты расширений: Если два разных расширения попытаются переопределить одну и ту же процедуру через &Вместо, возникнет конфликт, и система выполнит только одно из них.

Выясним, какие существуют альтернативы, позволяющие избежать этих рисков.

Метод №1: Аннотация &ИзменениеИКонтроль (рекомендуемый)

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

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


&ИзменениеИКонтроль("РассчитатьСкидкиНаСервере")
Процедура Расшир_РассчитатьСкидкиНаСервере(ПараметрыРасчета)
    
    // Типовой код до наших правок
    СуммаБезСкидки = ПараметрыРасчета.Сумма;
    
    #Вставка
    // Наша проверка в середине метода
    Если СуммаБезСкидки > 100000 Тогда
        ПараметрыРасчета.ДополнительныйПроцент = 5;
    КонецЕсли;
    #КонецВставки

    // Продолжение типового кода
    КонечныйРезультат = СуммаБезСкидки * (1 - ПараметрыРасчета.Процент/100);
    
КонецПроцедуры

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

Метод №2: Программное влияние через &Перед

Часто вставить код в середину требуется из-за какого-то условия (Если... Тогда). В некоторых случаях мы можем "обмануть" алгоритм, изменив входные данные в обработчике &Перед. Рассмотрим ситуацию, когда в середине процедуры проверяется некий флаг в структуре параметров.

Разберем пример изменения поведения через предобработку:


&Перед("ВыполнитьПроверкуДокумента")
Процедура Расшир_ВыполнитьПроверкуДокумента(ДокументСсылка, ПараметрыПроверки)
    
    // Если мы хотим, чтобы типовое условие в середине процедуры 
    // "Если ПараметрыПроверки.ПропускатьОшибки Тогда" сработало,
    // мы принудительно устанавливаем этот флаг здесь.
    
    ПараметрыПроверки.Вставить("ПропускатьОшибки", Истина);
    
КонецПроцедуры

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

Метод №3: Использование переопределяемых модулей (БСП)

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

Проанализируем структуру кода типовой конфигурации. Часто можно встретить вызовы вида:


// Типовой код
...
МодульВариантыОтчетовПереопределяемый.ПередВыводомОтчета(Параметры);
...

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

Метод №4: Подписки на события

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

Рассмотрим преимущества подписок:

Сравнение подходов и риски производительности

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

Подведем итог:

  1. Если версия платформы позволяет (8.3.15+), всегда выбирайте &ИзменениеИКонтроль вместо &Вместо.
  2. Прежде чем внедряться в середину, подумайте: нельзя ли изменить состояние объекта в методе &Перед так, чтобы середина отработала иначе.
  3. Всегда проверяйте наличие переопределяемых модулей БСП — это самый надежный способ интеграции.
  4. Избегайте копирования кода "как есть", так как это создает "технологический долг", который придется оплачивать временем при каждом обновлении конфигурации.

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

← На главную