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