gifts2017

Вызов функции, размещенной во внешней обработке

Опубликовал Андрей Конев (Infector) в раздел Программирование - Практика программирования

Размещаем во внешней обработке функцию, умеющую возвращать вычисленные в ней значения.

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

//Наименование - имя обработки в справочнике
//Параметры вызова - передаваемые в обработку параметры
Функция ВызватьВнешнююОбработку(Наименование, ПараметрыВызова=неопределено) Экспорт

СсылкаНаОбъект = Справочники.ВнешниеОбработки.НайтиПоНаименованию(Наименование);

Если не ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
Сообщить("Обработка не найдена");
Возврат неопределено;
КонецЕсли;

ЭтоОбработка = ?(СсылкаНаОбъект.ВидОбработки = Перечисления.ВидыДополнительныхВнешнихОбработок.Обработка, Истина, Ложь);

Если НЕ ЭтоОбработка Тогда
Возврат неопределено;
КонецЕсли;

ИмяФайла = ПолучитьИмяВременногоФайла();
ДвоичныеДанные = СсылкаНаОбъект.ХранилищеВнешнейОбработки.Получить();
ДвоичныеДанные.Записать(ИмяФайла);

Попытка
Обработка = ВнешниеОбработки.Создать(ИмяФайла);
ЗначениеИзОбработки = Обработка.ВычислитьЗначение(ПараметрыВызова);
Исключение
Сообщить ("Выбранный файл не является внешней обработкой,
|поврежден, либо функция вызвана неверно.");
КонецПопытки;

УдалитьФайлы(ИмяФайла);
Возврат ЗначениеИзОбработки;

КонецФункции

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

Функция ВычислитьЗначение(ПараметрыВызова) Экспорт
//Выполняем полезные действия

Возврат ПолученноеЗначение;
КонецФункции

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Александр Лыткин (TrinitronOTV) 14.12.12 07:26
спасибо за полезную информацию
2. Александр Табаков (ryutao) 14.12.12 09:43
А вот интересно, насколько замедляет работу использование этой возможности? Самому попробовать пока нет никакой возможности из-за перманентного цейтнота. Информация очень полезна!
3. Александр Медведев (anig99) 14.12.12 10:09
4. Ярослав Радкевич (WKBAPKA) 14.12.12 10:45
(2) ryutao,
думаю, что не сильно быстро работает... хотя бы уже распаковать, положить на диск, потом удалить
5. Дмитрий Денисов (Uncore) 14.12.12 11:55
По-моему похожий синтаксис используется в типовых конфигурациях при печати внешних печатных форм.
6. Андрей Конев (Infector) 14.12.12 13:13
№5 - вы правы. Внешние печатные функции, а так же простые обработки и обработки заполнения табличных частей вызываются схожим образом: достали из баз файл - выполнили обработку - убрали мусор.

№2,4 - скорость работы вытекает из этого же. Что работать такое решение будет медленнее, чем внутри конфигурации сомневаться не приходится, но если вызов не идет в цикле, заметить разницу сложно. Итоговая потеря во времени, как и везде зависит в конечном итоге от степени оптимизации кода. Наглядно скорость одиночного вызова можно проследить на обработках заполнения табличных частей, механизм взаимодействия конфигурации с обработкой одинаков.
7. Алексей Роза (DoctorRoza) 14.12.12 16:53
Ну да, выглядит достаточно простенько, пустячково. С другой стороны, зачем усложнять? То, что тут используются внешние обработки - мера вынужденная. Так что, решение заслуживает внимания!
8. Anatolii Karasev (KapasMordorov) 14.12.12 17:00
Проще хранить в любом подходящием справочнике или регистре строковые значения и использовать "Выполнить".
9. andrewks 14.12.12 17:18
минус ставить не буду, и "пустячковость" тут ни при чём.
тормоза при массовом использовании очевидны, - это раз,
если можно менять конфу, то почему бы не включить нужные функции сразу в общий модуль? - это два
AlexeyFreeLife; Kuzja_R; +2 Ответить
10. andrewks 14.12.12 17:21
и потом, куда именно мы учим возвращать значение внешнюю обработку? в конфу? значит, мы её изменили? так в чём же дело, почему не включили в общий модуль нужные функции?
11. Андрей Конев (Infector) 14.12.12 17:59
andrewks
Попробую пояснить зачем это :)

Представьте себе, что ваш коллега занял Конфигуратор и отдавать вам в ближайшие пару часов не собирается. В это время Вы заняты приведением файла для обмена с совершенно чужеродной системой, которая за пределами Вашей фирмы вряд ли кому-то известна, в приличный вид. Код нужно менять с незавидным постоянством по 20 раз на день, а коллега в это время изменил нечто в реквизитах и без того, чтобы выгнать всех уже не обойтись. Прибавьте, что формат этой выгрузки и данные, которые в ней хотят видеть, тоже периодически притерпевает изменения.

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

В итоге преймущество только одно, но иногда оно важно - такую функцию можно подменить налету, без конфа и стонов от пользователей. Любое решение должно быть кроме всего прочего еще и адекватно задаче. Не слишком адекватно для разгрузки мешка картошки пригонять спецтехнику с одной стороны. С другой стороны неадекватно разгружать несколько вагонов на горбу, когда спецтехника уже есть под боком.
Аналогично дергать в цикле внешнюю функцию или обработку не очень разумно, но зато можно передать в нее одну коллекцию, объект или т.п. и это уже будет заметно быстрее, чем вызов функции для каждого отдельного элемента.
12. Евгений Сосна (pumbaE) 14.12.12 19:18
Ну будущее, делайте экспортную переменную "Версия" и проверяйте ее, очень бывает неудобно, когда в конфигурации уже изменили обработку, а в справочнике Внешние обработки забыли удалить.

p.s.: пометка на удаление тоже в вашем коде не проверяется.
p.s. p.s: проверка на права тоже, НайтиПоНаименованию ну никак не учитывает РЛС (если у вас УПП, то и РЛС должен быть включен на внешние обработки отчеты).
Infector; Yashazz; +2 Ответить
13. Яков Коган (Yashazz) 18.12.12 19:48
(11) Несколько советов.
1. Приведите в порядок ход работ. Вас послушать - ад кромешный, такие танцы на граблях надо не лечить обходными костылями, а ликвидировать. До добра не доведёт.
2. Заведите справочник "Алгоритмы", в нужных местах проложите ссылки на него. В алгоритмах, в их строковых реквизитах, представляющих исходный код 1С, в режиме "Предприятие" сможете править всё "на лету", и привязка смысловая тоже будет. У меня эта идея себя оправдала. Могу выложить или прислать подсистему с этим справочником, если хотите.
3. Универсальный Подбор И Обработку Объектов никто не отменял, там тоже очень многое можно делать.
rincewind; Infector; +2 Ответить
14. Владимир Чаклин (vec435) 19.12.12 09:09
хранение доп кода во внешней обработке - плюс очевиден : конфа не меняется,код можно менять на лету.но время загрузки самой обработки, копирование файла- все это время .хорошо бы поместить обработку во временноехранилище в начале сеанса ,хранить строку с адресом временногохранилища и обращаться уже ко временномухранилищу через эту строку
Infector; +1 Ответить
15. Андрей Конев (Infector) 19.12.12 14:29
pumbaE, Yashazz, vec435
Спасибо за советы :) Конструктивная критика всегда полезна. Мысль собрать в одной обработке несколько нужных функций и создавать файл один раз при начале сеанса уже возникала. А вот до хранения кода в справочнике не додумался, такое решение весьма интересно. Всегда есть что-то, что можно сделать лучше :)
16. Евгений Сосна (pumbaE) 19.12.12 14:33
Просто используй "Инструменты разработчика".
17. Дмитрий Кондратьев (dmitryrk) 19.08.15 22:58
Спасибо за тему. И вариант пригодится и дискуссия удачная для выбора решения.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа