Виды модулей
Код в 1С не висит в воздухе — он всегда лежит в конкретном модуле, и от того, в каком именно, зависит, когда и где он выполнится.
Модуль — это контейнер с текстом программы (процедурами и функциями), привязанный к определённому объекту конфигурации или к приложению в целом. Каждый вид модуля отвечает за свой участок жизни программы.
Новички часто пишут первый код куда придётся — лишь бы «заработало». Но опытный 1С-разработчик, прежде чем набрать хоть строчку, отвечает себе на два вопроса: когда этот код должен сработать и где — на клиенте или на сервере. Ответ и определяет, в какой модуль его положить. Разберём пять основных видов модулей — их хватает для 90% задач.
Зачем вообще много видов модулей
Представьте, что вся программа 1С — это большое здание. Модуль объекта — это внутренние правила конкретной комнаты (справочника «Товары» или документа «Заказ»). Общий модуль — это служба, к которой может обратиться любая комната. Модуль приложения — вахта на входе, которая срабатывает, когда кто-то заходит в здание и выходит из него. Такое разделение не прихоть: оно позволяет платформе точно знать, какой код и в какой момент грузить в память и выполнять.
Модуль объекта
Модуль объекта принадлежит конкретному справочнику, документу, регистру. Он живёт на сервере и отвечает за поведение одного экземпляра данных — например, за проверку конкретного заказа перед записью. Именно здесь размещают обработчики событий вроде ПередЗаписью или ОбработкаПроведения (о них — в следующем уроке).
// Модуль объекта документа "РасходнаяНакладная"
Процедура ПередЗаписью(Отказ)
Если Не ЗначениеЗаполнено(Контрагент) Тогда
Сообщить("Не указан контрагент — запись отменена");
Отказ = Истина; // прерываем запись
КонецЕсли;
КонецПроцедурыКлючевая мысль: код модуля объекта имеет прямой доступ к реквизитам этого объекта по имени (Контрагент, Сумма, Товары) без всяких префиксов. Здесь мы находимся «внутри» самого документа.
Модуль менеджера
Модуль менеджера тоже принадлежит объекту метаданных, но описывает поведение не одного экземпляра, а всего вида объекта в целом. Разница тонкая, но важная: модуль объекта — про «этот конкретный заказ», модуль менеджера — про «заказы вообще». Сюда кладут процедуры, которые логически относятся к справочнику или документу, но не привязаны к отдельной записи: печатные формы, вспомогательные функции создания, регламентные операции.
// Модуль менеджера справочника "Номенклатура"
Функция НайтиИлиСоздать(Наименование) Экспорт
НайденныйЭлемент = Справочники.Номенклатура.НайтиПоНаименованию(Наименование);
Если ЗначениеЗаполнено(НайденныйЭлемент) Тогда
Возврат НайденныйЭлемент;
КонецЕсли;
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Наименование = Наименование;
НовыйЭлемент.Записать();
Возврат НовыйЭлемент.Ссылка;
КонецФункцииОбратите внимание на слово Экспорт — оно делает функцию видимой снаружи. Теперь из любого другого модуля можно написать Справочники.Номенклатура.НайтиИлиСоздать("Гвозди"). Без Экспорт процедура доступна только внутри своего модуля.
Модуль формы
Модуль формы отвечает за поведение конкретной формы — окна, которое видит пользователь. Это единственный из «часто используемых» модулей, где код выполняется и на клиенте, и на сервере — в зависимости от директив компиляции &НаКлиенте и &НаСервере. Здесь живут обработчики нажатия кнопок, реакции на изменение полей, открытие и закрытие окна.
// Модуль формы документа
&НаКлиенте
Процедура РассчитатьСуммуПоКнопке(Команда)
// клиентская часть: реагирует на нажатие
ПересчитатьНаСервере();
КонецПроцедуры
&НаСервере
Процедура ПересчитатьНаСервере()
Итого = 0;
Для Каждого Строка Из Объект.Товары Цикл
Итого = Итого + Строка.Количество * Строка.Цена;
КонецЦикла;
Объект.СуммаДокумента = Итого;
КонецПроцедурыПока просто запомните: форма — это мост между пользователем (клиент) и данными (сервер). Подробно клиент и сервер разберём в третьем уроке раздела.
Общие модули
Общий модуль не привязан ни к какому объекту — это библиотека переиспользуемого кода, доступная из всей конфигурации. Хотите функцию, которая форматирует телефон или считает НДС и нужна в десяти разных документах? Ей место в общем модуле. У общего модуля есть флажки-свойства: «Клиент», «Сервер», «Вызов сервера», «Глобальный». Они определяют, откуда его процедуры можно вызывать.
// Общий модуль "РаботаСНДС" (свойство: Сервер)
Функция ВыделитьНДС(СуммаСНалогом, Ставка = 20) Экспорт
Возврат СуммаСНалогом * Ставка / (100 + Ставка);
КонецФункцииВызов из любого места: РаботаСНДС.ВыделитьНДС(1200). Флаг «Глобальный» позволяет звать функцию вообще без имени модуля, но им злоупотреблять не стоит — теряется наглядность, откуда взялась функция.
Модуль приложения
Модуль приложения (управляемого приложения) — самый «верхнеуровневый». Его код выполняется в моменты запуска и завершения программы: обработчики ПередНачаломРаботыСистемы, ПриНачалеРаботыСистемы, ПередЗавершениемРаботыСистемы. Сюда кладут стартовую логику: проверку версии, открытие начальной страницы, вывод приветствия.
// Модуль управляемого приложения
Процедура ПриНачалеРаботыСистемы()
Сообщить("Добро пожаловать, " + ПользователиИнформационнойБазы.ТекущийПользователь().Имя);
КонецПроцедурыКак это работает
Под капотом платформа компилирует модули в разные контексты выполнения. Когда пользователь открывает форму, платформа поднимает серверный контекст, выполняет там всё, что помечено &НаСервере, готовит данные и «одним пакетом» отдаёт их тонкому клиенту. Клиент рисует форму и дальше живёт в браузере (или в приложении) пользователя, обращаясь к серверу только тогда, когда явно вызывается серверная процедура. Поэтому модуль формы двухконтекстный, а модуль объекта и модуль менеджера — чисто серверные: данные обрабатываются там, где они лежат, — в базе.
Компиляция происходит лениво: модуль объекта конкретного документа попадает в память только когда с этим документом что-то делают. Это экономит ресурсы, но и объясняет, почему код одного документа не «видит» переменные другого — у каждого экземпляра свой изолированный контекст.
Частые ошибки
- Логику пишут в модуле формы вместо модуля объекта. Тогда проверка данных работает только при ручном вводе через эту форму. Загрузили документ из обмена или создали кодом — проверка молча пропущена. Бизнес-правила объекта — в модуле объекта.
- Забывают
Экспорт. Функция вроде есть, а снаружи её «не видно». Платформа выдаёт «Процедура не обнаружена» — и новичок ищет опечатку там, где её нет. - Общий модуль с неверными флагами. Пометили модуль только как «Клиент», а зовут с сервера — ошибка компиляции. Сначала решите, откуда нужен вызов, потом ставьте галочки.
- Тяжёлые вычисления в модуле приложения. Код при старте тормозит вход всех пользователей. В
ПриНачалеРаботыСистемы— только лёгкое и необходимое.
Итоги
- Модуль — контейнер кода; вид модуля задаёт, когда и где код выполнится.
- Модуль объекта — поведение одного экземпляра данных, сервер.
- Модуль менеджера — операции над видом объекта в целом, сервер.
- Модуль формы — поведение окна, двухконтекстный (клиент + сервер).
- Общий модуль — библиотека переиспользуемых процедур для всей конфигурации.
- Модуль приложения — старт и завершение работы программы.
- Чтобы вызвать процедуру снаружи модуля, пометь её словом
Экспорт.