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