При разработке расширений в системе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью модифицировать поведение типовых механизмов. Одним из самых элегантных способов считается использование аннотации &Перед (Before). Однако на практике возникают ситуации, когда изменения, внесенные в параметры внутри расширения, «теряются» при переходе в основную процедуру. Разберем подробно, почему это происходит и как правильно управлять данными в цепочке вызовов.
Когда мы используем аннотацию &Перед, платформа формирует цепочку вызовов. Сначала выполняется код процедуры из расширения, и только после его успешного завершения управление передается в основную конфигурацию. По умолчанию параметры в 1С передаются по ссылке. Это означает, что если мы изменим значение переменной в расширении, основная процедура должна получить уже модифицированное значение. Рассмотрим, какие факторы могут этому помешать.
Проанализируем ситуацию, описанную в исходном вопросе. Разработчик пытается изменить свойство структуры внутри процедуры расширения. Посмотрим на фрагмент кода:
Процедура DO00001_ВставитьШтрихкодПродолжение_Расширенная_Перед(НастройкиПоложенияШК, Параметры) Экспорт
// Извлечение данных в локальные переменные
ТекущиеДанные = Параметры.ТекущиеДанные;
ДанныеОШтрихкодеФайла = Параметры.ДанныеОШтрихкодеФайла;
// ... логика проверки условий ...
// Попытка изменения данных
ДанныеОШтрихкодеФайла.ФайлРедактируется = Истина;
КонецПроцедуры
В данном примере Параметры — это структура, и ДанныеОШтрихкодеФайла также является вложенной структурой. В 1С структуры являются объектами ссылочного типа. Это означает, что при присваивании ДанныеОШтрихкодеФайла = Параметры.ДанныеОШтрихкодеФайла в переменную ДанныеОШтрихкодеФайла копируется ссылка на тот же объект памяти. Изменение свойства ФайлРедактируется должно отразиться на исходном объекте.
Почему же в отладчике автор видел «старые» данные? Разберем основные причины:
ДанныеОШтрихкодеФайла = Новый Структура(...), то связь с исходным параметром была бы разорвана. Локальная переменная стала бы указывать на новый объект, а старый (внутри Параметры) остался бы неизменным.Знач, то расширение получит копию данных. Любые изменения этой копии (даже свойств структуры в некоторых контекстах выполнения) не вернутся в вызывающий код.Чтобы избежать неопределенности при работе с параметрами в &Перед, рекомендуется придерживаться следующих правил:
1. Прямое обращение к свойствам. Вместо создания промежуточных локальных переменных, изменяйте свойства структуры напрямую через главный параметр. Это исключает риск потери связи с объектом. Проанализируем правильный подход:
&Перед("ВставитьШтрихкодПродолжение")
Процедура DO00001_ВставитьШтрихкодПродолжение_Расширенная_Перед(НастройкиПоложенияШК, Параметры) Экспорт
// Обращаемся напрямую к вложенному объекту структуры Параметры
Если Параметры.Свойство("ДанныеОШтрихкодеФайла") Тогда
// Меняем свойство непосредственно в переданном объекте
Параметры.ДанныеОШтрихкодеФайла.Вставить("ФайлРедактируется", Истина);
КонецЕсли;
КонецПроцедуры
2. Проверка сигнатуры. Выясним причину, по которой параметры могут не меняться: всегда проверяйте, как описана процедура в основной конфигурации. Если там используется Знач, аннотация &Перед не позволит вам изменить «внешнюю» переменную, так как вы работаете с локальной копией, созданной для этого вызова.
Если логика изменения параметров сложна или &Перед по каким-то причинам не дает нужного результата, профессиональное сообщество рекомендует использовать аннотацию &Вместо (Instead). Рассмотрим этот способ подробнее.
В процедуре с аннотацией &Вместо мы можем полностью контролировать момент вызова основной логики с помощью метода ПродолжитьВызов(). Это позволяет подготовить параметры до того, как они попадут в базовый код.
&Вместо("ВставитьШтрихкодПродолжение")
Процедура DO00001_ВставитьШтрихкодПродолжение_Расширенная_Вместо(НастройкиПоложенияШК, Параметры)
// Модифицируем параметры по своему усмотрению
Если Параметры.ДанныеОШтрихкодеФайла <> Неопределено Тогда
Параметры.ДанныеОШтрихкодеФайла.ФайлРедактируется = Истина;
КонецЕсли;
// Вызываем основную процедуру с уже измененными параметрами
ПродолжитьВызов(НастройкиПоложенияШК, Параметры);
КонецПроцедуры
Этот метод считается более надежным (robust), так как вы явно передаете измененные объекты в метод ПродолжитьВызов. Здесь нет зависимости от того, как платформа управляет стеком вызовов в &Перед.
Часто программисты допускают ошибку при использовании отладчика. При проверке значений в &Перед важно помнить:
Параметры = Новый Структура;), тем самым затирая ваши изменения из расширения.Таким образом, мы выяснили, что изменять параметры через &Перед можно и нужно, если понимать разницу между ссылочными типами данных и примитивами, а также следить за тем, чтобы не разрывать связь с объектами через лишние локальные переменные.