Общий модуль в расширении конфигурации: создание, свойства и связь с типовой
Содержание
Общий модуль добавляют в расширение в Конфигураторе. Откройте Конфигурация → Расширения конфигурации, выберите расширение и нажмите «Открыть конфигурацию». В дереве расширения правой кнопкой щёлкните по ветке Общие → Общие модули и выберите «Добавить». Затем отметьте, где будет работать код (Сервер, Клиент, Вызов сервера), напишите экспортные процедуры и выполните «Обновить конфигурацию
базы данных» для расширения (F7 в окне расширения).
Так обычно и начинается доработка типовой: бухгалтер просит, чтобы при записи реализации проверялся лимит по договору. Править типовую БП или УТ нельзя — потеряется лёгкое обновление. Поэтому общий модуль с проверкой кладут в расширение, а в типовую «врезаются» через заимствование. Всё ниже относится к платформе 1С:Предприятие 8.3 (расширения появились в версии 8.3.6) и одинаково для любой конфигурации.
Подготовка расширения перед созданием модуля
Если расширения ещё нет, создайте его: в окне Расширения конфигурации нажмите «Добавить». Платформа создаст пустую конфигурацию-расширение и откроет её свойства.
В свойствах расширения проверьте три поля:
- 🏷️ Префикс имён — например,
Расш1_или короткий код вашей компании. Конфигуратор сам подставляет его в имена новых объектов. Префикс защищает от совпадения имён с объектами типовой после её обновления. - 🎯 Назначение — «Исправление», «Адаптация» или «Дополнение». Для своих доработок чаще всего ставят «Адаптация» или «Дополнение». От назначения зависит порядок применения нескольких расширений.
- 🔒 Безопасный режим — если расширение работает в безопасном режиме, код в нём не сможет выполнять потенциально опасные действия: работу с файлами на сервере, внешние компоненты, COM. Решите это заранее, а не после ошибки в рабочей базе.
Держите отдельное расширение под каждую задачу. Одно «большое» расширение со всеми доработками сложно отключить частично, когда что-то сломалось.
Как добавить новый общий модуль в расширение 1С
Новый (собственный) общий модуль — это модуль, которого нет в основной конфигурации. Он целиком принадлежит расширению.
Шаг 1. Создание объекта
- Откройте дерево расширения.
- Разверните ветку
Общие, щёлкните правой кнопкой поОбщие модулии выберите «Добавить». - Задайте имя. Префикс уже стоит в начале, допишите смысл:
Расш1_КонтрольЛимитовСервер. - Заполните синоним — его увидят в сообщениях об ошибках и в отладчике.
Шаг 2. Свойства
В палитре свойств отметьте флажки контекста. Подробно о них — в следующем разделе. Минимальный набор для серверной логики: только «Сервер».
Шаг 3. Код и применение
- Двойным щелчком откройте модуль и напишите процедуры с ключевым словом
Экспорт. - Проверьте синтаксис:
Ctrl+F7или команда проверки модулей в менюКонфигурацияокна расширения. - Выполните «Обновить конфигурацию базы данных» (F7) в окне расширения.
- Перезапустите сеанс 1С:Предприятия — уже открытые сеансы новое расширение не увидят.
Если расширение подключено к рабочей базе, где сидят пользователи, изменения подхватятся только при их следующем входе. Предупредите людей заранее.
Чтобы перенести готовое расширение в другую базу, сохраните его в файл .cfe через меню Конфигурация → Сохранить в файл в окне расширения. В целевой базе загрузите файл и отдельно выполните обновление конфигурации
базы данных — это два разных шага.
Свойства общего модуля в расширении: где выполняется код
Флажки в свойствах определяют, в каком контексте модуль скомпилируется и откуда его можно вызвать. Это главное место, где ошибаются при переносе кода.
| Свойство | Что даёт | Когда ставить |
|---|---|---|
| Сервер | Модуль доступен в серверном коде | Запросы, запись объектов, расчёты |
| Клиент (управляемое приложение) | Модуль доступен на тонком и веб-клиенте | Диалоги, оповещения, работа с формой |
| Вызов сервера | Экспортные методы можно вызывать с клиента | «Мост» с клиента на сервер |
| Внешнее соединение | Доступ при подключении через COM | Интеграции, внешние обработки через COM |
| Клиент (обычное приложение) | Доступ в толстом клиенте обычного приложения | Только для старых конфигураций на обычных формах |
| Привилегированный | Код выполняется без проверки прав | Служебные операции, которым не хватает прав пользователя |
| Глобальный | Методы вызываются без имени модуля | Почти никогда — засоряет пространство имён |
| Повторное использование возвращаемых значений | Кэш результатов функций | Справочные данные, которые редко меняются |
Флажок «Вызов сервера» имеет смысл только вместе с «Сервер». Клиентский код не может обратиться к модулю, у которого стоит один «Сервер», — нужен именно «Вызов сервера».
«Привилегированный» отключает проверку прав для всего кода модуля. Не кладите туда методы, которые принимают с клиента произвольные параметры: это лазейка в обход ролей. Привилегированный модуль делайте только серверным и держите в нём минимум кода.
Схема разделения на несколько модулей
Удобно сразу делить логику по контексту, как это сделано в типовых на БСП:
- 🖥️
Расш1_КонтрольЛимитовСервер— флажок «Сервер», вся работа с базой. - 🔁
Расш1_КонтрольЛимитовВызовСервера— «Сервер» + «Вызов сервера», тонкая обёртка для клиента. - 💻
Расш1_КонтрольЛимитовКлиент— «Клиент (управляемое приложение)», сообщения и диалоги. - 🧩
Расш1_КонтрольЛимитовПовтИсп— «Сервер» + повторное использование, кэш настроек.
Суффиксы Сервер, Клиент, ВызовСервера, ПовтИсп — договорённость, а не требование платформы. Но с ними с первого взгляда ясно, где выполняется метод.
Код общего модуля: экспорт, контекст и инструкции препроцессора
Директивы компиляции &НаКлиенте, &НаСервере, &НаСервереБезКонтекста пишут в модулях форм и команд. В общем модуле их нет: контекст задают флажки свойств из раздела выше.
Если модуль собирается и на клиенте, и на сервере (стоят оба флажка), разделяйте код инструкциями препроцессора:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Возвращает остаток лимита по договору в рублях.
Функция ОстатокЛимита(Договор) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Договоры.Расш1_Лимит КАК Лимит
|ИЗ
| Справочник.ДоговорыКонтрагентов КАК Договоры
|ГДЕ
| Договоры.Ссылка = &Договор";
Запрос.УстановитьПараметр("Договор", Договор);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Лимит;
КонецЕсли;
Возврат 0;
КонецФункции
#КонецЕсли
Реквизит Расш1_Лимит в примере добавлен в заимствованный справочник тем же расширением. Без такого реквизита запрос не скомпилируется — замените поле на своё.
Правила, которые экономят время на отладке:
- ✅ Без слова
Экспортметод не виден за пределами модуля. Это самая частая причина ошибки «Метод объекта не обнаружен ». - ✅ Обращайтесь к методу через имя модуля:
Расш1_КонтрольЛимитовСервер.ОстатокЛимита(Договор). - ✅ С клиента на сервер передавайте ссылки и примитивные значения, а не объекты. Объект справочника на клиент не передаётся.
- ✅ Комментарий над экспортным методом показывается в контекстной подсказке — описывайте параметры и возвращаемое значение.
Как связать модуль расширения с типовой конфигурацией
Основная конфигурация ничего не знает о собственных объектах расширения. Написать вызов Расш1_... в модуле типовой нельзя — типовую вы не меняете. Поэтому связь строится от расширения к типовой.
Способ 1. Заимствовать модуль типовой и перехватить метод
- В окне расширения откройте дерево основной конфигурации (кнопка показа основной конфигурации или отдельное окно
Конфигурация → Открыть конфигурацию). - Найдите нужный общий модуль, щёлкните правой кнопкой и выберите «Добавить в расширение». Модуль появится в дереве расширения как заимствованный.
- Откройте модуль типовой, встаньте в нужную процедуру, правой кнопкой — «Добавить в расширение». Платформа предложит вид перехвата и создаст заготовку.
Виды перехвата:
| Аннотация | Что делает | Риск при обновлении типовой |
|---|---|---|
&Перед("Метод") | Ваш код выполняется до исходного | Низкий |
&После("Метод") | Ваш код выполняется после исходного | Низкий |
&Вместо("Метод") | Ваш код заменяет исходный; оригинал вызывается через ПродолжитьВызов() | Средний: легко потерять логику типовой |
&ИзменениеИКонтроль("Метод") | Копия метода с правками, платформа сверяет текст с оригиналом | Расширение не применится, если метод в типовой изменился |
Пример: перед записью документа вызываем свою проверку лимита.
&После("ПередЗаписью")
Процедура Расш1_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если Отказ Тогда
Возврат;
КонецЕсли;
Расш1_КонтрольЛимитовСервер.ПроверитьЛимит(ЭтотОбъект, Отказ);
КонецПроцедуры
Это обработчик в модуле заимствованного документа, а не в общем модуле. Именно отсюда управление уходит в ваш общий модуль. ПроверитьЛимит — ваша экспортная процедура, которую нужно дописать по образцу функции из прошлого раздела.
Способ 2. Переопределяемые модули БСП
В типовых на БСП есть общие модули с окончанием Переопределяемый. Их процедуры специально пустые или почти пустые — это точки для подключения доработок. Заимствуйте такой модуль и повесьте &После на нужную процедуру. Код типовой при этом остаётся нетронутым, а риск конфликта при обновлении минимальный.
Способ 3. Вызов по имени
В конфигурациях на БСП есть функция ОбщегоНазначения.ОбщийМодуль("ИмяМодуля"). Она возвращает модуль по имени строкой. Так из заимствованного кода можно обратиться к модулю, существование которого заранее не гарантировано. Пользуйтесь этим осторожно: ошибка в имени всплывёт только при выполнении, а не при проверке синтаксиса.
Выбирайте &Перед и &После, где только можно. &Вместо без ПродолжитьВызов() молча отключает часть типовой логики, и после очередного обновления этого никто не заметит.
Отладка и типичные ошибки модулей расширения
Точки останова в модулях расширения работают так же, как в основной конфигурации. Запустите отладку из Конфигуратора (F5), поставьте точку в модуле расширения и выполните действие в пользовательском режиме. Если отладка идёт на сервере, отладка на сервере должна быть разрешена. Для клиент-серверной базы это делается в параметрах службы агента сервера, и без доступа администратора сервера не обойтись.
Ещё две ловушки, которые встречаются у разработчиков:
- ⚠️ Совпадение имени. Если в новом релизе типовой появился объект с тем же именем, что и ваш, расширение не применится. Префикс почти полностью снимает этот риск.
- ⚠️ Тестирование на рабочей базе. Отлаживайте расширение на копии. Ошибка в обработчике
ПередЗаписьюсОтказ = Истиназаблокирует запись документов у всех пользователей сразу.
Производительность общих модулей расширения
Код в расширении работает с той же скоростью, что и в основной конфигурации. Тормозит не расширение, а то, как написаны вызовы.
Сократите серверные вызовы
Каждый вызов метода модуля с флажком «Вызов сервера» — это обращение клиента к серверу. В веб-клиенте и по медленному каналу каждое такое обращение заметно.
- 📦 Собирайте данные за один вызов: верните структуру из пяти полей вместо пяти вызовов по одному значению.
- 🔁 Никогда не вызывайте сервер в цикле на клиенте. Передайте массив ссылок одним вызовом.
- 🧹 Не перехватывайте частые клиентские события (
ПриИзмененииреквизита в табличной части) обращением к серверу без необходимости.
Используйте повторное использование
Модуль со свойством «Повторное использование возвращаемых значений» кэширует результаты функций. Два режима:
- На время вызова — кэш живёт, пока выполняется один серверный вызов. Удобно, когда одна и та же настройка читается много раз в рамках проведения.
- На время сеанса — кэш хранится дольше. Подходит для констант и настроек, которые меняются редко.
Правила для кэшируемого модуля:
- В нём только функции — процедуры кэшировать нечего.
- Возвращайте
ФиксированнаяСтруктураилиФиксированныйМассив. Иначе вызывающий код может изменить значение прямо в кэше. - Не кладите туда данные, которые пользователь меняет в течение дня. Он не увидит изменений до сброса кэша.
- Сбросить кэш из кода можно методом
ОбновитьПовторноИспользуемыеЗначения().
Следите за перехватами
&Перед и &После на методе, который вызывается тысячи раз (например, в цикле по строкам табличной части), умножают нагрузку. Делайте в таком обработчике только быстрые проверки, а запрос к базе выносите за пределы цикла: соберите все ссылки и прочитайте данные одним запросом.
Замер производительности в Конфигураторе (Отладка → Замер производительности) показывает время и число вызовов по строкам кода, включая модули расширения. Начинайте оптимизацию с него, а не с догадок.