При работе с управляемыми формами в платформе «1С:Предприятие 8.3» разработчики часто сталкиваются с крайне странным поведением системы. Сценарий выглядит следующим образом: пользователь открывает форму списка документов или справочника, и система внезапно выдает ошибку компиляции вида «Переменная не определена (ИмяОбщегоМодуля)» или «Не найден общий модуль». При этом самое загадочное заключается в том, что в самом модуле открываемой управляемой формы вообще нет никакого кода — там все настроено по умолчанию. Ошибка при этом указывает на строку кода, расположенную в модуле менеджера совершенно другого прикладного объекта (например, справочника, связанного с этим документом).
Ситуация становится еще более запутанной, когда мы пытаемся воспроизвести баг в других условиях. На файловой копии базы ошибка пропадает. При запуске отладки из конфигуратора — всё работает отлично. На другом сервере SQL — тоже тишина. Но на рабочем сервере у пользователя стабильно воспроизводится сбой. В этой статье мы подробно разберем природу этого поведения платформы «1С:Предприятие», выясним реальные причины различий при запуске базы в разных окружениях и рассмотрим надежные стандарты разработки для полного устранения проблемы.
Разрабатывая современные конфигурации на управляемых формах, мы привыкаем к парадигме клиент-серверного разделения. Мы знаем, что код модулей объектов, модулей менеджеров и модуля сеанса по умолчанию должен выполняться на стороне сервера. В этих модулях мы смело пишем вызовы серверных общих модулей, у которых в свойствах не установлена галочка Клиент (управляемое приложение).
Однако всё кардинально меняется, когда база запускается в режиме Толстого клиента (управляемое приложение). Давайте проанализируем, как ведет себя платформа в этом случае:
В Тонком клиенте такой проблемы не возникает физически, поскольку тонкий клиент вообще не компилирует модули менеджеров у себя — он всегда делегирует вызовы к ним на сервер.
Давайте разберем по шагам причины столь разного поведения системы в различных сценариях, которые часто сбивают с толку даже опытных разработчиков:
1. Отладка из конфигуратора. В настройках конфигуратора («Сервис» -> «Параметры» -> «Запуск 1С:Предприятия») по умолчанию для управляемого приложения чаще всего жестко задан запуск в режиме Тонкий клиент. Когда разработчик нажимает кнопку «F5» для отладки под тем же пользователем, запускается именно тонкий клиент. Ошибка компиляции модуля менеджера не происходит, и система работает штатно.
2. Копия базы на другом сервере. При создании копии базы на другом SQL-сервере или на локальном компьютере, в списке баз пользователя (в файле ibases.v8i) создается совершенно новая запись. По умолчанию для новых записей в поле «Режим запуска» устанавливается значение Выбирать автоматически. Платформа анализирует возможности и запускает более современный и легкий Тонкий клиент. В оригинальной же базе у пользователя в свойствах подключения мог быть принудительно прописан Толстый клиент.
3. Файловая версия. В файловом варианте работы разница между клиентским и серверным контекстами сильно сглажена, так как и клиент, и сервер фактически работают в рамках одного процесса на локальном компьютере. Многие серверные вызовы там отрабатывают без жестких ошибок компиляции, которые мгновенно проявляются в полноценной клиент-серверной архитектуре.
Простое оборачивание одной конфликтующей строки в условие #Если Сервер Тогда — это временное и локальное решение, которое не гарантирует защиту от аналогичных ошибок при написании нового кода в этом же модуле. Согласно официальным стандартам разработки фирмы «1С» (требования к поддержке толстого клиента в управляемом приложении), весь код модуля менеджера должен быть строго разделен по контекстам выполнения.
Для модулей менеджеров рекомендуется оборачивать абсолютно весь код (за исключением специфических обработчиков получения представления, если они обязаны отрабатывать на клиенте для оптимизации скорости) в следующую инструкцию препроцессора:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Весь основной код модуля менеджера:
// Процедуры, функции, экспортные методы, вызовы серверных общих модулей.
#КонецЕсли
Для модулей объектов (справочников, документов, процессов) стандарт еще более жесткий. Там рекомендуется использовать следующую защитную конструкцию препроцессора, которая не только предотвращает компиляцию кода на клиенте, но и генерирует понятное исключение при попытке некорректного вызова:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Основной код модуля объекта (ПередЗаписью, ПриЗаписи, обработчики бизнес-логики)
#Иначе
ВызватьИсключение NStr("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли
Рассмотрим комплекс превентивных мер, которые позволят вам раз и навсегда обезопасить вашу конфигурацию от «фантомных» ошибок компиляции контекста:
Для того чтобы находить проблемные места в коде до того, как они попадут в рабочую базу к пользователям, обязательно используйте встроенную проверку конфигурации в конфигураторе. Для этого:
Если ваша конфигурация полностью спроектирована под управляемый интерфейс, эксплуатация её в режиме Толстого клиента нецелесообразна и повышает нагрузку на рабочие станции пользователей. Рекомендуется перевести всех сотрудников на Тонкий клиент:
Выбирать автоматически или Толстый клиент принудительно установите «Тонкий клиент».Если в вашей системе активно применяются расширения, помните, что модули расширений подчиняются тем же правилам компиляции препроцессора. Код в расширениях, перехватывающий методы модулей менеджеров или объектов (с помощью аннотаций &Перед, &После или &Вместо), также должен корректно обрабатывать контекст Толстого клиента. Не забывайте оборачивать заимствованные методы в соответствующие директивы препроцессора.