Данная
статья носит скорее теоретический характер, чем практический.
Она описывает метод, который мог бы сработать, если бы о нем задумалась 1С7 или
навалились 1С-ники коллективно.
Но, думаю, время упущено и количество переходов на 1С7 уже не так много, как
раньше.
Технология перевода кода 77 на 80.
К сожалению, разработчики
не пошли по пути обратной совместимости (хотя и могли бы). Поэтому этим путем
пойдем мы! ;-)
1С позволяет только конвертировать конфигурацию 77 на 80, при этом переносятся данные
базы, формы, макеты, прикладные объекты, но не конвертируется код модулей,
потому что он несовместим.
1С могла бы поддерживать старый и новый код, чтобы можно было постепенно
переписывать важные участки на 80, оставляя старые и непринципиальные на 77.
Но, увы.
К счастью, в беседе с Анатолием Федьковым мне пришла спасительная для кодеров
77 идея, которой я и делюсь с вами.
Она заключается в эмуляции кода 77 встроенными средствами 80. К счастью, 1С в
основном оперирует с объектами, поэтому существует очень простой способ
перехода с 77 на 80, о котором мало кто задумывался. Этот способ поможет вам
без дополнительного кодирования сделать 80% конвертации кода.
Эмуляция объектов
Нужно заменить все создаваемые
объекты 77 объектами-эмуляторами, эмулирующими работу 77. В таком случае
изменения в конфигурацию минимальны.
Такие объекты-эмуляторы имеют методы и свойства, полностью идентичные свойствам
объектов 77. К сожалению, в 80 нельзя поставить триггер на изменение свойства
объекта, поэтому в некоторых случаях (когда установка свойства влечет побочный
эффект), нужно будет поработать руками. Но таких случаев мало.
Суть в том, что объекты 77 заменяются соответствующими обработками.
Например объект «БухгалтерскиеИтоги» 77 заменяется на
объект Обработка.БухгалтерскиеИтоги77.
К счастью, функция «СоздатьОбъект» в 80 не занята,
поэтому можно поставить на нее перехватчики, который будет вместо объекта
создавать соответствующий ему объект-эмулятор:
Функция
СоздатьОбъект(ТипОбъекта) Экспорт
Если Лев(«ТипОбъекта»,10)=«Справочник» Тогда
Обработки.Справочник.Создать(ТипОбъекта);
ИначеЕсли Лев(«ТипОбъекта»,8)=«Документ» Тогда
Обработки.Документ.Создать(ТипОбъекта);
Иначе
Возврат Обработки[ТипОбъекта].Создать();
КонецЕсли;
КонецФункции
Возможно, удобнее эмулировать объекты
77 не обработками, а формами, но это помешает нам воспользоваться
преимуществами трехзвенной архитектуры, зато у форм есть ОбработчикИзмененияДанных,
реагирующий на изменение данных формы и скорее всего
можно динамически управлять составом форм. Этот вопрос нужно исследовать.
Возможно, более удобно эмулировать объекты 77 через ОЛЕ-объект, который будет содержать нужную
обработку-эмулятор, написанную на языке 77, и дополнительно отлавливать
изменение и чтение свойств, а также динамически изменять состав свойств
объектов.
Но пока в нашем распоряжении только обработки.
Эмуляторы прикладных объектов
Лучше конечно, создавать
объект-эмулятор для каждого типа прикладного объекта, чем внедрять весь
функционал 77 в каждый вид прикладного объекта 80.
Т.е. например лучше создать обработку, содержащую реквизит «НомерДок», чем у каждого документа создавать реквизит «НомерДок».
К сожалению, обработка не умеет обрабатывать событие, когда обращаются к
свойству, которого у него нет. Поэтому надежнее заменить все обращения к
реквизитам объекта 77 через, но в
принципе, можно обойтись и без этого, если при вызове метода 77 ТекущийОбъект и других подобных ему, свойства объекта считывать
в память и доступны на чтении.
В таком случае объект-эмулятор должен содержать всевозможные свойства всех
объектов.
О другом способе эмуляции читайте в разделе «Умная точка».
Умная точка
Некоторые недостатки
эмуляторов можно разрешить, если грамотно обработать исходный код 77 с помощью
регулярных выражений. Как вы знаете, в 80 можно выгрузить все модули в файлы,
обработать их, а затем загрузить обратно.
Лучше всего пометить каждую строку 77 комментарием //77 в конце, чтобы не
путать с переписанным на 80 кодом. Тогда обработки кода можно выполнять
многократно.
Итак, «умная точка». Суть в том, чтобы найти все обращения к свойствам объекта
через точку и заменить их на вызов метода ПолучитьАтрибут/УстановитьАтрибут, который должен установить свойство.
Выражение замены для чтения свойства:
Точка, за которой следует идентификатор, после которого стоит не знак «равно» -
заменить точку и идентификатор на .ПолучитьАтрибут(Идентификатор);
Выражение замены для установки свойства:
Точка, за которой следует идентификатор, после которого стоит знак «равно» и
далее идет некоторое выражение, заканчивающееся точкой с запятой, словами «КонецЕсли», «КонецЦикла», «КонецФункции», «КонецПроцедуры» и т.п. - заменить точку, идентификатор, знак
равно и выражение на .УстановитьАтрибут(Идентификатор, Выражение).
В таком случае доступ к свойствам эмулируемого объекта будет осуществляться
только через вызовы методов ПолучитьАтрибут/УстановитьАтрибут, что позволит гибко управлять чтением свойств
объектов.
Если с регулярными выражениями у вас не очень складывается, можно нанять
студента, который сам обработает эти точки (можно обработать еще в базе 77),
чтобы потом было легче переходить.
Объем работ можно оценить, запустив глобальный поиск символа «.» по конфигурации и платить студенту чисто за количество
строк. Работа-то механическая.
О развитии способа
Представляете,
труд миллиона леммингов, переводящих самописные
конфигурации из 77 в 80 оказался рабским, потому что можно было пойти
другим путем. К счастью, эта информация пригодится еще другим, переходящим с 77
на 80, программистам.
Со временем, когда конфигурация, переведенная подобным способом с 77 на 80,
заработает, можно по частям переводить ее с объектов-эмуляторов на объекты 80,
уже по ходу работы.
Контексты
Стоит обратить внимание,
что при выводе секции отчета (а также вычислении функции Шаблон) доступны все
переменные, видимые в контексте выполнения. Для 80 их нужно загонять в
параметры, лучше всего в структуру.
Формы
В формах 77 можно было
содержать вычислимые поля для надписей и ячеек таблиц значения.
В формах 80 все эти вычисления нужно перенести в событие ОбновлениеОтображения.
Периодические реквизиты справочников
Для простоты
периодические реквизиты можно хранить в одном регистре сведений с
периодичностью до даты и структурой измерений Справочник (ссылка на справочник),
Реквизит (идентификатор или значение перечисления (лучше)) и ресурсом Значение
произвольного типа.
Учитывая, что документы могут устанавливать реквизиты периодических реквизитов
справочника и при снятии с проведения эти реквизиты могут удаляться, лучше
завести регистр, не подчиненный регистратору, и реквизит этого регистра
«Документ». При снятии с проведения документа удалять все записи в этом
регистре, где реквизит «Документ» указывает на этот документ.
Константы
Самый простой способ –
создать по одному регистру сведений на каждую константу с заданной
периодичностью.
В таком случае возможна универсальная обработка для переноса констант на
заданную дату в соответствующий регистр сведений.
Ключевое слово Константа. нужно заменить на вызов СоздатьОбъект(«Константа»).
А уж реализация класса Константа в обработке Константа77 – на ваше усмотрение.
Пример:
//Исходный
код:
Константа.ОсновнойСклад
Константа.Руководитель.Получить(’12.10.1980’);
//Меняем
на:
СоздатьОбъект(«Константа»).Получить(«ОсновнойСклад») ;
СоздатьОбъект(«Константа»). Получить(«Руководитель», ’19801012’);
Ограничения
В обработках 1С8 нельзя
использовать функцию с именем Выполнить, поэтому перед запуском эмуля нужно будет выполнить глобальную замену .Выполнить на ._Выполнить.
Но по-моему в 1С7 нет объектов с методом Выполнить. ;-)
Еще один хитрый метод
Пока писалась статья, я придумал еще один хитрый
метод борьбы с ограничениями 1С. Чтобы не приходилось выискивать точки в коде,
можно поступить по другому.
Рассмотрим на примере констант.
Допустим список семерочных констант хранится в массиве
в глобальной переменной глКонстанты77.
Допустим эмулятор константы с методами Получить и
Установить у нас находится в обработке Эмулятор77_Константа.
Тогда мы создаем глобальную переменную Константа.
Далее:
Константа
= Новый Структура();
Для Каждого Эл Из лКонстанты77 Цикл
Константа.Вставить(Эл, Обработки.Эмулятор77_Константа.Создать());
КонецЦикла;
Все, никакого изменения
кода. Исходный код констант работает.
Аналогично будет работать и код справочников и документов без точек.
Достаточно только на каждый реквизит повесить обработчик.
Хороший подход, по сути, исходный код вообще не меняется.
Ссылки
Обсуждение можно почитать
здесь:
http://www.forum.mista.ru/topic.php?id=218854
http://www.forum.mista.ru/topic.php?id=371983
http://www.forum.mista.ru/topic.php?id=372222