В процессе разработки конфигураций нередко возникает ситуация, когда алгоритм уже реализован в одном прикладном объекте (например, в справочнике или документе), и его требуется переиспользовать в коде другого объекта. Разберем по шагам, как правильно организовать вызов таких процедур и функций, с какими потенциальными рисками можно столкнуться и какие архитектурные практики платформы 1С считаются наиболее эффективными.
Рассмотрим ситуацию, когда нужная нам функция расположена в модуле объекта справочника. Важно помнить, что любая процедура или функция модуля объекта доступна извне только в том случае, если она объявлена с ключевым словом Экспорт.
Для обращения к методу модуля объекта требуется экземпляр этого объекта. Если логика привязана к конкретному элементу базы данных, алгоритм вызова выглядит следующим образом:
ПолучитьОбъект().Посмотрим на пример кода с безопасной проверкой полученных данных:
СсылкаНаЭлемент = Справочники.Номенклатура.НайтиПоНаименованию("Товар 1");
Если Не СсылкаНаЭлемент.Пустая() Тогда
ОбъектСправочника = СсылкаНаЭлемент.ПолучитьОбъект();
Результат = ОбъектСправочника.НашаЭкспортнаяФункция();
КонецЕсли;
Важные риски прямого вызова через ПолучитьОбъект():
ПолучитьОбъект() от пустой ссылки вызовет аварийное падение программы с ошибкой «Значение не является значением объектного типа».ПолучитьОбъект() полностью считывает все данные элемента, включая табличные части. Если функция не изменяет и не использует специфические данные конкретной записи, чтение объекта создает лишнюю нагрузку.ПолучитьОбъект() внутри транзакции накладываются блокировки на запись таблицы базы данных, что может приводить к конфликтам блокировок при многопользовательской работе.Проанализируем случай, когда метод жестко привязан к модулю объекта (например, использует типовые реквизиты объекта или структуру его табличных частей), но при этом обращаться к конкретному существующему элементу в базе данных нет необходимости. В этом случае мы можем создать элемент в оперативной памяти без записи в базу:
НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
Результат = НовыйОбъект.НашаЭкспортнаяФункция();
Этот подход избавляет от необходимости искать существующую запись и исключает риск падения на пустой ссылке.
Если алгоритм логически относится к конкретному справочнику, но не зависит от данных одной конкретной строки или экземпляра, наилучшей практикой является размещение процедуры в модуле менеджера справочника.
Выясним преимущества такого подхода: менеджер справочника доступен всегда, для его вызова не нужно читать данные из базы и создавать объекты в памяти. Метод также объявляется с ключевым словом Экспорт.
Посмотрим на пример вызова:
// В модуле менеджера справочника Номенклатура:
// Функция РассчитатьСкидку(Сумма) Экспорт
// ...
// КонецФункции
// Вызов из любого другого справочника или документа:
Результат = Справочники.Номенклатура.РассчитатьСкидку(1000);
Такой вызов работает значительно быстрее, безопаснее и требует меньше строк исходного кода.
Если процедура или функция является по-настоящему глобальной и используется в различных несвязанных между собой объектах (в нескольких справочниках, документах, отчетах), стандарты разработки 1С предписывают выносить ее в Общий модуль.
Разберем порядок действий:
Экспорт.Пример прямого вызова:
Результат = РасчетныеМеханизмыСервер.НашаУниверсальнаяФункция(Параметр1, Параметр2);
Вынос логики в общий модуль полностью устраняет искусственную связанность между различными справочниками и документами, делая архитектуру конфигурации чистой и удобной для сопровождения.
Обратим внимание на клиент-серверное разделение платформы: модули объектов и модули менеджеров справочников выполняются исключительно на стороне сервера. При работе в управляемом интерфейсе обратиться напрямую к методам Справочники... из клиентских процедур формы (с директивой &НаКлиенте) невозможно. Для выполнения таких операций необходимо перейти в контекст сервера с помощью директив &НаСервере или &НаСервереБезКонтекста.