Как обойти типовую логику и ограничения 1С с помощью расширений: практические приемы

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

Разработка в среде 1С часто ставит перед нами задачи, когда необходимо изменить поведение типовой конфигурации, не снимая ее с поддержки и не внося масштабных изменений в основную структуру метаданных. Расширения конфигурации предоставляют для этого мощный инструментарий, однако стандартные механизмы проверок и валидации (например, ограничение длины ИНН или маски ввода) могут мешать реализации специфических требований бизнеса. В этой статье мы разберем, как грамотно использовать аннотацию &Вместо, как управлять состоянием формы и как обращаться к данным, не перегружая расширение лишними объектами.

Метод перехвата управления через аннотацию &Вместо

Рассмотрим ситуацию, когда типовой код при выполнении процедуры (например, при обновлении параметров формы или перед записью) принудительно обрезает данные или сбрасывает значения, которые нам необходимо сохранить. Один из наиболее эффективных приемов — это использование «обертки» вокруг стандартного вызова. Мы перехватываем выполнение процедуры, запоминаем нужное нам состояние, даем типовому коду отработать, а затем восстанавливаем наши данные.

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


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

В данном примере крайне важно обратить внимание на работу с переменной Модифицированность. Типовой код при изменении реквизитов программно может установить флаг модифицированности в значение Истина. Если наша задача — сделать изменения «незаметными» для системы, чтобы форма не предлагала сохранение при простом просмотре, мы восстанавливаем исходное состояние флага.

Работа с данными в модуле объекта через расширение

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


&Вместо("ПередЗаписью")
Процедура дор_ПередЗаписью(Отказ)
    // Сохраняем значение перед тем, как типовой код его изменит или очистит
    ПредИНН = ЭтотОбъект.ИНН;
    
    // Выполнение стандартных проверок и логики типовой конфигурации
    ПродолжитьВызов(Отказ); 
    
    // Принудительное восстановление нашего значения после завершения типового алгоритма
    ЭтотОбъект.ИНН = ПредИНН;
КонецПроцедуры

Здесь важно помнить, что использование ПродолжитьВызов(Отказ) передает управление дальше по цепочке расширений и в основную конфигурацию. Если типовая логика установит параметр Отказ в значение Истина, запись не будет произведена, несмотря на наши манипуляции со значениями реквизитов.

Обращение к реквизитам без включения их в расширение

Одной из проблем при работе с расширениями является необходимость добавления в них всех используемых объектов метаданных. Это раздувает расширение и усложняет поддержку. Однако существует способ обращаться к реквизитам объекта «в обход» строгого контроля метаданных расширения. Рассмотрим два основных способа:

  1. Использование ключевого слова ЭтотОбъект: В контексте модуля объекта или формы обращение через ЭтотОбъект.ИмяРеквизита часто позволяет обойти проверку синтакс-помощника расширения, хотя платформа все равно требует наличия реквизита в основной конфигурации.
  2. Обращение через квадратные скобки (динамическое обращение): Это наиболее гибкий способ. Используя конструкцию Объект["ИмяРеквизита"] или ЭтотОбъект["ИмяРеквизита"], мы обращаемся к свойству по его строковому имени. В этом случае платформе не требуется, чтобы реквизит был явно добавлен в дерево метаданных расширения.

Важный нюанс: Хотя обращение через квадратные скобки удобно, оно лишает нас возможности проверки кода на этапе компиляции. Если в будущем реквизит будет удален из основной конфигурации, этот код вызовет ошибку времени выполнения.

Стратегия организации расширений: одно или много?

При активном использовании механизмов &Вместо встает вопрос архитектуры. Как лучше организовать доработки? Разберем два подхода, которые практикуются в сообществе программистов 1С:

  1. Монолитное расширение: Весь функционал собирается в одном «большом» расширении. Это упрощает управление общими модулями и позволяет избежать конфликтов приоритетов между разными расширениями. Это удобнее для поддержки уникальных информационных баз.
  2. Декомпозиция на патчи: Создание отдельного расширения под каждую конкретную задачу или исправление ошибки (по аналогии с патчами фирмы 1С). Это позволяет гибко отключать или подключать конкретные «заплатки», но может привести к путанице, если расширений становится больше 20–30, так как каждое из них потребляет ресурсы при инициализации сеанса.

Большинство экспертов сходятся во мнении, что для кастомизации под конкретного клиента лучше использовать одно основное расширение, а дополнительные создавать только для тиражируемых модулей или интеграций.

Риски и предостережения при модификации типовых полей

Разберем ситуацию с увеличением длины поля ИНН, приведенную в примере. Несмотря на техническую возможность «обмануть» систему, программист должен осознавать риски:

Таким образом, использование расширений для «обхода» типового кода — это мощный инструмент, требующий аккуратности. Рассмотренные нами приемы сохранения состояния через ПродолжитьВызов() и динамическое обращение к реквизитам позволяют решать сложные задачи адаптации систем без внесения правок в основную конфигурацию.

← На главную