Извлечение информацииЭтап извлечения информации подразумевает анализ фактического проектного решения и артефактов реализации системы с целью конструирования ее модели. Результатом проведения этого этапа должен стать набор информации, размещенный в базе данных, который в ходе объединения представлений обеспечивает конструирование представления системы. У процесса извлечения информации две составляющие: теоретическая (какая информация об архитектуре способна максимально повысить эффективность реконструкции?) и практическая (какую информацию можно извлечь и представить с помощью имеющихся инструментов?). Имея в наличии исходные (код, заголовочные файлы, файлы конструкций и т. д.) и другие артефакты (например, кальки исполнения), можно выявить и зафиксировать интересующие элементы системы (файлы, функции, переменные) и установленные между ними отношения; этих сведений вполне достаточно для построения базовых представлений системы. Список элементов и отношений между ними, которые в большинстве случаев удается извлечь, представлен в табл. 10.1. Все отношения между элементами по-своему содержательны. Отношение calls между функциями помогает построить граф вызываемых функций. Отношение includes между файлами сообщает о тех или иных зависимостях между системными файлами. Отношения access_read и access_write между функциями и переменными иллюстрируют использование данных — ведь одни функции записывают наборы данных, а другие их считывают. Исходя из этого можно делать выводы относительно передачи данных между различными частями системы — к примеру, установить наличие глобального хранилища данных или утвердиться во мнении о том, что основным механизмом передачи данных являются вызовы функции. положения файлов л структуре каталогов - эти данные могут пригодиться при реконструкции. Поскольку элементы или подсистемы хранятся в определенных каталогах, фиксация отношений типа dir_contains_file и dir_contains_dir помогает идентифицировать элементы и дальнейшем. Конкретный набор извлеченных элементов и отношений зависит, во-первых, от тина анализируемой системы и, во-вторых, от привлеченных инструментальных средств. Если система, которую предполагается реконструировать, относится к числу объектно-ориентированных, значит, помимо прочего, необходимо извлечь классы и методы (то есть элементы), а также отношения, например classJs_ subdass_of_class и class_contains_method. Полученная в результате анализа информация делится на статическую и динамическую. Для получения статической информации достаточно исследовать артефакты системы; динамическая информация, напротив, подразумевает анализ ее работы. В результате объединения этих двух видов можно достичь более высокой точности представления системы. (На тему объединения представлений мы поговорим в разделе 10.4.) Если архитектура системы предполагает изменения в период прогона (например, если при запуске системы она считывает конфигурационный файл, в результате чего выполняется загрузка новых элементов), при реконструкции не обойтись без фиксирования конфигурации для периода прогона. Инструментов, применяемых для извлечения информации, великое множество; в частности, среди них есть следующие: ♦ синтаксические анализаторы (например, Imagix, SNiFF++, CIA, rigiparse); ♦ анализаторы абстрактно-синтаксических деревьев (AST; например, Gen++, Refine); ♦ лексические анализаторы (например, LSME); ♦ профайлеры (например, gprof); ♦ инструменты измерения кода; ♦ специализированные средства (например, grep, peri). Синтаксические анализаторы выполняют анализ кода и генерируют на его основе внутренние отображения (которые, в свою очередь, предназначены для генерации машинного кода). Как правило, такое отображение можно преобразовать в представление. Анализаторы абстрактно-синтаксических деревьев (AST) выполняют примерно ту же функцию — с той лишь разницей, что на основе проанализированной информации они строят явное древовидное отображение. В наших силах создать такие инструменты анализа, которые по результатам своего прохода по AST смогут выводить в требуемом формате отдельные блоки информации, значимые с точки зрения архитектуры. Что касается лексических анализаторов, то исходные артефакты анализируются ими исключительно как строки лексических элементов или символов. У пользователя лексического анализатора есть возможность задать набор образцов кода, случаи совпадения с которыми следует выводить. Аналогичным образом действуют специализированные инструменты наподобие grep и peri — зная, какая информация требуется пользователю, они ищут в коде соответствия установленным образцам. Все вышеупомянутые средства — синтаксические анализаторы с генерацией кода, анализаторы на основе абстрактно-синтаксических деревьев, синтаксические анализаторы и специализированные средства сопоставления с образцами — выводят статическую информацию. Инструменты профилирования и анализа покрытия кода выводят информацию о коде во время его исполнения; кроме того, они в большинстве случаев не добавляют в систему новый код. Инструменты измерения кода, нашедшие широкое применение в области тестирования, напротив, предусматривают ввод в исполняемую систему нового кода с целью вывода информации определенного характера. Все эти средства генерируют динамические представления системы. При необходимости из проектных моделей, файлов конструкций, сборочных и исполняемых файлов можно извлечь дополнительную информацию. К примеру, в файлах конструкций и сборочных файлах содержится информация о зависимостях между модулями или файлами системы, которая может быть не выражена в исходном коде. Большое количество архитектурной информации можно статическим методом извлечь из исходного кода, артефактов периода компиляции и проектных артефактов. С другой стороны, учитывая возможность динамического связывания, наличие в исходных артефактах всего комплекса информации, значимой с точки зрения архитектуры, не гарантируется. Динамическое связывание, в частности, характерно для: ♦ полиморфизма; ♦ указателей функций; ♦ параметризации периода прогона. Иногда топологию системы нельзя определить вплоть до прогона. К примеру, многопроцессные и многопроцессорные системы, задействующие промежуточное ПО наподобие J2EE, Jini или.NET, зачастую прибегают к динамическому построению топологии в зависимости от доступности системных ресурсов. Поскольку топология таких систем не отражена в исходных артефактах, ее обратная разработка при помощи статических инструментов извлечения невозможна. Отсюда необходимость в инструментах, способных генерировать динамическую информацию о системе (к примеру, в инструментах профилирования). Само собой разумеется, что они должны работать на той же платформе, на которой исполняется система. Кроме того, следует иметь в виду трудности, связанные со сбором результатов работы инструментов измерения кода. Во встроенных системах зачастую отсутствуют средства вывода подобной информации.
|