Общий модуль в расширении конфигурации: создание, свойства и связь с типовой

· 10 мин

Содержание

Общий модуль добавляют в расширение в Конфигураторе. Откройте Конфигурация → Расширения конфигурации, выберите расширение и нажмите «Открыть конфигурацию». В дереве расширения правой кнопкой щёлкните по ветке Общие → Общие модули и выберите «Добавить». Затем отметьте, где будет работать код (Сервер, Клиент, Вызов сервера), напишите экспортные процедуры и выполните «Обновить конфигурацию базы данных» для расширения (F7 в окне расширения).

Так обычно и начинается доработка типовой: бухгалтер просит, чтобы при записи реализации проверялся лимит по договору. Править типовую БП или УТ нельзя — потеряется лёгкое обновление. Поэтому общий модуль с проверкой кладут в расширение, а в типовую «врезаются» через заимствование. Всё ниже относится к платформе 1С:Предприятие 8.3 (расширения появились в версии 8.3.6) и одинаково для любой конфигурации.

Подготовка расширения перед созданием модуля

Если расширения ещё нет, создайте его: в окне Расширения конфигурации нажмите «Добавить». Платформа создаст пустую конфигурацию-расширение и откроет её свойства.

В свойствах расширения проверьте три поля:

  • 🏷️ Префикс имён — например, Расш1_ или короткий код вашей компании. Конфигуратор сам подставляет его в имена новых объектов. Префикс защищает от совпадения имён с объектами типовой после её обновления.
  • 🎯 Назначение — «Исправление», «Адаптация» или «Дополнение». Для своих доработок чаще всего ставят «Адаптация» или «Дополнение». От назначения зависит порядок применения нескольких расширений.
  • 🔒 Безопасный режим — если расширение работает в безопасном режиме, код в нём не сможет выполнять потенциально опасные действия: работу с файлами на сервере, внешние компоненты, COM. Решите это заранее, а не после ошибки в рабочей базе.

Держите отдельное расширение под каждую задачу. Одно «большое» расширение со всеми доработками сложно отключить частично, когда что-то сломалось.

Как добавить новый общий модуль в расширение 1С

Новый (собственный) общий модуль — это модуль, которого нет в основной конфигурации. Он целиком принадлежит расширению.

Шаг 1. Создание объекта

  1. Откройте дерево расширения.
  2. Разверните ветку Общие, щёлкните правой кнопкой по Общие модули и выберите «Добавить».
  3. Задайте имя. Префикс уже стоит в начале, допишите смысл: Расш1_КонтрольЛимитовСервер.
  4. Заполните синоним — его увидят в сообщениях об ошибках и в отладчике.

Шаг 2. Свойства

В палитре свойств отметьте флажки контекста. Подробно о них — в следующем разделе. Минимальный набор для серверной логики: только «Сервер».

Шаг 3. Код и применение

  1. Двойным щелчком откройте модуль и напишите процедуры с ключевым словом Экспорт.
  2. Проверьте синтаксис: Ctrl+F7 или команда проверки модулей в меню Конфигурация окна расширения.
  3. Выполните «Обновить конфигурацию базы данных» (F7) в окне расширения.
  4. Перезапустите сеанс 1С:Предприятия — уже открытые сеансы новое расширение не увидят.

Если расширение подключено к рабочей базе, где сидят пользователи, изменения подхватятся только при их следующем входе. Предупредите людей заранее.

Чтобы перенести готовое расширение в другую базу, сохраните его в файл .cfe через меню Конфигурация → Сохранить в файл в окне расширения. В целевой базе загрузите файл и отдельно выполните обновление конфигурации базы данных — это два разных шага.

Свойства общего модуля в расширении: где выполняется код

Флажки в свойствах определяют, в каком контексте модуль скомпилируется и откуда его можно вызвать. Это главное место, где ошибаются при переносе кода.

СвойствоЧто даётКогда ставить
СерверМодуль доступен в серверном кодеЗапросы, запись объектов, расчёты
Клиент (управляемое приложение)Модуль доступен на тонком и веб-клиентеДиалоги, оповещения, работа с формой
Вызов сервераЭкспортные методы можно вызывать с клиента«Мост» с клиента на сервер
Внешнее соединениеДоступ при подключении через COMИнтеграции, внешние обработки через COM
Клиент (обычное приложение)Доступ в толстом клиенте обычного приложенияТолько для старых конфигураций на обычных формах
ПривилегированныйКод выполняется без проверки правСлужебные операции, которым не хватает прав пользователя
ГлобальныйМетоды вызываются без имени модуляПочти никогда — засоряет пространство имён
Повторное использование возвращаемых значенийКэш результатов функцийСправочные данные, которые редко меняются

Флажок «Вызов сервера» имеет смысл только вместе с «Сервер». Клиентский код не может обратиться к модулю, у которого стоит один «Сервер», — нужен именно «Вызов сервера».

«Привилегированный» отключает проверку прав для всего кода модуля. Не кладите туда методы, которые принимают с клиента произвольные параметры: это лазейка в обход ролей. Привилегированный модуль делайте только серверным и держите в нём минимум кода.

Схема разделения на несколько модулей

Удобно сразу делить логику по контексту, как это сделано в типовых на БСП:

  • 🖥️ Расш1_КонтрольЛимитовСервер — флажок «Сервер», вся работа с базой.
  • 🔁 Расш1_КонтрольЛимитовВызовСервера — «Сервер» + «Вызов сервера», тонкая обёртка для клиента.
  • 💻 Расш1_КонтрольЛимитовКлиент — «Клиент (управляемое приложение)», сообщения и диалоги.
  • 🧩 Расш1_КонтрольЛимитовПовтИсп — «Сервер» + повторное использование, кэш настроек.

Суффиксы Сервер, Клиент, ВызовСервера, ПовтИсп — договорённость, а не требование платформы. Но с ними с первого взгляда ясно, где выполняется метод.

Код общего модуля: экспорт, контекст и инструкции препроцессора

Директивы компиляции &НаКлиенте, &НаСервере, &НаСервереБезКонтекста пишут в модулях форм и команд. В общем модуле их нет: контекст задают флажки свойств из раздела выше.

Если модуль собирается и на клиенте, и на сервере (стоят оба флажка), разделяйте код инструкциями препроцессора:

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

// Возвращает остаток лимита по договору в рублях.
Функция ОстатокЛимита(Договор) Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Договоры.Расш1_Лимит КАК Лимит
	|ИЗ
	|	Справочник.ДоговорыКонтрагентов КАК Договоры
	|ГДЕ
	|	Договоры.Ссылка = &Договор";
	Запрос.УстановитьПараметр("Договор", Договор);

	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		Возврат Выборка.Лимит;
	КонецЕсли;

	Возврат 0;

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

#КонецЕсли

Реквизит Расш1_Лимит в примере добавлен в заимствованный справочник тем же расширением. Без такого реквизита запрос не скомпилируется — замените поле на своё.

Правила, которые экономят время на отладке:

  • ✅ Без слова Экспорт метод не виден за пределами модуля. Это самая частая причина ошибки «Метод объекта не обнаружен ».
  • ✅ Обращайтесь к методу через имя модуля: Расш1_КонтрольЛимитовСервер.ОстатокЛимита(Договор).
  • ✅ С клиента на сервер передавайте ссылки и примитивные значения, а не объекты. Объект справочника на клиент не передаётся.
  • ✅ Комментарий над экспортным методом показывается в контекстной подсказке — описывайте параметры и возвращаемое значение.

Как связать модуль расширения с типовой конфигурацией

Основная конфигурация ничего не знает о собственных объектах расширения. Написать вызов Расш1_... в модуле типовой нельзя — типовую вы не меняете. Поэтому связь строится от расширения к типовой.

Способ 1. Заимствовать модуль типовой и перехватить метод

  1. В окне расширения откройте дерево основной конфигурации (кнопка показа основной конфигурации или отдельное окно Конфигурация → Открыть конфигурацию).
  2. Найдите нужный общий модуль, щёлкните правой кнопкой и выберите «Добавить в расширение». Модуль появится в дереве расширения как заимствованный.
  3. Откройте модуль типовой, встаньте в нужную процедуру, правой кнопкой — «Добавить в расширение». Платформа предложит вид перехвата и создаст заготовку.

Виды перехвата:

АннотацияЧто делаетРиск при обновлении типовой
&Перед("Метод")Ваш код выполняется до исходногоНизкий
&После("Метод")Ваш код выполняется после исходногоНизкий
&Вместо("Метод")Ваш код заменяет исходный; оригинал вызывается через ПродолжитьВызов()Средний: легко потерять логику типовой
&ИзменениеИКонтроль("Метод")Копия метода с правками, платформа сверяет текст с оригиналомРасширение не применится, если метод в типовой изменился

Пример: перед записью документа вызываем свою проверку лимита.

&После("ПередЗаписью")
Процедура Расш1_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

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

	Расш1_КонтрольЛимитовСервер.ПроверитьЛимит(ЭтотОбъект, Отказ);

КонецПроцедуры

Это обработчик в модуле заимствованного документа, а не в общем модуле. Именно отсюда управление уходит в ваш общий модуль. ПроверитьЛимит — ваша экспортная процедура, которую нужно дописать по образцу функции из прошлого раздела.

Способ 2. Переопределяемые модули БСП

В типовых на БСП есть общие модули с окончанием Переопределяемый. Их процедуры специально пустые или почти пустые — это точки для подключения доработок. Заимствуйте такой модуль и повесьте &После на нужную процедуру. Код типовой при этом остаётся нетронутым, а риск конфликта при обновлении минимальный.

Способ 3. Вызов по имени

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

Выбирайте &Перед и &После, где только можно. &Вместо без ПродолжитьВызов() молча отключает часть типовой логики, и после очередного обновления этого никто не заметит.

Отладка и типичные ошибки модулей расширения

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

Диагностика: выберите симптом

Ещё две ловушки, которые встречаются у разработчиков:

  • ⚠️ Совпадение имени. Если в новом релизе типовой появился объект с тем же именем, что и ваш, расширение не применится. Префикс почти полностью снимает этот риск.
  • ⚠️ Тестирование на рабочей базе. Отлаживайте расширение на копии. Ошибка в обработчике ПередЗаписью с Отказ = Истина заблокирует запись документов у всех пользователей сразу.

Производительность общих модулей расширения

Код в расширении работает с той же скоростью, что и в основной конфигурации. Тормозит не расширение, а то, как написаны вызовы.

Сократите серверные вызовы

Каждый вызов метода модуля с флажком «Вызов сервера» — это обращение клиента к серверу. В веб-клиенте и по медленному каналу каждое такое обращение заметно.

  • 📦 Собирайте данные за один вызов: верните структуру из пяти полей вместо пяти вызовов по одному значению.
  • 🔁 Никогда не вызывайте сервер в цикле на клиенте. Передайте массив ссылок одним вызовом.
  • 🧹 Не перехватывайте частые клиентские события (ПриИзменении реквизита в табличной части) обращением к серверу без необходимости.

Используйте повторное использование

Модуль со свойством «Повторное использование возвращаемых значений» кэширует результаты функций. Два режима:

  • На время вызова — кэш живёт, пока выполняется один серверный вызов. Удобно, когда одна и та же настройка читается много раз в рамках проведения.
  • На время сеанса — кэш хранится дольше. Подходит для констант и настроек, которые меняются редко.

Правила для кэшируемого модуля:

  1. В нём только функции — процедуры кэшировать нечего.
  2. Возвращайте ФиксированнаяСтруктура или ФиксированныйМассив. Иначе вызывающий код может изменить значение прямо в кэше.
  3. Не кладите туда данные, которые пользователь меняет в течение дня. Он не увидит изменений до сброса кэша.
  4. Сбросить кэш из кода можно методом ОбновитьПовторноИспользуемыеЗначения().

Следите за перехватами

&Перед и &После на методе, который вызывается тысячи раз (например, в цикле по строкам табличной части), умножают нагрузку. Делайте в таком обработчике только быстрые проверки, а запрос к базе выносите за пределы цикла: соберите все ссылки и прочитайте данные одним запросом.

Замер производительности в Конфигураторе (Отладка → Замер производительности) показывает время и число вызовов по строкам кода, включая модули расширения. Начинайте оптимизацию с него, а не с догадок.

Частые вопросы

Можно ли добавить общий модуль в расширение, если основная конфигурация на поддержке?
Да. Расширение не меняет основную конфигурацию и не снимает её с поддержки. Для этого расширения и придуманы.
Нужен ли монопольный режим, чтобы применить расширение?
Для расширений без собственных данных обычно нет. Пользователи увидят изменения после перезапуска своих сеансов.
Можно ли из основной конфигурации вызвать собственный модуль расширения?
Напрямую — нет: типовая о нём не знает. Связь делают из расширения через перехват метода или переопределяемый модуль БСП.
Чем заимствованный модуль отличается от собственного?
Заимствованный — это ссылка на модуль типовой, в нём пишут только перехваты методов. Собственный модуль целиком ваш, с любыми процедурами.
Работают ли общие модули расширения в веб-клиенте и мобильном клиенте?
В веб-клиенте — да, если стоит флажок «Клиент (управляемое приложение)». Для мобильного клиента нужно проверять, поддерживает ли конфигурация этот режим.