gifts2017

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

Опубликовал Леонид Павлиенко (PLAstic) в раздел Программирование - Практика программирования

Бывает, в коде необходимо сослаться на конкретный элемент справочника, плана видов харктеристик или иной элемент объектного типа. Приходится ссылаться на конкретные значения реквизитов. Какие ошибки таит такой безобидный код и как их избежать?
Код наподобие следующего мешает получить удовольствие от проделанной работы:
ЦенаПродажи = Справочники.ТипыЦен.НайтиПоНаименованию("Розничные");
Это решение чревато ошибками в случае изменения ссылочных реквизитов, и неверно методологически: в случае перенумерации справочника надо лезть в код. Что делать?

Я предлагаю решение, которое не требует модификации стандартных объектов конфигурации, но подразумевает включение возможности внесения изменений в саму конфигурацию. Это решение опробовано на многочисленных типовых и самописных конфигурациях клиентов как в ОП, так и в УП (обычное и управляемое приложения).

В конфигурацию добавляем справочник СсылкиНаОбъекты:
  • - Без кода. Он не мешает, но это лишняя информация.
  • - С реквизитами:
    • "СсылкаНаОбъект" типа "Любая ссылка" или с множественным значением нужных типов;
    • "Описание" тип Строка (неогр.) для описания параметра;
  • - С предопределёнными элементами.
В качестве предопределённых элементов задаём те самые объекты, на которые бывает нужна ссылка:



В Наименовании указываем краткое описание параметра. Затем в режиме предприятия дообавляем в реквизит "Описание" более подробное описание параметра с указанием механизмов, в которых он используется. В значении выбираем тип и нужный объект:



Ну и теперь то, ради чего весь этот механизм создавался. Из кода можно сослаться на значение такого элемента следующим образом:
СвойствоСрокГарантии = Справочники.СсылкиНаОбъекты.СвойствоСрокГарантии.СсылкаНаОбъект;
Т.о. обеспечивается корректность ссылки при изменении любых реквизитов объекта и внесение каких-либо изменений при замене значения в код не требуется.

Добавлю для тех, кому лень читать комментарии:
* В (4) я признаю, что методологически этот способ не совсем правильный, т.к. именного для этих задач предназначен ПВХ. Этот механизм я использую в тех случаях, когда бюджет проекта не подразумевает выделения средств для программирования конструкций ПВХ + РС + общий модуль.
* Там же, в (4) я комментирую аналогичную статью на эту тему, автор которой не предлагал описываемый мной вариант. "Баянистов" прошу указывать пруф: до сих пор его нет.
* Решение не предусматривает ведения хронологии. Я до сих пор не сталкивался с такой необходимостью. Нужна хронология - периодический РС + ПВХ.
* Не считаю минусом то, что приходится выгонять всех пользователей ради применения изменений. Подразумевается, что программист ведёт разработку в тестовой базе и уже отлаженный механизм  применяет в боевую. Следовательно, выгонять пользователей нужно будет в любом случае и этот случай один.

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Яков Коган (Yashazz) 28.07.14 14:40
Баян же. Было обсуждено уже N раз.
amon_ra; vano-ekt; Aleks_Antonuk; cleaner_it; +4 Ответить 1
2. Леонид Павлиенко (PLAstic) 28.07.14 14:43
3. Артано Майаров (Артано) 29.07.14 19:43
(2) Подтверждаю, что баян - поиск по сайту и форму в помощь. Решение само по себе имеет право на жизнь. Эту проблему каждый решает по своему. Я, например, предпочитаю тематические регистры сведений с явной типизацией полей
4. Леонид Павлиенко (PLAstic) 30.07.14 08:29
(3) Артано, в (2) я уже запрашивал пруф. Вы его тоже не смогли предоставить. Поиск по "ссылка на конкретный элемент" ничего не даёт.
Друзья, логика проста: есть пруф, подтверждающий баянность - статья удаляется. Если вы в кулуарах где-то что-то обсудили на эту тему , извините, это известно только вам. Если решили иначе (через РС, например), то это другое решение со своими плюсами и минусами. Например, пользователь может ввести вторую строку или же при обмене данными они могут задвоиться. Т.е. потенциально это решение может привести к ошибкам.
В http://infostart.ru/public/275145/ автор предлагает аж три решения. Первое и третье - модификация стоящих на поддержке объектов, посему лично для меня неприменимо. Второе решение: ПВХ + РС + код. Оно сложнее в реализации и содержит те же потенциальные ошибки, что я описывал выше применительно к РС.

ps: Замечу сам, чтобы быть первым. :) Предлагаемое мной решение методологически верно не на 100%. Какой-нибудь преподаватель УЦ может сказать, что именно для таких случаев со значениями составных типов и создавались ПВХ: они позволяют жёстко определить, что такой-то параметр имеет такой тип, а другой параметр - иной. Возразить могу только то, что элементов в таком справочнике мало, а тип явно указывается в описании. Это не оставляет шансов пользователю накосячить.
5. Роман Осадченко (cleaner_it) 30.07.14 02:38
(0) Правда баян. Если придумал сам - молодец конечно, но иногда нужно ознакомиться с лучшими практиками и другими мнениями. Поиск в руки с тегом "НайтиПоНаименованию". Здесь обсуждали твой способ: http://infostart.ru/public/275145/
6. Леонид Павлиенко (PLAstic) 30.07.14 08:47
(5) cleaner_it, аккурат в предыдущем посте я обсудил эти "лучшие практики".
7. Роман Осадченко (cleaner_it) 30.07.14 03:16
(6) PLAstic, да ты не воспринимай в пику. Я и сам так делаю, только названия справочника и реквизитов другие. Весь вопрос в том, что этот способ известен очень многим, и довольно часто обсуждается.

Доработаешь статью с учетом рекомендаций из переписки по той публикации - тогда будет здорово.
В частности - про общий модуль с кешированием возвращаемых значений для ускорения работы и улучшения читабельности кода.
8. Леонид Павлиенко (PLAstic) 30.07.14 09:24
(7) cleaner_it, я спокоен. Отвечаю на всё, потому что самому интересно, есть ли лучшие решения.
В частности - про общий модуль с кешированием возвращаемых значений для ускорения работы

Мысль неоднозначной полезности, пожалуй. На моей практике нет таких случаев, когда бы я получал значение такой ссылки много раз за сеанс. Даже если идёт работа в цикле, то логично получить значение в переменную перед циклом и использовать в цикле её.
9. Степашка Никулин (Styvi) 30.07.14 11:13
Соглашусь, что "баян", ибо такая тактика вообще очень не нова - в 1с77 все ссылки в коде делались именно через подобный механизм... В основном это происходило через добавление новой Константы... но и через справочники - тоже...
Возразить могу только то, что элементов в таком справочнике мало, а тип явно указывается в описании. Это не оставляет шансов пользователю накосячить.

Если предопределённых элементов в конкретной базе предполагается немного, то можно по-старинке воспользоваться именно Константами... аналогично ОсновнойСклад и ОсновнаяФирма...
10. Артём Алтухов (Fannasankh) 30.07.14 12:21
Регистр сведений в таких случаях получше
11. г. Казань Рустем Гумеров (Rustig) 30.07.14 14:55
использую НайтиПоНаименованию() без зазрения совести после того, как на небольших внедрениях понял, что клиенту надо "быстро" и без особого вмешательства в конфигурацию (добавлять постоянно предопределенные элементы - это значит просить всех пользователей выйти), что основополагающие для учета требования клиента меняются условно "раз в 5 лет" и вся запрограммированная система стабильно работает длительное время. плюсов в предопределенных элементов не вижу, если только в типовых конфигурациях ЗУП и БП со своими сложными расчетами з/п и составлением деклараций.
в общем не стал заморачиваться с НайтиПоНаименованию().
информация в статье для меня новая, не могу сказать что баян, и в целом реализация мне нравится.
12. Кирилл Горшков (kirill_8bit) 30.07.14 15:19
13. Maxim Kolkin (the1) 30.07.14 15:58
(11) Только НайтиПоНаименованию(), только хардкор!
14. Алексей Кубовцов (aleksey.kubovtsov) 30.07.14 20:02
+ за статью.
как - то на эту тему не думал . найтиПоНаименованию, найтиПоКоду пока работает )
15. Геннадий Пиганов (Totoro) 30.07.14 21:07
Решение имеет право на жизнь. Я использовал по другому:
1) раз справочник все равно служебный и пользователю запрещено добавлять в него элементы, то предопределенные элементы не обязательны и не требуется выгонять пользователей при добавлении нового элемента. Сама же ссылка настройки без проблем получается через НайтиПоКоду
2) Нет возможности учета истории. Часто история все же нужна. Для этого есть доп. периодический регистр сведений.
Пользователь к ошибкам привести не может, т.к. прав интерактивного редактирования РС у него нет.
3) Еще, если добавить в РС группу пользователей можно разграничивать настройки между пользователями. Для общих настроек - все пользователи.

В типовых, когда изменения конфигурации запрещены, использовал ХранилищеЗначения в типовых справочниках хранения настроек. Нет контроля ссылочной целостности, но лучше чем НайтиПоКоду и настраивать можно.
Dach; PLAstic; +2 Ответить 2
16. Сергей Старых (tormozit) 31.07.14 09:01
Еще можно использовать метод ПолучитьСсылку менеджера и передавать в нее ИД, тогда получится близкий аналог предопределенного элемента, т.к. обращения к БД не будет и ссылка везде будет иметь одно и то же значение.
Донг = Справочники.Валюты.ПолучитьСсылку(Новый УникальныйИдентификатор("..."));

В любом случае такого рода приемов подразумевает инициализацию подобных элементов в новой базе, либо использование ее только в семействе уже инициализированных баз с общими данными этого типа.
17. Леонид Павлиенко (PLAstic) 31.07.14 09:25
(16) tormozit, этот способ описан в комментариях к упоминавшейся статье. Я согласен к комментаторами, что он ничем не лучше НайтиПоНаименованию().
18. Евгений Моисеенко (bpc222) 01.08.14 10:24
Зачем все это? Есть же все в платформе.
ИМХО, при грамотном подходе к проектированию решений эти "обходные" пути не пригодятся.
19. Александр Полтава (Патриот) 01.08.14 17:50
Юзаем такой справочник уже не первый год)
20. Алексей 1 (AlX0id) 02.08.14 18:44
(19) Патриот,
Аналогично )
Кстати, в решениях Первого БИТа видел не справочник, а ПВХ - так, наверное, все же более правильно.
21. Allexey (alex_4x) 04.08.14 10:39
Еще проще вынести в отдельную процедуру. Менее концептуально, зато больше возможностей, например в зависимости от даты или других параметров можно подставлять. Такой метод считается "не кошерным", только из за того, что в пользовательском режиме нельзя менять настройки. Но если эти "константы" системные, и пользователю к ним доступ давать не следует, как раз самый простой вариант.
22. Юрий Патласов (NoRazum) 04.08.14 17:26
А почему все это не вывести в реквизиты обработки и загружать при открытии и сохранять при закрытии.
Если появиться новый пользователь один раз ему поставить эти значения и ВСЁ.
На крайний случай искать через ПОПЫТКУ по наименованию.
И лесть в конфигурацию?
23. Damian (Damian) 06.08.14 13:54
У себя применяю ПВХ, 2 регистра: "Предопределенные элементы" и "Предопределенные списки" и общий модуль, в котором все это дело получается.
В результате можно хранить как одиночные значения (на замену константам), так и списки этих значений, в том числе упорядоченные.
Периодичность значений пока не требовалась, но допилить не сложно.
Если руки дойдут, может выложу и свой вариант :)
24. Андрей Киреев (FractonKireyev) 06.08.14 15:39
(15) Totoro,
К пункту 1. Поскольку добавление нового элемента всегда связано с изменением кода (нет смысла добавлять новый элемент, если на него нигде нет ссылок, а ссылки для этой задачи могут быть только в коде), то какая разница для чего выгонять пользователей - только для обновления кода конфигурации, или для изменения кода конфигурации плюс добавление нового предопределённого элемента?
25. Геннадий Пиганов (Totoro) 06.08.14 20:14
(24) для внешних печатных форм, обработок и отчетов изменения кода не требуется, а константы нужны/удобны.
26. Ivan Khorkov (vano-ekt) 11.08.14 10:41
27. Михаил Канаев (mrBart) 11.08.14 12:59
эммм... возникает вопрос удаления обхекта на которого в специальном справочнике есть ссылка, тут наверное два варианта, либо РС со свойством "Ведущее" и измерения СсылкаНаобъект, либо вместо ссылки писать тип и уид.
А вообще если говорить про обычные формы, во всех конфигурациях есть РС "Сохраненные значения", в управляемых формах стал пользоваться хранилищами значений.
28. VVV (V_V_V) 11.08.14 16:04
Правильной дорогой идете товарищи, защита от говнокодеров нужна! Статья хорошая.
Но, как уже было замечено, нельзя "про запас" накидать предопределенных элементов, нужно при возникновении потребности лезть в конфигуратор. При наличии РИБ - и не в один. Чем не вариант добавить ПВХ (пользователю недоступный), в котором на лету создавать необходимые записи и в коде нетленных отчетов\обработок ссылаться через (чую смерть моя близка!) НайтиПоНаименованию (или Коду) на свежесозданный элемент ПВХ...
PS. ПВХ в твоем полном распоряжении, изменил чего - ну кто тебе доктор...
PPS. Если группа разработчиков - и так должно быть понятно к каким последствиям может привести правка Наименования (Кода) именно этого ПВХ...
PPPS. Вместо ПВХ никто не запрещает использовать Справочник, как у автора...
PPPPS. При желании можно привязать историю правок...
29. Евгений К (rar_xxx) 18.08.14 11:30
Плохой совет! Во многих, если не во всех типовых конфигурациях(Бух, УТ, КА, ЗУП), есть регистр сведений "Соответствие объектов для обмена", вот его и нужно использовать для подобных целей. Все поля не обязательны для заполнения. СобственнаяСсылка - "ЛюбаяСсылка", СсылкаВДругойИБ - Строка(100), ИмяТипаПриемника - Строка(100). И не ограничены цели, для которых этот регистр будет использоваться. И самое важное, закройте конфигуратор!)
30. Леонид Павлиенко (PLAstic) 18.08.14 12:08
(29) rar_xxx,
Как ссылаться на конкретный элемент? НайтиПоРеквизиту или даже запросом?
Как убедиться, что нужный параметр присутствует в РС?
Как убедиться, что нужный параметр присутствует в одном экземпляре?

Не вижу плюсов данного варианта при наличии такого количества минусов.
31. Евгений К (rar_xxx) 18.08.14 19:19
(30) PLAstic, 1. Все делается запросами. 2 - Запросом. 3 - запросом. Выдуманные минуса, ровно как ты добавляешь предопределенные в справочник, так же добавляешь элементы в регистр. Хочется обращаться в запросах через НазваниеСправочника.НазваниеЭлемента, перед запросом получаешь все нужные значения и засовываешь их как параметры. Но + в том что если ты когда то работал с базами которые работают 24*7, то должен понимать что для полноценной безостановочной работы подходит только мой вариант.
ander_; kiros; +2 Ответить 1
32. Леонид Павлиенко (PLAstic) 18.08.14 19:38
(31) rar_xxx, я не говорил, что решение подходит для баз 24*7. Наоборот, в комментариях я упоминал, что настанет момент применения изменений в базу. Вполне вероятно, что для такого редкого случая как ОП типовая в режиме 24*7 этот способ является оптимальным. В остальных случаях лично мне он кажется более ресурсоёмким для 1С и менее надёжным при программировании, т.к. названия приходится вписывать ручками в текст и легко можно ненароком изменить их в регистре. По сути он мало чем отличается от НайтиПоНаименованию.
33. capone capone (capone) 18.08.14 21:58
А чем плох поиск по GUID? Типа - Справочники.Склады.ПолучитьСсылку(Новый УникальныйИдентификатор("cc1dd491-c7d8-11a2-f90a-1c7ee5263dff"))
34. Кирилл (kiros) 19.08.14 09:57
(33) capone, тем, хотя бы, что в запросе этого использовать нельзя. И я очень бы хотел посмотреть на Вас, через пол года, когда в алгоритм надо будет внести изменения. Т.е. к вашей конструкции еще ворох комментариев нужен как минимум. Да и GUID это вещь постоянная - относительно, имеется опыт...
ander_; PLAstic; +2 Ответить 1
35. Евгений К (rar_xxx) 19.08.14 15:26
(32) PLAstic,
По сути он мало чем отличается от НайтиПоНаименованию.
Отличается тем что наименование может меняться, а в регистре сидит ссылка.
В остальных случаях лично мне он кажется более ресурсоёмким для 1С и менее надёжным при программировании, т.к. названия приходится вписывать ручками в текст и легко можно ненароком изменить их в регистре
. Первое преподователь из СЦ не даст жизнь твоему решению, а если ты подобное на экзамене специалиста сделаешь снимут бал, ибо 1ое - изменение типовых конфигураций 1с не приветствует, 2ое - изменение конфигурации при возможности использования типовых объектов не кто не приветствует, мой метод простой,
приходится вписывать ручками в текст
при создании предопределенного ты имя не руками пишешь? Для самоконтроля сделай себе обработку по работе с этим регистром, придумай ИмяТипаПриемника - "мои переменные" и выводи в обработку список всех своих переменных, где будут проверки на задвоение и т.п. И еще кроме 24/7, есть еще базы >=100 Гб, а еще есть регламенты согласно которым каждое изменение ты утверждаешь с рук. отдела, такие изменения не разрешат.
36. Леонид Павлиенко (PLAstic) 19.08.14 15:57
(35) rar_xxx,
Отличается тем что наименование может меняться, а в регистре сидит ссылка.

Ссылку на строковое значение объекта мы заменяем на ссылку на строковое значение регистра. Суть не меняется.
изменение конфигурации при возможности использования типовых объектов не кто не приветствует

При чём тут преподаватели или руководители отдела? Это наглядный пример задействования объекта, предназначенного для одних нужд, для реализации других. Я склонен считать такое решение методологически некорректным. Из практики 1С не могу вспомнить конкретные примеры, но из практики IT помню, как один клиент хранил важные документы в "корзине". До тех пор, пока другой, не подозревая об этом, не очистил "корзину". Аналогия, думаю, понятна. Удачи.
37. Евгений К (rar_xxx) 19.08.14 18:18
(36) PLAstic,
Ссылку на строковое значение объекта мы заменяем на ссылку на строковое значение регистра. Суть не меняется.
я предлагаю сделать ровно то что предлагаешь ты, привязать к ссылке свое наименование, чтобы при изменении наименования объекта код работал. И где здесь
задействования объекта, предназначенного для одних нужд, для реализации других
?, этот регистр необходим для обмена, чтобы всякие правщики конфигураций, не добавляли реквизиты к метаданным с названиями "idТам", "IdдругойБазы" и т.п. После которых на базу смотреть невозможно! Задача у меня следующая: я - другая ИБ, у меня есть справочник переменных, хочу хранить связки своих переменных с ссылками в тек. базе, например: id моей ИБ - "Склад поступлений", ИмяТипаПриемника - "Мои переменные". Иногда надо послушать людей и подумать, а не с пеной доказывать свою точку зрения. А связывать это регистр с корзиной не корректно, то что он может бесконтрольно очистится говорит о кривом использовании базы. Когда строишь обмены между кучей систем, не только 1с, с помощью правил КД и использованием данного регистра, трогаешь его ООООооочень аккуратно! И еще
Справочники.МойСправочник.МоеНазвание
равносильно
"Выбрать Ссылка Из Справочник.МойСправочник Где Наименование = ""МоеНазвание"""
и равносильно
Справочники.МойСправочник.НайтиПоНаименованию("МоеНазвание");
В любом случае это превращается в запрос. Соответственно если регистр Соответствие объектов для обмена пустой то скорость работы этих 2х решений аналогична. Ща поговорил с 2мя напарниками имеющими звание - "Специалист 8.3" их перекосило от вашего метода, выводы делайте сами, но советовать надо когда 100 есть процентов уверенности в своем мнении.......
38. Леонид Павлиенко (PLAstic) 19.08.14 20:57
(37) rar_xxx, Вы позволите мне остаться при своем мнении или я обязан принять Вашу точку зрения? Я уже высказал свои доводы и не увидел веских аргументов. Предлагаю прекратить попытки.
39. Роман Ложкин (webester) 19.08.14 20:31
Сколько можно обсасывать одно и то же? Было и гораздо более развернуто http://infostart.ru/public/275145/
40. Роман Ложкин (webester) 19.08.14 21:03
(33)Тем что строка Справочники.Склады.ПолучитьСсылку(Новый УникальныйИдентификатор("cc1dd491-c7d8-11a2-f90a-1c7ee5263dff")) не говорит не о чем и глядя на код чуть позже ты долго будешь втыкать что же стоит за этим гуидом, а если таких гуидов больше чем несколько, то рассматривать такой код совсем печально.

(34)
Да и GUID это вещь постоянная - относительно, имеется опыт...
Гуид вещь постоянная, которая штатными средствами(если не лазить немытыми руками напрямую в базу) не меняется в принципе.

(37)Если мягко сказать вы неправы. Во первых наименование, это такая вещь, когда каждый пользователь может просто добавить туда пробел и ваш код перестанет работать. За работу с поиском по наименованию, били по рукам, еще во времена 77 и предопределенные элементы нужны как раз для того, что бы их заменить. Во вторых это
Справочники.МойСправочник.МоеНазвание
равносильно
"Выбрать Ссылка Из Справочник.МойСправочник Где Наименование = ""МоеНазвание"""
и равносильно
Справочники.МойСправочник.НайтиПоНаименованию("МоеНазвание");

тоже мягко говоря не так https://api.monosnap.com/image/download?id=FD7TO6AJxbeIv0SpkmrTrcf95yHJbM
41. Евгений К (rar_xxx) 20.08.14 12:07
(40) webester,
Если мягко сказать вы неправы. Во первых наименование, это такая вещь, когда каждый пользователь может просто добавить туда пробел и ваш код перестанет работать. За работу с поиском по наименованию, били по рукам, еще во времена 77 и предопределенные элементы нужны как раз для того, что бы их заменить.
Речь идет про справочник который хранит ссылку на необходимые объекты, обращение и поиск в этом справочнике идет по имени, например Справочники.МоиПеременные.СкладПродаж. 2 - я ошибся в плане скорости обработки 1с, если смотреть в анализатор запросов sql эти 3 метода идентичны, разница во времени выполнения 1с, заключается в том что при формирования запроса sql все названия таблиц, колонок, справочников меняет на реальные, а это еще заросы к таблице соответвия имен метаданных их реальным именам поэтом кло-во действий при обращении через точку меньше всего, через найти по наименованию изменений немного, а в случае запроса анализируется и изменяется весь его текст. Кстати в 8.3 переработали Предопределенные элементы в «1С:Предприятии 8.3» и теперь можно делать предопределенные элементы в нужных справочниках, не заходя в конфигуратор, так что больше не нужно создавать свое хранилище переменных.
42. Андрей Акулов (DrAku1a) 23.08.14 22:49
(15) 1. НайтиПоНаименованию() лучше будет, и длиннее идентификатор можно делать и понятнее при чтении кода.
2. Историю вполне можно хранить в табличной части справочника, добавив реквизит "Период".
3. Права доступа можно при необходимости организовывать - в еще одной табличной части.
43. Леонид Павлиенко (PLAstic) 25.08.14 10:18
(41) rar_xxx, итак, разница в скорости есть. "Новый" способ создавать предопределенные элементы далеко не такой новый. Он был подробно рассмотрен в упоминавшейся мной статье (3 вариант) на ту же тему и отклонен как требующий включения возможности внесения изменений в объект конфигурации. Напомню: "но советовать надо когда 100 есть процентов уверенности в своем мнении". Привет "специалистам".
(42) DrAku1a, методологически Вам нет оправдания. Нежелание включать возможность изменения для объектов не должно приводить к созданию таких некорректных решений. Эмулируем регистр сведений при его жизни? Игнорируем RLS? Я считаю, не стоит.