Использование программных перечислений, ч.1: строковые константы

06.10.22

Разработка - Механизмы платформы 1С

Часто ли у вас возникает необходимость в коде выполнять сравнение на строку?

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

 
 1. Концепция
 
 2. Примеры использования

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

  • Ленивой инициализации - расчет значения будет выполнен только один раз - при первом обращении (см. вики)

  • устранению дублирования кода

  • повышению читабельности кода

Продолжение здесь Программные перечисления, ч.2: приемы кэширования при разработке

См. также

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    3643    dsdred    48    

66

Как готовить и есть массивы

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Все мы используем массивы в своем коде. Это один из первых объектов, который дают ученикам при прохождении обучения программированию. Но умеем ли мы ими пользоваться? В этой статье я хочу показать все методы массива, а также некоторые фишки в работе с массивами.

24.01.2024    5045    YA_418728146    25    

62

Планы обмена VS История данных

Обмен между базами 1C Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    6175    dsdred    36    

110

1С-ная магия

Механизмы платформы 1С Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    18206    SeiOkami    46    

116

Дефрагментация и реиндексация после перехода на платформу 8.3.22

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    11785    human_new    27    

72

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    8569    YA_418728146    6    

139

Внешние компоненты Native API на языке Rust - Просто!

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    6207    sebekerga    54    

93

Все скопируем и вставим! (Буфер обмена в 1С 8.3.24)

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    15554    SeiOkami    31    

103
Вознаграждение за ответ
Показать полностью
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. VitaliyCeban 461 12.12.16 12:31 Сейчас в теме
Хорошее решение, разве что только скобки () глаза мусолят, но это терпимо.
Вот бы сделали "свойства", как в C#. С виду, обычные поля, а на деле - методы.
Хотя, если уж вносить изменения в встроенный язык 1С, то относительно этой задачи, надо сразу enum'ы делать.
dj_serega; demkonst; +2 Ответить
6. alex-l19041 8 12.12.16 17:16 Сейчас в теме
(1)
Хорошее решение
- можно уточнить о чем идет речь ? (обсуждается какая-то публикация ?)
7. unichkin 1559 12.12.16 17:26 Сейчас в теме
Что-то на ИС с комментариями, не видел (1) и (2)
(1) Ну да, мозолят) Идея использовать структуру для этих целей и появилась после того как прочитал чей-то коммент про отсутствие таких вещей в 1С, там тоже человек с любовью С вспоминал)
(6) я так понимаю, текущая ;)
78. Snouphruh 29.12.22 13:25 Сейчас в теме
(7) я не использую структуру для кэширования. вместо структуры я использую соответствие. в соответствии поиск нужного значения работает быстрее.
77. Snouphruh 29.12.22 13:20 Сейчас в теме
(1) в С# типы - это своего рода классы, в которых изначально прописаны все эти методы и свойства.
а язык 1С - это пародия на ООП, своего рода имитация.
2. пользователь 12.12.16 12:35
Сообщение было скрыто модератором.
...
3. CyberCerber 851 12.12.16 14:06 Сейчас в теме
Главная проблема, что для этого перечисления не сработает контекстная подсказка. Т.е. все равно придется идти и смотреть, какие значения бывают, копировать, вставлять...
Ali1976; dabu-dabu; TeMochkiN; AnderWonder; jaroslav.h; rpgshnik; demkonst; NN2P; pikachu94; TreeDogNight; minimajack; Yakud3a; Zhilyakovdr; 7OH; Krio2; Danila-Master; herfis; kraynev-navi; tormozit; mindcannon; +20 Ответить
79. Snouphruh 29.12.22 13:31 Сейчас в теме
(3) сработает, если использовать хитрость.

ВидыОпределенияКонтрагента = ВидыОпределенияКонтрагента();
СвойстваИсточника = СвойстваИсточника();

#Если Сервер И Не Сервер Тогда
ВидыОпределенияКонтрагента = Новый Структура;
СвойстваИсточника = Новый Структура;
#КонецЕсли

4. JohnGalt 57 12.12.16 16:56 Сейчас в теме
Актуальная проблема. Исходя из собственного опыта, лучше все настройки, в том числе и сравнения "повесить" на пользователя. Назначить ответственных за механизмы/процессы. Для этого лучше всего сделать справочник или несколько с набором реквизитов/табличных частей для различных настроек. И настройки получать, например, ПриНачалеРаботыСистемы()
5. unichkin 1559 12.12.16 17:12 Сейчас в теме
(4) Ну, тут речь не совсем об этом. Вам к уже введенным настройкам надо как-то обращаться в коде. То что должен быть момент передачи ответственности - полностью согласен, как и с тем что лучше такое реализовать пользовательской настройкой. Только имхо, это не взлетит в 90% случаев фикси. Но это уже тема для отдельной беседы)
8. v3rter 12.12.16 17:29 Сейчас в теме
автор забыл ссылку на публикацию http://infostart.ru/public/566908/ ?
9. корум 287 12.12.16 17:35 Сейчас в теме
(8) это скорей не автор забыл, а движок инфостарта заглючил...
14. unichkin 1559 12.12.16 19:20 Сейчас в теме
(8)(10) не понял вопросов?
(11) Любую коллекцию параметров удобно так использовать - посмотрите последний пример с планом счетов. В примере - сравниваются значения структуры. Ну добавьте такой элемент:
СтруктураСтатусыЗаявок.Вставить("ТоварВПути"    , "Товар в пути");
10. v3rter 12.12.16 17:49 Сейчас в теме
Если взять не общий случай - ветвление кода, а частный - выбор набора параметров или макета, то чем плох обыкновенный справочник?
11. shurik_shurik 12.12.16 17:57 Сейчас в теме
Это очень хорошо, если во входящем файле статусы заявок без пробелов записаны. А если с пробелами, как тогда поступать?
Идея конечно интересная.
37. IvSchekin 22.03.18 08:44 Сейчас в теме
(11) не надо останавливаться на приведению к какому то регистру, надо еще удалять крайние пробелы и заменять два пробела на один дважды, тогда строка боле менее приводится к нормальному виду.
Selena--1; +1 Ответить
12. пользователь 12.12.16 17:57
Сообщение было скрыто модератором.
...
13. herfis 496 12.12.16 18:16 Сейчас в теме
Честно говоря, профита не так много как хотелось бы.
Но уже одно то, что в рантайме упадет сразу в том месте, где была ошибка в названии перечисления, дорогого стоит.
Т.е. в сложных случаях имеет смысл использовать. В простых - вряд ли.
ixijixi; 7OH; zqzq; +3 Ответить
15. unichkin 1559 12.12.16 19:35 Сейчас в теме
(13) Основной профит - в удобной структуре кода. Кроме того, автоматически получается оптимизация - в том смысле что коллекция параметров не будет рассчитываться по 10 раз подряд. Неоднократно видел как люди в цикле пишут что-то вроде сч70_1_1 = ПланыСчетов.Хозрасчетный.НайтиПоКоду("70.1.1").
В каких случаях использовать - я теперь только так работаю, если есть несколько строковых констант, даже не задаюсь вопросом "надо ли". Это похоже на рассуждение: "зачем оформлять код по правилам ИТС, для своей разовой доработки?" - т. е. человек не понимает зачем вообще его нужно оформлять, не видит в чем удобство. Я например даже для небольших работ все оформляю - это копейки времени, которые окупаются с лихвой если из разовой доработки понадобится ваять что-то серьезное, или передать кому-то на анализ, или вспомнить что делалось через полгода. Это на подкорке. Чтобы я забыл код оформить - никогда такого не было. Также и здесь. Но это конечно мое "имхо")
Garik8866; Артано; for_sale; uncle_Vasya; nihfalck; +5 Ответить
17. herfis 496 13.12.16 10:20 Сейчас в теме
(15) "Основной профит - в удобной структуре кода". Не согласен. "Структура кода" удобнее не становится. Я не про счета и кэширование (это уже несколько про другое), а про саму идею программных перечислений. В плане удобства - получаем сомнительный аргумент "красивенько" против дополнительного времени на реализацию и въезжание постороннего программиста в этот код. Вот своевременное падение в рантайме для легкого поиска ошибки - это профит. Если бы во время компиляции ругалось - это вообще был бы всем профитам профит. А если бы еще и автокомплишн в конфигураторе - практически полноценные перечисления бы вышли.
AnderWonder; zqzq; uncle_Vasya; 7OH; +4 Ответить
18. unichkin 1559 13.12.16 11:05 Сейчас в теме
(17) Именно в нем. "Тупой код с хорошей структурой, лучше чем тупая структура с гениальным кодом". Про время на реализацию - расхожее заблуждение. Дровосек рубит деревья, у него спрашивают - мужик, че ты мучаешься, у тебя ж топор тупой. Наточи топор. А он отвечает: "мне НЕКОГДА! мне надо РУБИТЬ". И все "рубят". Код должен читаться как книга.
По приоритету, для меня так:
- "въехать" в это можно достаточно быстро
- при этом можно быть уверенным что коллекция заполняется только в одном конкретном месте, благодаря использованию фиксированной структуры
Sanario; MTK_Rosberg; Артано; for_sale; uncle_Vasya; borrman; +6 Ответить
16. vasilev2015 2677 13.12.16 10:15 Сейчас в теме
Может, лучше использовать соответствие ?
Синтаксис похожий, плюшек больше.
Подходит для больших списков.
mvxyz; ixijixi; vvirus; +3 Ответить
19. unichkin 1559 13.12.16 11:06 Сейчас в теме
(16) Используйте то, что вам удобнее) Но соответствие не выдаст исключения при получении отсутствующего значения, а вернет неопределено. У него несколько иное назначение, чем у структуры.
for_sale; sulfur17; +2 Ответить
20. =Kollega= 3 13.12.16 14:39 Сейчас в теме
Идея хорошая, но все же ИМХО лучше один раз вызвать функцию и вернуть в локальную переменную структуру и работать с ней, чем 10 раз вызывать и проверять, проиницилизирована ли нужная нам структура.
Но это так просто придирка, хотя когда подобных структур будет достаточно много (хотя я даже не представляю себе род такой задачи), поиск и копирование структур может стать достаточно ощутимым.
for_sale; m_sb; ixijixi; +3 Ответить
21. herfis 496 13.12.16 16:19 Сейчас в теме
(20) Тут как раз все в порядке.
Во-первых, ленивая инициализация - это само по себе хорошо.
Во-вторых, явная инициализация на старте - это еще одна "точка привязки" в коде для реализации этой концепции. Абсолютно лишняя.
ЗЫ. Поиск в структуре по ключу не должен стать ощутимым, даже если ключей будет много. Если я правильно помню - это хэшированная структура данных. Ну, разве что свопить начнет :) А копирования тут нет.
22. PLAstic 295 13.12.16 18:08 Сейчас в теме
Не имею возможности изучить каменты. А автору уже намекнули на то, что надо вынести инфу в табличный макет и грузить соответствия из него?
23. DrAku1a 1678 14.12.16 09:40 Сейчас в теме
Мне кажется, что автор начиная со первого примера "СтруктураСтатусыЗаявок" забыл про своё-же замечание: (буква "О" <> "о").
ehoes; корум; belchonokh; klinval; dimk@a; +5 Ответить
26. unichkin 1559 14.12.16 13:10 Сейчас в теме
(23)
Мне кажется, что автор начиная со первого примера "СтруктураСтатусыЗаявок" забыл про своё-же замечание: (буква "О" <> "о").
- не вижу ошибки, ткните пальцем если не сложно.
(24) Я думаю, если дорабатываете конфу - то добавьте нормальное перечисление.
Этот способ хорош для константных значений, уникальных в каком-то определенном алгоритме (внешнем или внутреннем). Например - статусы заявок приходят к нам в виде текста. Но в конфигурации это наверняка перечисление. Здесь структура нужна только для того, чтобы удобно и качественно проверять все входящие значения статусов.
Еще пример с потолка (кривая методология, просто чтобы отразить суть вопроса): скажем в документе оператор заполняет строковое поле "Причина отказа". Причина может вводиться как из заранее определенного списка, так и произвольно - если установлен соотв. флаг. Так вот - если не добавлять в конфигурации нормальное перечисление (а лучше добавить, сделав "причину" составным полем), то да, наверное логично так сделать. Только модуль ПовтИсп хранит кэш 20 минут. Возможно лучше использовать какие-то существующие кэши конфигурации. И "мСтруктураКэшПрограммныхПеречислений" не будет нужна только для этого конкретного случая.
(25) Если рассуждать только с позиции загрузки заявок - то конечно, да, лучше дать на откуп пользователю. А еще лучше проговорить это все в ТЗ. Потом при формировании структуры перечисления собрать данные из таблицы формы - да, логично, почему нет. Но загрузка заявок - это ведь частный случай, я его использовал для примера. У меня например была задача, в которой я создавал программное перечисление для событий журнала регистрации. Т.е. было примерно так:
СтруктураСобытийЖурнала = Новый Структура();
СтруктураСобытийЖурнала.Вставить("НачалоСеанса", "_$Session$_.Start");
СтруктураСобытийЖурнала.Вставить("КонецСеанса", "_$Session$_.Finish");
СтруктураСобытийЖурнала.Вставить("Проведение", "_$Data$_.Post");
// ну и т. д.

Потом для фильтров использовал СобытияЖР().Проведение и т.п.
Артано; корум; sulfur17; +3 Ответить
24. sulfur17 59 14.12.16 11:44 Сейчас в теме
А можно функцию СтатусыЗаявок() разместить в глобальном общем модуле с повторным использованием возвращаемых значений на время сеанса?
Тогда и переменная мСтруктураКэшПрограммныхПеречислений не нужна и можно будет использовать СтатусыЗаявок() в других модулях.

Например если я хочу передать СтатусыЗаявок().Отказ в качестве параметра из другого модуля, то в другом модуле функцию СтатусыЗаявок() не видно. А если разместить ее в глобальном модуле, то будет видно.
unichkin, Что об этом думаете?
25. корум 287 14.12.16 11:55 Сейчас в теме
(0) Более другой вариант.
Заполнять такие перечисления в таблицы на форме, проводить программное сопоставление, окончательную корректировку оставлять пользователю.
Обработку данных производить с учетом полученных таблиц соответствий (количество значений в которых неопределено и разработчика не волнует - он работает со стандартным справочником/перечислением из соответствия)

в таком варианте снижается требование к качеству заполнения таблицы для загрузки.
тавар ф пути
номенклатуро в перевозке
и ТоварВпути

обработаются одинаково корректно.
27. German_Tagil 42 15.12.16 07:58 Сейчас в теме
28. vlad.frost 186 15.12.16 09:35 Сейчас в теме
Если инвертировать проверку свойства в мСтруктураКэшПрограммныхПеречислений, то это позволит уменьшить уровни вложенности и код будет читаться легче. Сравните:

Функция СтатусыЗаявок()
	
	Если мСтруктураКэшПрограммныхПеречислений.Свойство("СтатусыЗаявок") Тогда		
		Возврат мСтруктураКэшПрограммныхПеречислений.СтатусыЗаявок;
	КонецЕсли;

	СтруктураСтатусыЗаявок = Новый Структура;
	СтруктураСтатусыЗаявок.Вставить("НаУтверждении", "НаУтверждении");
	СтруктураСтатусыЗаявок.Вставить("ТоварвПути", "ТоварВПути");
	СтруктураСтатусыЗаявок.Вставить("КОтгрузке", "КОтгрузке");
	СтруктураСтатусыЗаявок.Вставить("Отказ", "Отказ");
					
	мСтруктураКэшПрограммныхПеречислений.Вставить("СтатусыЗаявок", Новый ФиксированнаяСтруктура(СтруктураСтатусыЗаявок));
	
	Возврат мСтруктураКэшПрограммныхПеречислений.СтатусыЗаявок;
		
КонецФункции
Показать
Egovigor; TeMochkiN; Daruma; ValentinGushchin; dj_serega; +5 Ответить
29. unichkin 1559 15.12.16 10:09 Сейчас в теме
(28) Я обычно стремлюсь к сокращению "Возвратов", если можно рассчитать значение внутри функции и вернуть результат в конце метода - так и делаю; приведенный вами код не кажется мне более читабельным решением, может дело вкуса. Делайте как вам удобнее) Я останусь при своем.
Кстати, сейчас подумал - что в функциях обычно минимизирую возвраты, а в процедурах как раз наоборот - если есть условие прерывания, стараюсь выполнить его в самом начале, чтобы не использовать лишних расчетов.
30. vlad.frost 186 15.12.16 13:54 Сейчас в теме
(29) Единая точка выхода, ага, нас тоже так в школе учили. Но если уж вы предлагаете способы, как улучшить читаемость кода, идите дальше. Согласен, в приведённом мной примере данное изменение не сильно улучшит читаемость, но примените его к вашей функции ИспользуемыеСчета(), и там такое улучшение будет уже более актуально. Матчасть: Замена вложенных условных операторов граничным оператором.
ValentinGushchin; +1 Ответить
31. unichkin 1559 15.12.16 16:41 Сейчас в теме
(30) Да нет в "ИспользуемыеСчета()" ветка условия всего одна, так что принцип тот же что и в (29). То, что описывает приведенная вами статья я стараюсь соблюдать, и это как-то всегда на уровне спинного мозга осознавал - что не стоит допускать дебрей Case-Of Если-Тогда. Однако за наводку и интерес к моей статье - спасибо)
Мне в данном конкретном случае кажется более логичным заполнять структуру именно внутри условия. Возможно потому, что основные цели этих методов (для вызова программного перечисления) - это заполнение соотв. кэша, и более логично в начале алгоритма видеть инициализацию коллекции по условию ее отсутствия. Тут с т.з. рефакторинга было бы неплохо вынести код по заполнению структуры счетов в внешний метод, но я не люблю перегружать программный интерфейс методами (пусть даже и служебный). Т.е. использоваться -то он будет все-равно только в одном месте. Вот если его глобальным сделать, тогда другое дело. Было бы нечто вроде такого:
Функция ИспользуемыеСчета()
	
	Если НЕ мСтруктураКэшПрограммныхПеречислений.Свойство("ИспользуемыеСчета") Тогда
		СтруктураИспользуемыеСчета = Новый Структура;
		
		// Чтобы добавить счет, добавьте сюда его код
		СтрокаКодовСчетов = "10, 10.3, 19, 60.1, 60.2, 62, 51, 51, 70, 70.1, 76.АВ, 90, 90.01, 90.02";
		СтруктураИспользуемыеСчета = ОбщегоНазначенияБП.СтруктураСчетовПоСтрокеКодов(СтрокаКодовСчетов );

		мСтруктураКэшПрограммныхПеречислений.Вставить("ИспользуемыеСчета", Новый ФиксированнаяСтруктура(СтруктураИспользуемыеСчета));
	КонецЕсли; 	
	
	Возврат мСтруктураКэшПрограммныхПеречислений.ИспользуемыеСчета;
	
КонецФункции
Показать
32. neikist 29.12.16 20:38 Сейчас в теме
Понимаю что поздновато отписываюсь, но как вам такой вариант?

#Область ПрограммноеПеречисление_СтатусыЗаявок

Функция _СтатусыЗаявок_НаУтверждении()	Возврат "НаУтверждении"	КонецФункции
Функция _СтатусыЗаявок_ТоварВПути()		Возврат	"ТоварВПути"		КонецФункции
Функция _СтатусыЗаявок_КОтгрузке()			Возврат	"КОтгрузке"		КонецФункции
Функция _СтатусыЗаявок_Отказ()			Возврат	"Отказ"			КонецФункции


#КонецОбласти

Функция ДанныеФайлаУспешноСчитаны() Экспорт
	
	//...
	СтатусЗаявки = СокрЛП(Excel.Cells(1, Сч).Text);

	Если СтатусЗаявки = _СтатусыЗаявок_НаУтверждении() Тогда
		//...		
	ИначеЕсли СтатусЗаявки = _СтатусыЗаявок_ТоварВПути() Тогда
		//...		
	ИначеЕсли СтатусЗаявки = _СтатусыЗаявок_КОтгрузке() Тогда	
		//...		
	КонецЕсли; 

	Возврат Истина; 		
	
КонецФункции
Показать



Плюсы:
1. Можно использовать в формах &НаСервере, вместо того чтобы каждый раз инициализировать переменную после клиента;
2. Есть автодополнение и контекстная подсказка;
3. Если даже набрать имя функции неправильно - ошибка всплывет на этапе синтаксической проверки (при отладке вашего способа не всегда может получится все ветки прогнать, и до ветки с ошибочно набранным значением можно не добраться)
4. По идее возвращаемое значение таких функций должно "инлайниться" в место использования, так что производительность должна быть такая же как при обычном сравнении со значением, а если и нет то что у меня, что у Вас накладные расходы на вызов функции так или иначе идут.

Минусов с ходу могу назвать только два:
1. Засорение контекстной подсказки, для чего и добавил в начало _;
2. Такое "перечисление" не передашь в другой модуль, разве что вместе со всем текущим контекстом (ЭтотОбъект придется передавать из общего модуля или формы) и делать данные функции экспортными.
33. unichkin 1559 29.12.16 23:51 Сейчас в теме
(32)
1. Объявляете реквизит формы "СтруктураКэшПрограммныхПеречислений", с произвольным типом реквизита... А остальное все то-же) Это если для формы. Вообще правильнее все-же к форме относить то, что касается *формы* - интерактив, все расчеты лучше отправлять на сервер, т.е. в модуль объекта. Ну тут можно много рассуждать и говорить - по всякому можно. Если говорим о внешней обработке можно сделать реквизит обработки произвольного типа - он будет доступен и с сервера и с клиента. Если о объекте конфигурации - сделайте реквизит формы. Или - вызов из модуля ПовтИсп.
2. Если учесть что различие только в префиксе - имхо, не очень удобно для набора, когда много коллекций.
С моей точки зрения, когда перечисление обосабливается в свой метод - это и нагляднее и удобнее. Ну да, синтакс контроль не заругается. Пишите аккуратнее) Каждому свое конечно, используйте то что вам больше подходит. Но мне с таким кодом было бы работать тяжеловато. Подчеркивание в начале метода - это нарушение правил образования имен переменных. Ну и плюшки с ленивой инициализацией теряются.
Vortigaunt; +1 Ответить
34. tailer2 20.01.17 18:31 Сейчас в теме
>через предопределенный список элементов плана счетов, т.е. туда надо провалиться, найти код счета, скопировать имя... - долго

на этот случай имена счетов сохранены в отдельном файлике, открыл, скопипастил
35. SergeyFirst 70 19.09.17 12:05 Сейчас в теме
Красиво и лаконично! Молодца!
36. Tapochki-tmn 43 22.03.18 08:26 Сейчас в теме
Возможно, я чего-то не понял, но мне кажется в коде примера использования ошибка.

Строка "ВидОпределенияКонтрагента = ВидыОпределенияКонтрагента().Контрагент;" не корректна, т.к. структура СтруктураВидыОпределенияКонтрагента не содержит свойства "Контрагент", зато содержит "Документ".

И чтобы сработало вот это:

Если СвойстваИсточника().ВидОпределенияКонтрагента = ВидыОпределенияКонтрагента().Документ Тогда
Контрагент = мИсточник.Контрагент;

наверное, нужно было написать так:

Если ТипЗнч(мИсточник) = Тип("ДокументОбъект.РеализацияТоваровУслуг") Тогда
ВидОпределенияКонтрагента = ВидыОпределенияКонтрагента().Документ;

Сори, если туплю...
Но может кому сбережет нервы при копипасте примера :)
unichkin; +1 Ответить
38. unichkin 1559 22.03.18 10:52 Сейчас в теме
(36) Все верно, спасибо, поправил
39. Sei Souma 23.03.18 19:39 Сейчас в теме
Идея неплохая,но вообще удобнее чем работать с макетами в которых все зашито ничего опытным путем найдено не было.
40. webester 26 24.03.18 13:11 Сейчас в теме
Прошу прощения за глупые вопросы. Но вся суть это длинной статьи, отсылки на вики, простыней кода, заключаются в фразе: "Если вам нужно использовать несколько строк в операторах сравнения, используйте структуру" ? Или я чего то не заметил?
41. Digest08 21.05.18 08:33 Сейчас в теме
42. markers 274 15.08.19 07:49 Сейчас в теме
Если религия не запрещает, то можно использовать сами чистокровные перечисления без регистрации, смс и совершенно без серверных вызовов, спросите как? Очень просто!
1) Создаем реквизит формы произвольного типа, Назовем её к примеру "Переч_Статусы"
2) При создании формы на сервере (или любой другой метод, выполняющимся одним из первых на сервере) выполняете такой код для нужных перечислений:
Переч_СтатусыВрем = Новый Структура;
Итератор = 0;
	
Для Каждого стр из Метаданные.Перечисления.Статусы.ЗначенияПеречисления Цикл
		
	Переч_СтатусыВрем.Вставить(стр.Имя, Перечисления.Статусы[Итератор]);
	Итератор = Итератор + 1;
		
КонецЦикла;
	
Переч_СтатусыВрем.Вставить("ПустаяСсылка", Перечисления.Статусы.ПустаяСсылка());
Переч_Статусы = Новый ФиксированнаяСтруктура(Переч_СтатусыВрем);
Показать
Если перечислений много, можно использовать фиксированное соответствие, так вообще будет похоже на штатное перечисление
3) Там где надо получить значения перечисления пишите так:
Если Статус = Переч_Статусы["Готово"] Тогда
	// Ваш код
КонецЕсли;
Так можно без вызова сервера проверять/устанавливать значения перечислений, единственный минус, это отсутствие подсказки, но если вы ошибётесь в копипейсте значения перечисления при вставке в код, то так-же как и в данной публикации, будет выдана ошибка при выполнении.
PS: Так как это реквизит формы, а не переменная, то данный код можно использовать и на сервере (дабы не мучить базу лишними запросами).
43. unichkin 1559 18.08.19 14:06 Сейчас в теме
(42) Клиент-серверный кэш на форме нужен крайне редко. Кэшировать именно значения предопределенных элементов \ значения перечислений самостоятельно не требуется - для этого есть метод "ПредопределенноеЗначение". В том случае если на форме нужен кэш - это бывает, когда архитектурно невозможно вынести код в модуль объекта, можно также использовать глобальную переменную (в данные формы таблицу значений например не поместишь). Я это делаю примерно так:

&НаСервере
Перем мСтруктураКэшДанных;

//... 

&НаСервере
Функция КэшСервера()
	Если мСтруктураКэшДанных = Неопределено Тогда
		мСтруктураКэшДанных = Новый Структура;
		
	КонецЕсли; 
	
	Возврат мСтруктураКэшДанных;
	
КонецФункции

&НаСервере
Функция ДокументыКАнализу()
	
	Если НЕ КэшСервера().Свойство("ДокументыКАнализу") Тогда
		
		ДокументыКАнализу = Новый Массив;		
		//... 	
		КэшСервера().Вставить("ДокументыКАнализу", ДокументыКАнализу);
	КонецЕсли; 
	
	Возврат КэшСервера().ДокументыКАнализу;
	
КонецФункции

Показать
44. markers 274 18.08.19 14:32 Сейчас в теме
(43)
ПредопределенноеЗначение
я возможно сделаю для вас открытие, но данный метод делает серверный вызов и если сервер рядом, этим можно и пренебречь, но я как-то заметно ускорил РМК из 1С:Розница 2.2 особенно на слабом интернете, заменив ПредопределенноеЗначение на нечто подобное описанное в (42) ничего не потеряв при этом.
TeMochkiN; acanta; +2 Ответить
45. unichkin 1559 18.08.19 14:35 Сейчас в теме
(44) я руководствуюсь этой статьей https://its.1c.ru/db/v8std#content:443:hdoc
"При этом не следует в прикладном коде реализовывать собственные механизмы кеширования на клиенте предопределенных значений. Функция ПредопределенноеЗначение не ухудшает клиент-серверное взаимодействие: серверный вызов выполняется только при первом обращении к значению, а результат автоматически кешируется в кеше конфигурации на клиенте до следующего обновления версии конфигурации или версии платформы."
з.ы. не умаляю ваших результатов, но по своему опыту - сначала делаю как сказано на ИТС, если не катит начинаю изобретать велосипеды. А "не катит" довольно редко, до сих пор только один случай могу вспомнить.
markers; acanta; +2 Ответить
46. markers 274 18.08.19 14:46 Сейчас в теме
(45) По моему субъективному опыту, кешируется на время сеанса. И это кеширование несколько дороговатое, если можно это сделать самостоятельно, один раз и при создании формы на сервере. Я ни чуть не осуждаю вас, но к сожалению должен констатировать, что 1С делая Розницу, походу полагала что сервер будет находится за стенкой с гигабитной сетью и будет всего один магазин. И там много где используются избыточные вызовы сервера и много где используется в том числе ПредопределенноеЗначение на клиенте. Даже просто запуск сеанса в рознице и то удалось сильно ускорить (не смотря на то, что там ещё и мои обработчики навешаны по мимо типовых) заменив в куче мест вызовы модулей с галочкой "вызов сервера" и даже с галочкой "повторное использование" заменив всё это тем, что получаю все эти необходимые значения в типовую глобальную переменную "ПараметрыПриложения" один раз, делая один серверный вызов и просто в местах где это вызывалось, заменил на получение значения из этой клиентской переменной. Конечно, таким способом можно ускорить только получение некой статичной информации, но я даже некоторую потенциально не статичную информацию засунул туда, только сделал кнопочку "Обновить" на всякий случай, которая требуется раз в пятилетку.
PS: Но в любом случае, спасибо за ссылку!
47. markers 274 18.08.19 15:01 Сейчас в теме
Да, ещё хочется припомнить 1С один курьёзный случай в РМК (Розница 2.2), точно его не помню, по этому опишу по своему:
&НаСервере
Процедура ЧтоТоДеламемНаСервере()
	а = НайтиЭлемент("а");	
КонецПроцедуры

&НаКлиенте
Процедура ЧтоТоДеламемНаКлиенте()
	б = НайтиЭлемент("б");
КонецПроцедуры

&НаСервере
Функция НайтиЭлемент(Имя)
	Возврат Элементы[Имя]; // Этот кусок я точно помню, именно для этого и вызывался сервер
КонецФункции
Показать
И вот этот "НайтиЭлемент" вызывался на клиенте при наборе и пробитии одного чека что-то около 40 раз. Мне даже те кто пользуются файловой базой, начали жаловаться на тормоза. Что уже говорить о том, когда клиент отнесен от сервера на десятки и сотни километров и работает через тонкий клиент. Но это просто у меня наболело, извините
48. It-developer 24 21.07.20 10:59 Сейчас в теме
Соответствие лучше структуры. Можно избавиться от такого кода
Если СтатусЗаявки = СтатусыЗаявок().НаУтверждении Тогда
//...
ИначеЕсли СтатусЗаявки = СтатусыЗаявок().ТоварВПути Тогда
//...
ИначеЕсли СтатусЗаявки = СтатусыЗаявок().КОтгрузке Тогда
//...
КонецЕсли;
имея соответствие такое же как исходная структура
49. Zurfik 18.09.20 12:19 Сейчас в теме
Видимо я что-то делаю не так. Почему-то всегда структура заново заполняется значениями, хотя после первого выполнения функции они должны кэшироваться. Код в модуле формы.


Перем КэшДанныхПараметров;

Функция СтруктураЗначениеОсновныхПараметров()
	
        //КэшДанныхПараметров - пустой при каждом вызове функции
	Если НЕ КэшДанныхПараметров.Свойство("ПроизвольнаяСтруктура") Тогда
		
		ЗначенияСтруктуры = Новый Структура;
		ЗначенияСтруктуры.Вставить("Параметр1","Строка");
		ЗначенияСтруктуры.Вставить("Параметр2","123");
		ЗначенияСтруктуры.Вставить("Параметр3",Истина);
		
		КэшДанныхПараметров.Вставить("ПроизвольнаяСтруктура", Новый ФиксированнаяСтруктура(ЗначенияСтруктуры));
		
	КонецЕсли;
	
	Возврат КэшДанныхПараметров.ПроизвольнаяСтруктура;
	
КонецФункции

&НаКлиенте
Процедура КомандаА(Команда) Экспорт
	
//первый вызов функции, КэшДанныхПараметров - пустой что логично 
	Если СтруктураЗначениеОсновныхПараметров().Параметр1 = "Строка2"Тогда 
		Сообщить(""); 
//второй вызов функции, КэшДанныхПараметров пустой.. 
	ИначеЕсли СтруктураЗначениеОсновныхПараметров().Параметр2 = 222 Тогда
		Сообщить(""); 
//третий, КэшДанныхПараметров пустой..
	ИначеЕсли  СтруктураЗначениеОсновныхПараметров().Параметр3
		Тогда Сообщить(""); 
	КонецЕсли;
	
	Структура = СтруктураЗначениеОсновныхПараметров();
	
КонецПроцедуры

КэшДанныхПараметров = Новый Структура;


Показать
50. unichkin 1559 18.09.20 12:25 Сейчас в теме
(49) Все правильно, серверный кэш живет столько же, сколько и серверный вызов. К сожалению, нормальный клиент-сервер в формах реализуется достаточно убого: через реквизит произвольного типа. При этом следует учитывать, что данные этого реквизита будут гоняться на сервер, т.е. лишний трафик.
Выводы - на клиенте клиентский кэш, на сервере - серверный. Причем на клиенте время жизни кэша - пока открыта форма, на сервере - на время серверного вызова.
51. Zurfik 18.09.20 12:29 Сейчас в теме
(50) Я форму не закрывал. Просто нажимаю кнопку на форме и у меня 4 раза отрабатывает заполнение структуры, в чем тогда смысл кэширования, если оно не работает? Получается то же самое что и функцию Нрег вызывать для каждого строкового значения как у вас в примере.
52. unichkin 1559 18.09.20 12:34 Сейчас в теме
(51) Вы не понимаете поведения формы. Набросал реализацию клиентского кэша, на вашем примере:

#Область ОписаниеПеременных

&НаКлиенте
Перем мКэшКлиент;

#КонецОбласти 

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура КомандаА(Команда)
	
	ОсновныеПараметры = ОсновныеПараметры();
    
    Если ОсновныеПараметры.Параметр1 = "Строка2"Тогда 
        Сообщить(""); 
		
    ИначеЕсли ОсновныеПараметры.Параметр2 = 222 Тогда
        Сообщить(""); 
		
	ИначеЕсли  ОсновныеПараметры.Параметр3 Тогда 
		Сообщить(""); 
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти 

#Область СлужебныеПроцедурыИФункции

#Область Сервис

&НаКлиенте
Функция КэшКлиент()
	Если мКэшКлиент = Неопределено Тогда
		мКэшКлиент = Новый Структура;		
	КонецЕсли; 
	Возврат мКэшКлиент;	
КонецФункции
 
#КонецОбласти 

#Область ПрограммныеПеречисления

&НаКлиенте
Функция ОсновныеПараметры()
	
	Кэш = КэшКлиент();
	Если НЕ Кэш.Свойство("ОсновныеПараметры") Тогда
        Результат = Новый Структура;
        Результат.Вставить("Параметр1","Строка");
        Результат.Вставить("Параметр2","123");
        Результат.Вставить("Параметр3",Истина);
		
		Кэш.Вставить("ОсновныеПараметры", Результат);
	КонецЕсли; 
	
	Возврат Кэш.ОсновныеПараметры;
	
КонецФункции 

#КонецОбласти 

#КонецОбласти

Показать
67. Zurfik 18.09.20 12:58 Сейчас в теме
(52) А области в вашем коде обязательно использовать или они только для читаемости кода необходимы?
#Область СлужебныеПроцедурыИФункции
#Область Сервис
#КонецОбласти 
#КонецОбласти
71. unichkin 1559 18.09.20 13:14 Сейчас в теме
(67) На работоспособность отсутствие областей не повлияет конечно, но мое мнение - *всегда*, при разработке чего угодно надо следовать ИТС: Соглашения при написании кода.
Это можно считать "библией" 1С-ника, и читать как молитву каждый день, пока не будет от зубов отскакивать.
53. unichkin 1559 18.09.20 12:35 Сейчас в теме
(51) + кэш на форме нужен достаточно редко. Пример из статьи реализовывается в модуле объекта, там где необходимо писать серверную логику. Форма - это только интерактив.
55. FatPanzer 18.09.20 12:37 Сейчас в теме
(51) Потому что вы его вызываете ровно 4 раза.
Прикрепленные файлы:
56. Zurfik 18.09.20 12:39 Сейчас в теме
(55) У АС то же самое. Это просто пример посмотреть как работает механизм, этот код нигде не используется и не будет.
Если СтатусЗаявки = СтатусыЗаявок().НаУтверждении Тогда
		//...		
	ИначеЕсли СтатусЗаявки = СтатусыЗаявок().ТоварВПути Тогда
		//...		
	ИначеЕсли СтатусЗаявки = СтатусыЗаявок().КОтгрузке Тогда	
		//...		
	КонецЕсли; 
Показать
58. unichkin 1559 18.09.20 12:41 Сейчас в теме
(56) Еще раз, см. (52): пример статьи реализован в модуле объекта.
59. Zurfik 18.09.20 12:42 Сейчас в теме
(58)
Спасибо. Я попробую с вашим кодом.
60. FatPanzer 18.09.20 12:43 Сейчас в теме
(56) У меня? Где? Это не мой код. Это код автора статьи. Но ему я бы тоже по рукам настучал бы. Вместо того, чтобы один раз проверить кэш в начале функции (и перезаполнить его при необходимости), а вызывать его проверку в каждой строке - это моветон.
62. unichkin 1559 18.09.20 12:46 Сейчас в теме
(60) АС - это и есть автор статьи :) С вашим предложением согласен, но мне эта идея пришла позднее. На самом деле, проверка наличия свойства структуры происходит настолько мгновенно, что практически не отражается на производительности. Переменную кэша я обычно выношу в начало метода (см. 52) - но в первую очередь для читабельности, чтобы скобки нигде не писать.
63. FatPanzer 18.09.20 12:47 Сейчас в теме
(62) Я думал, что это опечатка - "У ВАС то же самое..." )))
64. Zurfik 18.09.20 12:48 Сейчас в теме
(60) Под АС я имел ввиду Автор Статьи. У вас 5 звезд, если вы такой специалист напишите статью, пустая критика тоже моветон.
68. FatPanzer 18.09.20 13:01 Сейчас в теме
(64) Не уверен, что автор статьи нуждается в вашей защите ;-)
75. Zurfik 21.09.20 04:19 Сейчас в теме
(68) Где вы тут увидели защиту автора. Ваше высокомерие не оправдано, у вас нет ни одной интересной статьи. Может специалист вы и хороший, но какая польза от вашей пустой критики, почувствовать собственную важность? Вместо того, что бы сделать что-то полезное для комьюнити брызжете слюной во все стороны и гордитесь этим фактом. От того что вы новичка в 1с обкакаете вы лучше не станете, хотя если это единственный способ самоутвердиться, то ок )
76. unichkin 1559 21.09.20 10:25 Сейчас в теме
(75) Пожалуйста, не флудите здесь. Общайтесь через ЛС, например.
72. unichkin 1559 18.09.20 13:20 Сейчас в теме
(60) Да, пожалуй надо бы подкорректировать завтра, чтобы не смущать умы. Спасибо за замечание)
FatPanzer; +1 Ответить
73. FatPanzer 18.09.20 13:21 Сейчас в теме
74. unichkin 1559 18.09.20 13:28 Сейчас в теме
(73) у меня многие скиллы с помощью мисты прокачаны, с такой закалкой какие обиды :))
57. unichkin 1559 18.09.20 12:40 Сейчас в теме
(55) У человека явное непонимание разницы между клиентским и серверным методом, он такого объяснения не поймет. Тут надо отправлять учить матчасть
61. FatPanzer 18.09.20 12:45 Сейчас в теме
(57) У меня для таких случаев клиентсерверный модуль с повторным использованием. В начале работы клиентского/серверного метода или при открытии/создании формы прочитал из него закэшированные данные, и хватит на весь сеанс работы с формой или на весь сеанс работы серверного вызова...
65. unichkin 1559 18.09.20 12:49 Сейчас в теме
66. FatPanzer 18.09.20 12:54 Сейчас в теме
(65) Я знаю )) Я ленивую использую только в том случае, если логика решения подразумевает от факт, что какая-то служебная коллекция может НЕ пригодиться в течении жизни (в тех же условных ветвлениях) - тогда да, я добиваю такие служебные коллекции в кэш только в момент обращения.
Если же при разработке формы или метода я точно знаю, что она та или иная коллекция мне необходима безо всяких условий - я набиваю эти служебные коллекции в кэш сразу при старте.

Обычное поведение, ничего экстраординарного. Удивлюсь, если опытные бойцы поступают как-то по-другому...
69. unichkin 1559 18.09.20 13:04 Сейчас в теме
(66) Т.е. вы *явно* управляете этим. А с кэшированием, описанным в статье это выходит само собой)
70. FatPanzer 18.09.20 13:13 Сейчас в теме
(69) Ну почему же сразу явно. В случае использования ленивости - конечно же точно так же через проверку свойств кэша, то есть неявно.
Но иногда лучше явно. Как раз вы об этом и писали. Если по ходу алгоритма к коллекции необходимо обращаться несколько раз, то в каждом случае подставлять ленивку - ну так себе читабельность кода может получиться. Иногда корректнее в самом начале явно закэшировать.
Все зависит от прикладной логики, на самом деле. Например в инструментах настройки чего либо, которые используются раз в год - можно и сразу кэшировать не озираясь на ресурсоемкость. В часто выполняемых операциях (какие-нибудь общие модули печати) - имеет смысл экономить ресурсы.
unichkin; +1 Ответить
54. FatPanzer 18.09.20 12:35 Сейчас в теме
(49) В вашем коде надо уничтожать все от первой до последней буквы.
Оставьте свое сообщение