О реверс-инжиниринге, самопознании и альтернативной навигации

Список из двух всем известных российских бед я дополнил бы третьей – отсутствием документации при разработке ПО. Лично я столкнулся со всеобъемлющим описанием системы лишь однажды. Это была разработка специалистов новосибирского Академгородка. С их слов, на написание документации у них уходило до пятидесяти процентов времени. Признаемся честно, разработчики на Prognoz Platform в этом грехе не замечены. А необходимость в доработках давно написанных систем возникает. И непременно дорабатывать приходится не тем, кто мог бы что-то об этих системах помнить. Попытку разобраться в чужой системе без документации называют реверс-инжинирингом. Об опыте моего приобщения к этому красивому названию посредством репозитория Prognoz Platform я и хочу рассказать.

Опишу условия задачи. Не пугайтесь, их немного. Собственно, известно было только одно – имя таблицы в БД, в которую загружались данные из внешних источников. Называлась таблица, скажем, SOURCE_DATA. Структура данных, получаемых из внешних источников, изменилась, и необходимо было определить, какие объекты репозитория придется доработать, если внести изменения в указанную таблицу.

В репозитории Prognoz Platform имеется удобный способ подключения таблицы БД для использования ее в других объектах репозитория – создание метаобъекта «Присоединенная таблица». Можно создать такой метаобъект и дать ему осмысленное имя или идентификатор, содержащие имя таблицы БД. В нашем случае, например, TBL_SOURCE_DATA. После этого любой погрузившийся в сладостный, волшебный, поэтический мир реверс-инжиниринга может найти эту таблицу в навигаторе с помощью встроенного в Prognoz поиска объектов репозитория по наименованию или идентификатору. Далее с помощью стандартного же просмотра свойств можно пройти всю цепочку связанных объектов.

Но это слишком просто. Это не для нас. Таблицу БД можно запрятать в текст SQL-запроса метаобъекта репозитория типа «Запрос». А если ни в названии, ни в идентификаторе метаобъекта не отразить название таблицы, то остается только открывать в редакторе навигатора Prognoz подряд все метаобъекты типа «Запрос» и на закладке «Свойства запроса» глазками искать в тексте название. Вслед за Чернышевским и Лениным вопрошаю: «Что делать?».

Двести лет назад Гегель (да, я не прогуливал лекции по философии) пришел к мысли – мировой дух создал человека для того, чтобы через его познавательную деятельность познать себя и созданный им окружающий мир. К нашему счастью, в Prognoz Platform также имеется инструмент, с помощью которого можно познать созданный им «мир», ну, в смысле, репозиторий. Это язык FORE. В FORE имеется возможность пройтись по всем объектам репозитория и обратиться к любому их свойству.

Для прохода по дереву метаобъектов репозитория используем интерфейс IMetabaseObjectDescriptor, для доступа к тексту запроса – IQuery и IView. Идентификаторы найденных метаобъектов выводим в консоль. Вот полный текст модуля на FORE:

<em>Sub Main; Begin Search(metabaseclass.Active.Root, "SOURCE_DATA"); End Sub Main; Const DriverCode = "MSSQL2005"; Sub Search(parent: IMetabaseObjectDescriptor; TextToFind: string); Var Descr: IMetabaseObjectDescriptor; OK: boolean; SQLText: string; Begin For Each Descr In parent.children Do //Поиск текста в названии или идентификаторе метаобъекта OK := (string.ToUpper(Descr.Name).IndexOf(TextToFind)>-1) Or (string.ToUpper(Descr.Id).IndexOf(TextToFind)>-1); If ((Descr.ClassId=MetabaseObjectClass.KE_CLASS_EXTERNTABLE) Or (Descr.ClassId=MetabaseObjectClass.KE_CLASS_TABLE)) And (string.ToUpper((Descr.bind As ITable).NativeName) = TextToFind) Then //Поиск присоединенной таблицы OK := True; End If; If (Descr.ClassId=MetabaseObjectClass.KE_CLASS_QUERY) Or (Descr.ClassId=MetabaseObjectClass.KE_CLASS_VIEW) Then //Поиск в тексте запроса If Descr.ClassId=MetabaseObjectClass.KE_CLASS_QUERY Then SQLText := (Descr.bind As IQuery).SqlText(DriverCode); Else SQLText := (Descr.bind As IView).SqlText(DriverCode); End If; If string.ToUpper(SQLText).IndexOf(TextToFind)<>-1 Then OK := True; End If; End If; If OK Then debug.WriteLine(Descr.Id); End If; Search(Descr, TextToFind); End For; End Sub Search;</em>

Запускаем на выполнение и смотрим в окно консоли. Вуаля:

  • COMMON_SOURCE_DATA
  • OBJ7038211
  • OUR_DATA

Найдены три метаобъекта. Первый найден по контексту «SOURCE_DATA» в идентификаторе, второй – по контексту в тексте запроса, третий – по физическому имени прикрепленной таблицы. По этим идентификаторам объекты можно найти и просмотреть в стандартном навигаторе объектов репозитория.

На этом можно было бы и остановиться. Но ведь неудобно поиск производить в модуле, а просматривать найденные объекты в стандартном навигаторе. Да и во вкус я вошел: не хочу быть черной крестьянкой, хочу быть столбовою дворянкой… Поэтому перейдем к созданию (естественно, в свободное от работы время) GUI с помощью метаобъекта «Форма».

Вот что получилось:

Действует эта форма так. Название искомой таблицы вводим в однострочном редакторе 1 и нажимаем кнопку «Поиск». Если необходимо искать по имени или идентификатору, используем группу 2. Найденные объекты выводятся в виде древовидного списка 3. В этом списке кроме найденных объектов иерархически отображаются метаобъекты, которые от них зависят. Например, от найденного объекта «Запрос7038211» зависит справочник «Табличный справочник7038231», а от него, в свою очередь, – «Стандартный куб7038291». При отметке элемента в дереве 3 в дереве 4 отображаются метаобъекты, из которых он состоит, а в текстовом редакторе 5 сразу видны параметры метаобъекта с их значениями по умолчанию, формулы управления параметрами вложенных объектов и текст запроса для метаобъектов типа «Запрос».

По нажатии кнопки «Перейти» фокус формы устанавливается на объект в дереве 6, соответствующий объекту, выделенному в окне 3. Дерево 6 повторяет дерево объектов стандартного навигатора и отображает расположение объектов в папках репозитория. То есть имеется возможность перехода между альтернативными навигаторами: навигатору по расположению объектов в репозитории и навигатору по зависимости объектов друг от друга.

Мы получили удобный инструмент для анализа репозитория Prognoz. Например, в нашей форме мы видим:

То есть данные для куба «Стандартный куб7038291» выбираются из таблицы БД запросом:

SELECT * from SOURCE_DATA WHERE item=:ITEM,

где параметр :ITEM принимает значение по умолчанию равное четырем.

Чтобы получить эту же информацию по объекту стандартными средствами навигатора Prognoz Platform, потребовалось бы выполнить ряд действий: открыть окно свойств куба, перейти к закладке «Состоит из», выбрать метаобъект «Запрос7038211», открыть его на редактирование, на закладке «Свойства» просмотреть текст запроса, а на закладке «Параметры» открыть на редактирование параметр «ITEM» и просмотреть его значение по умолчанию.

Читайте также

Комментарии

Подробнее о политике использования персональных данных