No Image

Используется вызов контекстного серверного метода формы

СОДЕРЖАНИЕ
16 просмотров
05 мая 2020

При выборе ссылочного значения в поле ввода иногда возникает необходимость специальным образом обработать выбирамемое значение. Например, в документе нужно выбрать поставщика. Но нужно вмешаться в процесс выбора значения и кроме ссылки на поставщика получить еще и другую информацию о поставщике. Например, его полное наименование и ИНН, которые являются реквизитами поставщика.

Для того, чтобы вмешаться в процесс выбора значения используется событие ОбработкаВыбора элемента формы Поле . Это событие поставляется расширением поля ввода. Обработчик этого события имеет такой синтаксис:

В параметре ВыбранноеЗначение платформа передает в обработчик то значение, которое выбрал пользователь. В данном случае это будет ссылка на поставщика. Но проблема заключается в том, что обработчик ОбработкаВыбора исполняется на клиенте. А на клиенте возможности ссылки очень сильно ограничены. В частности, от нее нельзя через точку получить значения реквизитов.

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

При этом следует иметь ввиду два момента:

  • Во-первых, для получения реквизитов используется неконтекстный серверный вызов ( &НаСервереБезКонтекста ). Это важно, т.к. в этом обработчике нельзя использовать контекстные серверные вызовы ( &НаСервере ).
  • Во-вторых, любое обращение к серверу требует дополнительных ресурсов системы и может замедлять работу пользователя, особенно в случае подключения по низкоскоростному каналу связи. Поэтому нужно прежде всего внимательно оценить, а так ли необходимо в этом месте получать реквизиты ссылки или можно обойтись без этого? И если нужно получать несколько реквизитов и при этом используется какой-то сложный алгоритм — нужно постараться реализовать его так, чтобы все необходимые данные получить за один серверный вызов, вернуть их на клиента и на клиенте только поместить их в нужные поля формы, не проводя каких-то сложных вычислений.

Справка

  • ВыбранноеЗначение , тип Произвольный . Результат выбора в подчиненной форме. В случае множественного выбора возвращается массив выбранных значений.
  • ИсточникВыбора , тип Произвольный . Форма, где осуществлен выбор.
  • Возникает на клиенте при выборе объекта в одной из подчиненных форм или при вызове в одной из подчиненных форм метода ОповеститьОВыборе .
  • ЗначениеВыбора , обязательный, тип Произвольный . Результат выбора.
  • Посылает оповещение владельцу формы о выполнении выбора или подбора, передает ему выбранное значение. Закрывает форму в соответствии со значением свойства ЗакрыватьПриВыборе . Данное действие аналогично выполнению выбора в форме, открытой для выбора в поле ввода или ячейке табличного поля.
  • Тонкий клиент, веб-клиент, толстый клиент, мобильное приложение (клиент).
  • Может применяться в случае, когда открытие формы выбора или подбора выполнено средствами языка.
Читайте также:  Как определить разрядность двоичного кода

Ни разу не постил на Хабр, а тут такой интересный повод нарисовался.

Вопросы, обсуждаемые в статье:

  • Выбрать публичность или приватность — вот в чем вопрос;
  • Кто главнее — клиент или сервер?
  • Прочтите статью и вы увидите, как на эти вопрос отвечает 1С в своей платформе;
  • И еще неожиданный интересный факт о Google узнают те, кто дочитает до конца;
  • Я кратко расскажу, как я нашел точного виновника бага.

Сразу скажу, что я любитель находить баги, а баги любят находить меня. И 13 число в моей жизни играет не последнюю роль.

История

Итак, сижу я вечером (на дворе как раз 13 декабря), тружусь над одним из своих любимых продуктов xUnitFor1C над значимым релизом 4.0

Тестирую работу тестов в режиме управляемого приложения при переходе с клиента на сервер и обратно.

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

В модуле контекста ядра тестирования (Упр.форма) созданы 2 похожих метода ВыполнитьТестовыйМетодНаКлиенте (признак &НаКлиенте) и ВыполнитьТестовыйМетодНаСервере (признак &НаСервере).
Назначение их понятно из названия.

Обычно в тесте я использовал метод УпрФорма.ВыполнитьТестовыйМетодНаКлиенте для проверки тестов УФ, т.е. через контекст управляемой формы.

Все штатно, проблем нет.

Но теперь мне понадобилось проверить переход с клиента на сервер. Я решил, что хватит использовать ВыполнитьТестовыйМетодНаКлиенте, пора заняться более глубоким хакингом и вызвал метод ВыполнитьТестовыйМетодНаСервере.

Написал специальный тест, описал поведение согласно сценария и внутри теста вызываю ЭтаФорма.ВыполнитьТестовыйМетодНаСервере.

Тест предсказуемо падает, ведь я работаю по методике TDD. Начинаю разбираться, что нужно поправить в коде, чтобы тест заработал (ТДД работает именно так).

Проходит несколько минут, и я с огромным изумлением вижу, что вызываемой мной метод ВыполнитьТестовыйМетодНаСервере является приватным, т.е. у него нет признака Экспорт!

При этом я его успешно вызываю, и он прекрасно отрабатывает.

Поиск и подтверждение бага в платформе 1С

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

Читайте также:  Keyboard error or no keyboard present

Сначала я проверил, вызываю я правильный код из правильного места и т.д. Еще через пару минут я убедился, что ошибки нет, действительно, я вызываю приватный метод и он успешно отрабатывает!

Также я проверил, что метод ВыполнитьТестовыйМетодНаКлиенте является публичным/экспортным методом.

Согласно методикам поиска багов я максимально упростил ситуацию и исключил сторонние факторы:

создал отдельную внешнюю обработку. Добавил к ней простую управляемую форму.
Добавил 2 команды ВызовПриватногоКлиентскогоМетода и ВызовПриватногоСерверногоМетода
Для этой формы добавил следующий код:

Первоначально я запускал подобный ручной тест на свежайшей версии 8.3.7.1805 (выпущена 10.12.2015, если я не ошибаюсь).

Получаю поведение:

  • приватный серверный метод успешно вызывается, сообщения отрабатывают. Это ошибка.
  • с приватным клиентским методом проще. Выдается правильное исключение, что метод не обнаружен.

<Форма.Форма.Форма(15)>: Метод объекта не обнаружен (ПриватнаяНаКлиенте)
ЭтаФорма.ПриватнаяНаКлиенте();

В итоге получаем явный баг в 8.3.7.

Далее я согласно тем же методикам поиска багов проверяю поведение на другой платформе 1С 8.2.19
Поведение абсолютно такое же.

Проверил поведение на встроенной обработке, те же проблемы.

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

Риторические вопросы

  • Получается, это не баг, это фича, потому что подобное «странное» поведение наблюдается очень давно, уже несколько лет?
  • А как же приватность/публичность? это же базовые принципы!
  • А как же инкапсуляция? получается, что кто угодно может вызвать скрытые серверные методы и нарушить поведение.
  • А как же равноправие? почему клиент настолько ущемлен по сравнению с сервером 🙂 ?

В итоге этот баг сделал мой вечер!

Надеюсь, и вам понравилась указанная багофича.

Ух, как теперь можно развернуться кодерам на языке 1С, теперь можно экспорт не писать, все и без него работает.
Это же сколько кода можно наваять, если не тратить время на написание Экспорт! А в масштабах страны какая экономия времени?

А если более серьезно, то хочется обратиться к 1С для исправления данной ошибки.
Евангелист 1С PeterG, что скажешь?
Также предлагаю встроить в продукт АПК (Автоматизированная проверка конфигурации) проверку на подобный баг.

PS Если кому-то нужно, могу дать обработку для ручного тестирования.

PPS А если кому интересно, что же нового будет в версии 4.0 xUnitFor1C, ждите следующей статьи и новогоднего подарка!

Читайте также:  1С интерактивный табличный документ

1. Платформа 1С:Предприятие позволяет передавать управление из клиентского в серверный код модуля формы двумя способами: контекстно и внеконтекстно.

При внеконтекстной передаче управления на сервер передаются только те данные, которые явно специфицированы разработчиком в параметрах процедуры (функции) с директивой компиляции &НаСервереБезКонтекста.

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

2. Контекстную передачу управления следует использовать в случаях когда:

  • платформа 1С:Предприятие самостоятельно оптимизирует объем передаваемых данных между клиентом и сервером (в обоих направлениях). Прежде всего, это реквизиты формы с табличными документами и коллекции элементов (ДанныеФормыКоллекция, ДанныеФормыСтруктураСКоллекцией, ДанныеФормыДерево). См. также: Использование объекта ДанныеФормыКоллекция.
  • и при этом затраты ресурсов сервера на инициализацию контекста формы оправдываются существенным снижением трафика между клиентом и сервером и снижением числа вызовов сервера.

В остальных случаях рекомендуется использовать внеконтекстную передачу управления с клиента на сервер.

3. При передаче управления с клиента на сервер недопустимо использовать объекты типов ДанныеФормыСтруктура, ДанныеФормыКоллекция, ДанныеФормыСтруктураСКоллекцией, ДанныеФормыДерево и ТабличныйДокумент в качестве параметров функции, передаваемых по значению. При передаче таких типов по значению с клиента на сервер всегда передается полная копия объекта, а не только измененные данные.
Вести работу с этими типами следует на сервере, для чего переходить с клиента на сервер с помощью явного контекстного вызова сервера.
Например, неправильно:

Приложение

При контекстной передаче управления на сервер в платформе 1С:Предприятие действуют следующие правила передачи измененных данных формы между клиентом и сервером:

  • значения реквизитов формы типа ДанныеФормыСтуктура передается целиком, в случае если изменился хотя бы один из его реквизитов;
  • для объектов, представленных типами ДанныеФормыКоллекция (ДанныеФормыСтруктураСКоллекцией, ДанныеФормыДерево) изменения учитываются с "точностью" до каждого элемента коллекции – передаются только измененные элементы. При этом измененные элементы коллекций передаются целиком. См. также: Использование объекта ДанныеФормыКоллекция.
  • для объектов типа ТабличныйДокумент передаются только измененные области;
  • объекты типа ДинамическийСписок не передаются.
Комментировать
16 просмотров
Комментариев нет, будьте первым кто его оставит

Это интересно
No Image Компьютеры
0 комментариев
No Image Компьютеры
0 комментариев
No Image Компьютеры
0 комментариев
Adblock
detector