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

При работе в режиме управляемого приложения, иногда на клиентской стороне приходится получать результат "элементарного выражения", вычислить которое можно только на сервере. В "классической" реализации это может приводить к обилию сдвоенных процедур/функций (одна на клиенте — вызывает другую на сервере). В статье рассмотрены 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 не будет опубликован. Обязательные поля помечены *