Как в 1С 7.7 определить дополнительные модули


В статье представлен способ добавления новых (локальных) программных модулей в конфигурации 1С:Предприятие, версии 7.7, наподобие того, как это возможно в версии 8.Х. Указанный способ построен на использовании компонент 1С++.

В 1С 8 реализована одна очень приятная особенность — создание нескольких модулей, дополнительных к глобальному. В 1С 7.7 все «свалено в кучу» в глобальном модуле. Я нахожу это очень неудобным. Приходится все время листать этот «здоровенный» список в поисках нужной процедуры, а обилие посторонней информации, при этом, просто утомляет.

Почему разработчики платформы 1С 7.7 изначально не включили такую возможность — уму непостижимо. По всей видимости, они всерьез не задумывались о том, что на их платформе будут реализовывать сложные приложения.

Однако есть возможность эту проблему как то решить. Эта возможность появилась благодаря разработчикам проекта «1С++» [ссылка на проект], в частности, Дмитрию Гусеву aka Deb — разработчику класса «ВыполняемыйМодуль» и Алексею Фёдорову aka АЛьФ — разработчику компоненты «FormEx». Благодаря им, работать с 1С 7.7 не так скучно и уныло, как изначально планировалось.

Что мы, по-сути, сейчас сделаем. В дереве конфигурации новой информационной базы создадим обработку «ТестМодуль» в модуле которой разместим следующий текст:

//*******************************************
Процедура Выполнить()
 
// реализация метода модуля:
 
    Сообщить("""ТестМодуль"" успешно загружен");
 
КонецПроцедуры
//*******************************************
// {{Удалить
 
Процедура ПриОткрытии()
 
// "открывать" в действительности форму обработки
// мы, конечно же, не будем:
 
    СтатусВозврата(0);
 
// подключение расширения формы в целях доступа к
// тексту модуля данной обработки:
 
    ФормаРасш = СоздатьОбъект("РасширениеФормы");
    ФормаРасш.УстановитьФорму(Форма);
 
// получение текста модуля:
 
    стрИсхТекст = ФормаРасш.ТекстМодуля;
 
// инициализация начальных значений
 
    стрРезТекст = ""; // загружаемого текста модуля
 
    ИсключатьТекст = 0; // флага исключения строк модуля
 
// в цикле по строкам модуля обработки:
 
    Для й = 1 По СтрКоличествоСтрок(стрИсхТекст) Цикл
 
// для каждой строки:
 
        стрТекст = СокрЛП(СтрПолучитьСтроку(стрИсхТекст, й));
 
        Если ИсключатьТекст = 0 Тогда
 
// либо включаем ее в состав загружаемого модуля:
 
            стрРезТекст = стрРезТекст
                + стрТекст + РазделительСтрок;
        Иначе
 
// ... либо - нет
 
        КонецЕсли;
 
// принимаем решение об исключении блока текста
// программного модуля:
 
        Если стрТекст = "// {{Удалить" Тогда
            ИсключатьТекст = 1;
 
        ИначеЕсли стрТекст = "// Удалить}}" Тогда
            ИсключатьТекст = 0;
 
        КонецЕсли;
    КонецЦикла;
 
// инициализация выполняемого модуля:
 
    глмТестМодуль = СоздатьОбъект("ВыполняемыйМодуль");
    глмТестМодуль.УстановитьМодуль(стрРезТекст);
    глмТестМодуль.ПрисоединитьТекущийМодуль();
    глмТестМодуль.НазначитьКонтекст(Контекст);
 
// компиляция ...
 
    глмТестМодуль.КомпилироватьМодуль();
 
// выполнение ...
 
    глмТестМодуль.ВыполнитьМодуль();
 
КонецПроцедуры
 
// Удалить}}

Если вкратце, то, при открытии обработки, создается объект класса «ВыполняемыйМодуль» компоненты «1С++» с загрузкой модуля обработки, без непосредственно блока инициализации, расположенного внутри комментария «{{Удалить» … «Удалить}}».

В глобальном модуле информационной базы, нужно добавить строки:

//*******************************************
// переменная-идентификатор глобального модуля
 
Перем глмТестМодуль Экспорт;
//*******************************************
Процедура ПриНачалеРаботыСистемы()
 
// инициализация модуля:
 
    ОткрытьФорму("Обработка.ТестМодуль");
 
// вызов метода модуля:
 
    глмТестМодуль.Выполнить();
 
КонецПроцедуры
//*******************************************
// подключение внешней компоненты 1С++
 
ИмяФайлаКомпоненты = "1cpp.dll";
Если ЗагрузитьВнешнююКомпоненту(ИмяФайлаКомпоненты) = 0 Тогда
 
// исключительное сообщение:
 
    Сообщить("Ошибка при загрузке внешней компоненты: "
        + ИмяФайлаКомпоненты, "!");
КонецЕсли;
 
// подключение внешней компоненты "FormEx"
 
ИмяФайлаКомпоненты = "FormEx.dll";
Если ЗагрузитьВнешнююКомпоненту(ИмяФайлаКомпоненты) = 0 Тогда
 
// исключительное сообщение:
 
    Сообщить("Ошибка при загрузке внешней компоненты: "
        + ИмяФайлаКомпоненты, "!");
КонецЕсли;

При открытии полученной конфигурации в режиме 1С: Предприятие, должно быть выведено сообщение: «Тест модуль» успешно загружен. Естественно, файлы «1cpp.dll» и «FormEx.dll» должны находиться в каталоге информационной базы. Работающий пример можно скачать здесь.

Примечание

Очевидным минусом такого решения является то, что исполнение процедур дополнительного модуля не поймать в отладчике. Можно выгрузить обработку в файл, отредактировать обработчик «ПриОткрытии», добавить интерфейс, позволяющий вызвать функции модуля с определенными значениями параметров, но это все — дополнительные действия. Такого удобства, как в реализации на 1С 8, конечно, не получить.

Тексты модулей необязательно должны храниться в конфигурации. Это могут быть и просто внешние текстовые файлы, расположенные в определенном каталоге базы данных. Просто, если расположить их в обработках конфигурации, мы имеем возможность использовать стандартный 1С-овский редактор для их правки. В рабочей реализации, описанный алгоритм построен таким образом, что для добавления нового дополнительного модуля, достаточно добавить в дереве конфигурации обработку с префиксом идентификатора «глм» и определить этот идентификатор как глобальную переменную в глобальном модуле. При запуске приложения, будет выполнен обход обработок конфигурации и инициализация дополнительных модулей. Обработчик «ПриОткрытии» формы у меня «переехал» в обработчики глобального контекста.

И, раз уж коснулись темы комментариев-меток модуля, анализируемых программно, не могу не прокомментировать возможности, в связи с этим открывающиеся. А именно, программный код может стать само-документированным в полной мере, если при помощи подобных меток, «накладывать» схему-описание модуля в какой-нибудь нотации непосредственно на программный код. Тогда можно будет, по тексту модуля, генерировать его описание в этой нотации.

Более-менее подходящую нотацию для этого дела я пока не нашел. Может быть даже, ее еще предстоит разрабатывать самостоятельно. Тем не менее, считаю, у такого подхода есть перспективы. Встать в один ряд с такими компаниями, как «Rational Software» [ссылка] или «Computer Associates» [ссылка] — по меньшей мере, романтично.