Разработка в среде 1С часто ставит перед нами задачи, когда необходимо изменить поведение типовой конфигурации, не снимая ее с поддержки и не внося масштабных изменений в основную структуру метаданных. Расширения конфигурации предоставляют для этого мощный инструментарий, однако стандартные механизмы проверок и валидации (например, ограничение длины ИНН или маски ввода) могут мешать реализации специфических требований бизнеса. В этой статье мы разберем, как грамотно использовать аннотацию &Вместо, как управлять состоянием формы и как обращаться к данным, не перегружая расширение лишними объектами.
Рассмотрим ситуацию, когда типовой код при выполнении процедуры (например, при обновлении параметров формы или перед записью) принудительно обрезает данные или сбрасывает значения, которые нам необходимо сохранить. Один из наиболее эффективных приемов — это использование «обертки» вокруг стандартного вызова. Мы перехватываем выполнение процедуры, запоминаем нужное нам состояние, даем типовому коду отработать, а затем восстанавливаем наши данные.
Проанализируем пример реализации в модуле управляемой формы. Здесь мы меняем программно ограничение типа для поля и защищаем данные от очистки:
&НаКлиенте
&Вместо("УправлениеФормой")
Процедура дор_УправлениеФормой()
// Устанавливаем желаемую ширину элемента на форме
Элементы.ИНН.МаксимальнаяШирина = 18;
// Запоминаем текущее состояние: модифицированность и значение реквизита
ПредМодифицированность = Модифицированность;
ПредИНН = Объект.ИНН;
// Вызываем типовой код. Если в нем есть логика обрезки ИНН, она сработает здесь
ПродолжитьВызов();
// Программное изменение типа позволяет обойти жесткие ограничения метаданных в сеансе
Элементы.ИНН.ОграничениеТипа = Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(18));
// Восстанавливаем данные и состояние флага изменения формы
Объект.ИНН = ПредИНН;
Модифицированность = ПредМодифицированность;
КонецПроцедуры
В данном примере крайне важно обратить внимание на работу с переменной Модифицированность. Типовой код при изменении реквизитов программно может установить флаг модифицированности в значение Истина. Если наша задача — сделать изменения «незаметными» для системы, чтобы форма не предлагала сохранение при простом просмотре, мы восстанавливаем исходное состояние флага.
Аналогичный подход применим и в серверных модулях, например, при записи объекта. Если типовая конфигурация содержит жесткие проверки в процедуре ПередЗаписью, мы можем нивелировать их влияние, используя аналогичный алгоритм сохранения и восстановления значений. Выясним, как это выглядит в расширении модуля объекта:
&Вместо("ПередЗаписью")
Процедура дор_ПередЗаписью(Отказ)
// Сохраняем значение перед тем, как типовой код его изменит или очистит
ПредИНН = ЭтотОбъект.ИНН;
// Выполнение стандартных проверок и логики типовой конфигурации
ПродолжитьВызов(Отказ);
// Принудительное восстановление нашего значения после завершения типового алгоритма
ЭтотОбъект.ИНН = ПредИНН;
КонецПроцедуры
Здесь важно помнить, что использование ПродолжитьВызов(Отказ) передает управление дальше по цепочке расширений и в основную конфигурацию. Если типовая логика установит параметр Отказ в значение Истина, запись не будет произведена, несмотря на наши манипуляции со значениями реквизитов.
Одной из проблем при работе с расширениями является необходимость добавления в них всех используемых объектов метаданных. Это раздувает расширение и усложняет поддержку. Однако существует способ обращаться к реквизитам объекта «в обход» строгого контроля метаданных расширения. Рассмотрим два основных способа:
ЭтотОбъект.ИмяРеквизита часто позволяет обойти проверку синтакс-помощника расширения, хотя платформа все равно требует наличия реквизита в основной конфигурации.Объект["ИмяРеквизита"] или ЭтотОбъект["ИмяРеквизита"], мы обращаемся к свойству по его строковому имени. В этом случае платформе не требуется, чтобы реквизит был явно добавлен в дерево метаданных расширения.Важный нюанс: Хотя обращение через квадратные скобки удобно, оно лишает нас возможности проверки кода на этапе компиляции. Если в будущем реквизит будет удален из основной конфигурации, этот код вызовет ошибку времени выполнения.
При активном использовании механизмов &Вместо встает вопрос архитектуры. Как лучше организовать доработки? Разберем два подхода, которые практикуются в сообществе программистов 1С:
Большинство экспертов сходятся во мнении, что для кастомизации под конкретного клиента лучше использовать одно основное расширение, а дополнительные создавать только для тиражируемых модулей или интеграций.
Разберем ситуацию с увеличением длины поля ИНН, приведенную в примере. Несмотря на техническую возможность «обмануть» систему, программист должен осознавать риски:
&Вместо с цепочкой вызовов увеличивает стек вызовов и может незначительно влиять на производительность в высоконагруженных участках кода.Таким образом, использование расширений для «обхода» типового кода — это мощный инструмент, требующий аккуратности. Рассмотренные нами приемы сохранения состояния через ПродолжитьВызов() и динамическое обращение к реквизитам позволяют решать сложные задачи адаптации систем без внесения правок в основную конфигурацию.