Имя: Пароль:
1C
 
Глобальные переменные в контексте сервера
0 Kaidend
 
23.04.10
17:20
Всем привет.
Есть достаточно большой код (несколько общих модулей, десятки процедур и функций), опирающийся на использование глобальных переменных, объявленных в модуле приложения. Код выполняет обмен между базой 1С и системой Оптимум (мобильная торговля).

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

Можно, конечно, собрать все глобальные переменные в одну структуру и передавать их каждой процедуре при каждом вызове. Можно отказаться от регламентых заданий в пользу запуска bat-файла по расписанию планировщика ОС.

Но мне интересно - неужели нет никакого способа для "эмуляции" глобальных переменных на стороне сервера? Пусть бы они и жили только пока выполнялась бы "родительская" функция, запустившая некоторый процесс на сервере.
1 Stepa86
 
23.04.10
17:23
ПараметрыСеанса?
2 Kaidend
 
23.04.10
17:27
(1) Проблема в том, что эти глобальные переменные имеют тип структура и таблица значений. Параметры сеанса такой тип иметь не могут...
3 Господин ПЖ
 
23.04.10
17:29
>Есть достаточно большой код (несколько общих модулей, десятки процедур и функций), опирающийся на использование глобальных переменных, объявленных в модуле приложения.

за такие штуки eggs отбивать надо
4 nop
 
23.04.10
17:31
(3) не надо.
(2) ХранилищеЗначения ?
5 fisher
 
23.04.10
17:31
(2) Статическую коллекцию можно запихать в "ФиксированныйМассив"
С динамическими сложнее. Их можно паковать в "ХранилищеЗначений".
Но при частом использовании в цикле лучше дополнительно кэшировать на клиенте (паковка/распаковка довольно затратны по времени).
6 fisher
 
23.04.10
17:33
На 8.2 есть прикольный финт ушами через общие модуля с повторным использованием возвращаемых значений.
7 Kaidend
 
23.04.10
17:36
(3) Там глобальными переменными не злоупотребляют, их немного и они действительно нужны.

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

По всей видимости, буду таки исправлять вызовы процедур.
8 fisher
 
23.04.10
17:41
(7) И каким образом планируешь "исправлять вызовы процедур"?
Просто интересно...
9 Kaidend
 
23.04.10
17:43
(8) Ну я в (0) написал.

В стартовой процедуре объявлем структуру, добавляем туда элементы, ключи - названия наших глобальных переменных. Далее при каждом вызове процедуры эта структура передается "по цепочке", от вызывающей процедуры к вызываемой. В текстах самих процедур обращение к глобальной переменной на обращение к структуре можно будет заменить с помощью глобального поиска и замены.
10 fisher
 
23.04.10
17:56
(9) Дык а хранить твою таблицу между сеансами обмена где?
Каждый раз инициализировать?
11 Kaidend
 
23.04.10
18:06
(10) А табличку не надо хранить между сеансами обмена. Табличка - это протокол обмена, в конце обмена она преобразуется в табличный документ и сохраняется на диске.

Вообще, кажется, я нашел нормальное решение. Метод регламентного задания будет вызывать процедуру ЗапуститьСистему(), которая запустит 1С от имени специального пользователя и в качестве параметра запуска передаст имя настройки, по которой должен выполняться обмен. В обработчкие ПриНачалеРаботыСистемы() будет проверяться, от имени какого пользователя работаем, и, если это наш специальный пользователь, выполняем обмен по указанной настройке и завершаем работу системы.
12 fisher
 
23.04.10
18:12
(11) Ну ты извращенец. Использовать регламентное задание как виндовый шедулер - это цирк. Если между сеансами хранить не надо - делай как сразу решил. Передавай параметром между всеми процедурами обмена. Самое правильное решение.
13 Kaidend
 
23.04.10
18:20
(12) Можно и Win-планировщик использовать, вариант в (11) действительно не без изврата. Хотя что использование внешнего планировщика при наличии у 1С своего собственного, что передача в каждую процедуру при каждом вызове одного и того же аргумента - приемы одинаково кривые. Я еще подумаю, какой из них наименее кривой, его и выберу.

Жаль, что в 1С нет механизма, позволяющего использовать глобальные переменные в ходе одного "сеанса работы" сервера, не вижу для этого никаких принципиальных ограничений.
14 fisher
 
24.04.10
11:15
(13) "передача в каждую процедуру при каждом вызове одного и того же аргумента" - приём ни разу не кривой, а очень даже стандартный и правильный. Намного правильнее, чем использовать глобальные переменные. Почему сам догадаешься, или нужно классику перечитать?
15 Kaidend
 
24.04.10
12:08
(14) Ммм, смотрите, у меня есть потребность в трех переменных, которые были бы доступны в нескольких процедурах и функциях. Две из этих переменных нужны только одной функции, которая вызывается множеством других функций (можно было бы объявить ее с ключевым словом static, если бы 1С такое поддерживала), и одна переменная нужна многим функциям. Есть два варианта:

1) Объявить три глобальные переменные, присвоить им нормальный префикс, очищать их содержимое в начале и конце обмена. Это с вероятностью 99% исключит случайное изменение значения этих переменных и другие возможные ошибки, связанные с расширением глобального контекста.

2) "Изуродовать" вызов каждой процедуры передачей того, что она могла бы взять сама. Код станет "тяжелее" и избыточнее за счет увеличения числа формальных и фактических параметров и использования конструкций типа имяСтруктуры.ИмяПеременной вместо имяГлобПеременной.

А теперь объясните мне, пожалуйста, чем второй вариант лучше первого, кроме того, что он "стандартный", "правильный", "как в классике" и прочее пустословие? Нормальная классика, кстати говоря, учит думать и понимать, а не слепо следовать каким-то правилам.
16 Defender aka LINN
 
24.04.10
12:17
(15) "Нормальная классика, кстати говоря, учит думать и понимать, а не слепо следовать каким-то правилам." - ну, думай, понимай, смотри дальше в нерабочую конфигурацию.
17 Jolly Roger
 
24.04.10
12:21
(0) нужно, просто, "сконвертировать" общие модули в обработки...
18 Kaidend
 
24.04.10
12:23
(16) А с чего вы взяли, что она у меня нерабочая? Захотелось щеки лишний раз надуть?
19 Defender aka LINN
 
24.04.10
12:38
(18) То есть, у тебя код на сервере работает без проблем, да?
20 Kaidend
 
24.04.10
12:52
(19) А мне не нужно, чтобы код обязательно работал на сервере :) Мне главное, чтобы код работал по расписанию, а серверный процесс его будет выполнять или клиентский - мне не важно. Я в (15) вообще немного о другом писал.
21 Defender aka LINN
 
24.04.10
12:59
(20) Значит, у тебя нерабочая конфигурация.
22 Kaidend
 
24.04.10
13:16
(21) Т.е. моя конфигурация, реализуя весь требуемый от нее функционал, является нерабочей? Как там щеки, не лопнули еще?
23 Defender aka LINN
 
24.04.10
13:29
(22) Представь себе, нет. Твоя конфигурация не работает на сервере. В режиме внешнего соединения, я так понимаю, тоже. То есть, работать в ней можно только в клиентском режиме. Это не конфигурация уже получается, а кусок гуано.
У тебя, похоже, очень крепкая лобовая кость, раз стукнувшись об (0) ты продолжаешь считать, что что-то сделал правильно.
24 Kaidend
 
24.04.10
13:37
(23) Хуже того - моя конфигурация не готовит налоговую отчетность, не рассказывает пользователем анекдоты и не способна пилотировать космический корабль. Делает ли это ее "куском гуано"? Думаю, что нет. Она делает все то, что должна делать, а когда возникают новые потребности (как в (0)), то их можно реализовать. Может, решение будет не очень красивым, но конфигурация была и будет рабочей.
25 Kaidend
 
24.04.10
13:43
(23) Кстати, стукнувшись головой об (0) я понял, что использовать глобальные переменные в коде, который предположительно будет работать на сервере, в принципе нельзя.

Чего я не могу понять - какого черта вы вылезли в (16) с воплями о нерабочей конфигурации, когда я просто столкнулся со вполне решаемой сложностью и описал пути ее решения в (0)?

Хотя нет, я это тоже понимаю - обычное сочетание высокого самомнения, низкой культуры общения и, видимо, каких-то глубоких комплексов. Никак не могу приучить себя не реагировать на таких персонажей, ужасно раздражают ((
26 Defender aka LINN
 
24.04.10
13:49
(25) Скучно было, решил дятлов погонять. Раз понял, то хорошо, может что и получится.
27 Kaidend
 
24.04.10
13:57
(26) Проще говоря - поднять себе самооценку наиболее примитивным методом. Впрочем, я тоже получаю некоторое удовольствие от осаживания самоуверенных ослов, признаться.

Ладно, проехали. Можете что-нибудь написать, чтобы последнее слово осталось за вами, я не потружусь отвечать :)
28 acsent
 
24.04.10
14:03
Сделай обработку, там можно сколь угодно "глобальных" переменных использовать
29 Kaidend
 
24.04.10
14:09
(28) Я уже сделал запуск клиентского сеанса по расписанию.
Использовать обработку не хотелось бы потому, что код в общих модулях разделен по выполняемой задаче, ориентироваться потом в одном объединенном модуле будет сложнее. Была бы возможность создавать несколько модулей в одной обработке - так бы и сделал.
30 acsent
 
24.04.10
14:11
(29) Несколько обработок
31 acsent
 
24.04.10
14:11
(29) Тогда уж лучше через обработку ожидания
32 Kaidend
 
24.04.10
14:16
(30) Несколько обработок нужно увязывать между собой, т.е. код перетряхивать.

(31) Чем лучше?
33 acsent
 
24.04.10
14:17
(32) Нужно запустить только 1 сеанс. Так делаяются онгламентные задания в файловых версиях
34 fisher
 
24.04.10
14:59
(15) Ничего уродовать не надо. Создаешь одну структуру с именем "КонтекстСеансаОбмена" (к примеру) и используешь в параметрах нужных тебе функций.
35 fisher
 
24.04.10
15:45
(34) +
Теперь на пальцах, чем такой вариант лучше (раз классики мы не знаем, но следовать ей заранее не хотим).
1) конфликты пространств имен и прочие трудновыловимые ошибки связанные с использованием глобальных переменных исключаются В ПРИНЦИПЕ и НАВСЕГДА. А не "на сейчас", пока ты всё помнишь и в голове держишь.
2) читабельность/сопровождение процедур, использующих только данные из своих параметров (это называется инкапсулированность) намного выше. Ибо совершенно постороннему человеку (читай, тебе же через годик) будет достаточно одного взгляда на заголовок процедуры, чтобы понять, что она использует какой-то "КонтекстСеансаОбмена". Что это, где и как инициализируется - тут же в момент выясняется. Дальше можно вообще не смотреть - в большинстве случаев достаточно понять, что на входе и на выходе. А вот то, что внутри используются не пойми какие глобальные переменные, влияющие на её работу - нихрена не очевидно.