В процессе сопровождения старых конфигураций, созданных на базе 1С:Управление торговлей 10.2 или аналогичных решений той эпохи, разработчики часто сталкиваются с наследием «глобальных» общих модулей. В те времена это казалось удобным: можно было вызывать функции напрямую, не указывая имя модуля. Однако современные стандарты разработки, а также внедрение расширений и подсистем, диктуют иные правила. Глобальные модули становятся причиной конфликтов имен («метод уже определен»), замедляют запуск системы и затрудняют чтение кода. В данной статье мы разберем, как системно подойти к вопросу деглобализации модулей и автоматизировать замену тысяч вызовов.
Прежде чем мы перейдем к техническим решениям, проанализируем ситуацию. Когда модуль помечен флагом Глобальный, все его экспортные процедуры и функции попадают в общий контекст конфигурации. Если у вас есть 400 методов в таком модуле, то при запуске сеанса все они компилируются и удерживаются в памяти. При использовании расширений 1С часто возникают конфликты: если в расширении объявлен метод с таким же именем, система выдаст ошибку. Единственный верный путь — снять флаг Глобальный и добавить имя модуля перед каждым вызовом метода.
Рассмотрим наиболее современный способ решения задачи. Если ваша конфигурация позволяет выполнить импорт в среду разработки EDT, это будет самым безопасным вариантом. В отличие от стандартного Конфигуратора, EDT строит полный индекс проекта и понимает семантику кода.
Разберем по шагам, как выполнить рефакторинг в EDT:
Преимущество EDT заключается в том, что среда понимает контекст: она не заменит локальную переменную с тем же именем на вызов модуля, что часто случается при «слепой» текстовой замене.
Проанализируем ситуацию, когда методов сотни, а вызовов — тысячи, и использование EDT по каким-то причинам невозможно. В этом случае мы воспользуемся механизмом выгрузки конфигурации в файлы. Это позволит нам работать с кодом как с обычным текстом.
Выполним следующие действия:
Рассмотрим правильное составление регулярного выражения. Простая замена ИмяМетода на ИмяМодуля.ИмяМетода — это опасная ловушка. Мы можем случайно изменить комментарии, строковые константы или части других слов.
Используем паттерн с «негативным просмотром назад». Пример для Notepad++:
Найти: (?<![\.\w])ИмяМетода\s*\(
Заменить на: ИмяМодуля.ИмяМетода(
Разберем, что делает этот код: конструкция (?<![\.\w]) проверяет, что перед именем метода нет точки (значит, имя модуля еще не добавлено) и нет буквенно-цифровых символов (значит, это не часть другого имени, например Префикс_ИмяМетода).
Если модулей много, и для каждого нужно составить таблицу замен, ручная работа в текстовом редакторе может занять вечность. Проанализируем способ автоматизации через OneScript. Мы можем написать скрипт, который сам сформирует список экспортных методов и проведет замену.
Посмотрим на пример логики скрипта, который можно реализовать:
// Пример логики для получения списка методов из файла модуля
ТекстМодуля = ЧтениеТекста.Прочитать(ПутьКФайлу);
// Регулярное выражение для поиска экспортных процедур и функций
РегЭкспо = Новый РегулярноеВыражение("(Процедура|Функция)\s+(\w+)\s*\(.*Экспорт", Истина);
Результаты = РегЭкспо.НайтиСовпадения(ТекстМодуля);
Для Каждого Матч Из Результаты Цикл
ИмяМетода = Матч.Подгруппы[1].Значение;
// Добавляем в таблицу замен
КонецЦикла;
После формирования таблицы замен («СтароеИмя» -> «ИмяМодуля.СтароеИмя»), скрипт должен обойти все файлы в папке src (модули форм, модули объектов, общие модули) и выполнить замену. Важно помнить, что файлы конфигурации в формате XML содержат модули внутри тегов <source> или в отдельных .bsl файлах в зависимости от версии выгрузки.
Иногда объем изменений настолько велик, что страшно сломать систему в один момент. В таком случае рассмотрим стратегию постепенного перехода через модули-врапперы.
ОбщегоНазначенияКлиентСервер (неглобальный).ОбщегоНазначения.Пример кода в старом (пока еще глобальном) модуле:
Процедура ПолучитьДанныеСервера(Параметр) Экспорт
// Вызываем метод уже из нового неглобального модуля
ОбщегоНазначенияКлиентСервер.ПолучитьДанныеСервера(Параметр);
КонецПроцедуры
Это позволит вам постепенно, по мере правки конкретных участков кода, менять прямые вызовы на вызовы с указанием модуля. Как только количество вызовов старого метода станет нулевым (что легко проверить глобальным поиском), метод из глобального модуля можно удалять. Когда методов не останется — удаляйте сам модуль.
При выполнении массовой замены вызовов, проанализируем критические моменты, которые могут привести к ошибкам компиляции:
Настройка = 1;, а в глобальном модуле есть функция Настройка(), то слепая замена превратит код в Модуль.Настройка = 1;, что приведет к ошибке.ИмяФ = "МояФункция"; Выполнить(ИмяФ + "()");. Такие места придется искать и править вручную..txt или .bsl, которые отвечают за программный код форм.Мы рассмотрели несколько путей деглобализации кода. Выбор метода зависит от ваших ресурсов: EDT — самый надежный и интеллектуальный способ; RegEx + выгрузка в файлы — самый быстрый для огромных объемов; Модули-переходники — самый безопасный для живой, постоянно обновляемой системы.
После проведения всех замен обязательно выполните Синтаксический контроль всей конфигурации (желательно для всех вариантов: Тонкий клиент, Сервер, Внешнее соединение). Это позволит выявить пропущенные точки вызова или ошибки, возникшие из-за совпадения имен переменных и методов.