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

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

Допустим на форме нужно в зависимости от интерактивного изменения флажка устанавливать значение какого-либо реквизита, это можно сделаеть так:

Вариант 1:
&НаКлиенте
Процедура ФлажокПриИзменении(Элемент)
      ФлажокПриИзмененииНаСервере();
КонецПроцедуры

 &НаСервере
Процедура ФлажокПриИзмененииНаСервере()
      Объект.Статус = Перечисления.СтатусыЗаказовКлиентов.КОбеспечению;
      // или так: Объект.Статус = Перечисления.СтатусыЗаказовКлиентов.ПустаяСсылка; 
КонецПроцедуры 

Или так: 

Вариант 2:
&НаКлиенте
Процедура ФлажокПриИзменении(Элемент)
       Объект.Статус = ВернутьСтатусНаСервере();
КонецПроцедуры

 &НаСервереБезКонтекста
Функция ВернутьСтатусНаСервере ()
      Возврат Перечисления.СтатусыЗаказовКлиентов.КОбеспечению;
      // или так: Возврат = Перечисления.СтатусыЗаказовКлиентов.ПустаяСсылка; 
КонецФункции

Строго говоря, оба эти варианта «неправильные», т.е. работать они конечно же будут, но неэффентивно, так же неэффективен следующий вариант (есть в УТ11):

Вариант 3:
&НаКлиенте
Процедура ФлажокПриИзменении(Элемент)
       Объект.Статус = РаботаСФомулами.ВычислитьФормулу(«Перечисления.СтатусыЗаказовКлиентов.КОбеспечению»);
КонецПроцедуры

Здесь производится вывов стандартной серверной функции, реализованной в общем модуле УТ11 РаботаСФомулами.ВычислитьФормулу. Её реализация:

Функция ВычислитьФормулу(ТекстРасчета) Экспорт
       Возврат Вычислить(ТекстРасчета);
КонецФункции

Эта «фича», которая позволяет не описывать процедуры/функции исполняемой на сервере, а использует уже готовую «универсальную», но существует и «пара но«, а именно:
   — уже есть функция платформы, которая может выполнять, почти тоже самое(об этом позднее);
   — если у вас есть РаботаСФомулами.ВычислитьФормулу, а база опубликована в веб, то любой человек может выполнять на вашем сервере произвольный 1С-код, просто передавая туда HTTP-запросы (Evil Beaver)

Функция платформы, которая позволяет сделать тоже самое, но с одной стороны без привязки к конфигурации, с другой кэшируя полученное значение:

Вариант 4:
&НаКлиенте
Процедура ФлажокПриИзменении(Элемент)
       Объект.Статус = ПредопределенноеЗначение(«Перечисление.СтатусыЗаказовКлиентов.КОбеспечению»);
КонецПроцедуры

Последний вариант с одной стороны позволяет не прибегать к увеличению кода, за счет вызова на клиенте, с другой кэширует полученное значение на уровне платформы. Есть у него и незначительный недостаток, который, впрочем, возникает при «некрасивом стиле» программирования, например таком:

&НаКлиенте
Процедура ФлажокПриИзменении(Элемент)
       Объект.Группа = РаботаСФомулами.ВычислитьФормулу(«Справочники.Партнеры.НайтиПоКоду(«»00002″»)»);
КонецПроцедуры

Такое значение нельзя вычислить используя Вариант 4, но правильнее в этом случае использовать предопределенный элемент справочника, тогда Вариант 4 вполне применим, например так:

&НаКлиенте
Процедура ФлажокПриИзменении(Элемент)
       Объект.Группа = ПредопределенноеЗначение(«Справочник.Партнеры.НашеПредприятие»);
КонецПроцедуры

 

Кратко преимущества(+)/недостатки(—) каждого варианта

+/— Возможность Вариант Вариант 1 Вариант 2 Вариант 3 Вариант 4
  Количество вызовов сервера при первоначальном использовании одного значения формы 1 1 1 1
  Количество вызовов сервера при первоначальном использовании N значений формы  1 N N N
  Количество вызовов сервера при повторном использовании уже полученного одного значения  1 1 1 0
  Количество вызовов сервера при повторном использовании уже полученных N значений 1 N N 0
+ Контекстная подсказка при написании кода Есть Есть Нет Есть
+ Возможность использования предопределенных и пустых значений объектов Есть Есть Есть Есть
+ Использование функций типа НайтиПоКоду, НайтиПоНаименованию… Есть Есть Есть Нет
+ Нагладность кода Есть Есть Есть Есть
+ Возможность проверки, используя синтаксис контроль Есть Есть Нет Нет
+ Возможность проверки, используя контроль при сохранении (со словами «Возможно ошибочный параметр») Нет Нет Нет Есть
— Необходимость написания процедуры/функции исполняемой на сервере  Есть Есть Нет Нет

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

Вариант 2 — вообще желательно не употеблять ввиду его недостатков и возможность замещения другими, более эффективными вариантами.

Вариант 3 — можно рекомендовать только как временное решение (если база не опубликована в веб), до добавления предопределенного значения.

ЗЫ: Особое спасибо Magisterу, Поручику и Evil Beaver, за то что наставили на «путь истины», критикой в комментариях (изначально статья имела совсем другое содержание и выводы).

19 Comments

  1. mxm2

    Применять удобно при взаимодействии с пользователем, например, при изменении реквизита на форме, — заполнять нужным значением, какой-либо другой реквизит. Если же нужно заполнить несколько реквизитов применение указанного метода будет приводить к нескольким вызовам сервера, что нежелательно.

    Reply ↓
  2. Magister

    Вот за это:

    РаботаСФомулами.ВычислитьФормулу(«Перечисления.СтатусыЗаказовКлиентов.КОбеспечению»);

    минус!

    нужно писать так:

    ПредопределенноеЗначение(«Перечисление.СтатусыЗаказовКлиентов.КОбеспечению»);

    Это, как минимум, кэшируется на уровне платформы — так что при втором и следующих вызовах обращения к серверу не будет.

    Reply ↓
  3. Поручик

    Тоже самое касается и получения пустой ссылки для перечисления и справочника или предопределённых элементов справочника.

    Reply ↓
  4. mxm2

    (2) Magister, (3) Поручик, спасибо за критику, принял к сведению, изменил статью.

    Reply ↓
  5. mxm2

    (5) artbear, Для простейших 4 для более сложных (без взаимодействия с пользователем) — 1. К предопределенным можно сводить НайтиПоКоду, НайтиПоНаименованию.

    Reply ↓
  6. Magister

    (5) Зато он по скорости оптимальнее, т.к. значения кешируются платформой.

    Reply ↓
  7. DoctorRoza

    Хм, а ведь интересная тема поднята на самом деле. Использование функции глобального контекста маленько, но сократит код! Автору респект! 🙂

    Reply ↓
  8. TODD22

    Автор купи себе учебник по стилистике русского языка. Твой заголовок ужасен.

    Reply ↓
  9. mxm2

    (9) TODD22, заголовок неказист, но суть отражает верно ).

    Reply ↓
  10. Evil Beaver

    Обожымой! Зачем эта статья? Сообщить миру, чтобы прежде, чем городить костыли с ОбщийМодуль.ВычислитьНаСервере почитали документацию про ПредопределенноеЗначение?

    Reply ↓
  11. Evil Beaver

    И еще. Если у вас есть СерверныйМодуль.ВычислитьНаСервере, а база опубликована в веб, то любой человек может выполнять на вашем сервере произвольный 1С-код, просто передавая туда HTTP-запросы. Вас это не пугает?

    Reply ↓
  12. mxm2

    (12) Evil Beaver, вебом не пользуюсь, но пугает, такая интересная особенность… а ведь она в стандарте УТ11…

    Reply ↓
  13. mxm2

    (11) Evil Beaver,

    Зачем эта статья? Сообщить миру, чтобы прежде, чем городить костыли с ОбщийМодуль.ВычислитьНаСервере почитали документацию про ПредопределенноеЗначение?

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

    Reply ↓
  14. Evil Beaver

    (13)

    а ведь она в стандарте УТ11…

    Что-то не нашел. Подскажете модуль, номер строки и версию конфы?

    Reply ↓
  15. mxm2

    (15) Evil Beaver,

    11.0.9.15: ОбщиеМодули.РаботаСФормулами.ВычислитьФормулу (стр. 85) (актуальная на момент написания статьи версия).

    11.1.1.11: ОбщиеМодули.РаботаСФормуламиКлиентСервер.ПроверитьФормулу (стр. 32) — правда здесь добавлен код обработки, (который может не позволить использовать само вычисление, но передать на запуск выражение возможно).

    Вопрос: какой должен быть HTTP запрос к веб-базе, чтобы выполнить произвольный код на 1С (обходящий права доступа, или вообще вредоносный)?

    Reply ↓
  16. Evil Beaver

    (16) mxm2 нет под рукой редакции 11.0, чтобы проверить. Но в 11.1 в модуле РаботаСФормуламиКлиентСервер нет вызова сервера. То есть, формула будет исполнена там, где вызван данный модуль. Перехода на сервер нет, а значит исполнения внешнего (по отношению к серверу) кода тоже нет. Все чисто.

    Беда, если у модуля стоит флаг ВызовСервера, а внутри выполнение переданного извне кода. В 11.1 такого нет.

    Reply ↓
  17. mxm2

    (17) Evil Beaver, 11.0.9.15: таки да…)

    Reply ↓
  18. LexSeIch

    Мир этому дому!

    В споре рождается истина. Интересно читать полемику — что то новое узнаешь, иногда даже и не в теме: «а база опубликована в веб, то любой человек может выполнять на вашем сервере произвольный 1С-код, просто передавая туда HTTP-запросы» (Evil Beaver) — второй раз за день читаю об очередной дырке… Сколько же их?

    Reply ↓
  19. Evil Beaver

    (19) LexSeIch, ну в случае модуля РаботаСФормулами, могу ошибаться, но там, насколько мне известно передается не чистый код, а некий псевдокод, который еще и синтаксическую проверку проходит. То есть, прямого выполнения нет. Так что вроде бы не все так печально.

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *