СОЗДАНИЕ УПРАВЛЯЕМОЙ ПРОГРАММНОЙ АРХИТЕКТУРЫ
В.В. Бахтизин, С.Н. Неборский
Одними из самых ранних этапов практически любой модели жизненного цикла программных средств (ПС) являются этапы разработки требований и создания архитектуры ПС. Можно с уверенностью утверждать, что от проектирования требований и построения архитектуры зависит качество конечного программного продукта. Однако в реальных проектах происходит постоянная модификация требований по следующим причинам:
- ошибки, конфликты, несогласованность требований;
- изменение взглядов заказчиков на тот продукт, который они хотят получить;
- технические проблемы, проблемы стоимости и времени реализации проекта;
- изменение приоритетов заказчика;
- изменение среды развертывания ПС [1].
Очевидно, изменение требований отражается
и на архитектуре ПС. Для эффективного управления изменяющимися требованиями существуют системы управления требованиями (СУТ). Для создания архитектуры ПС используются различные CASE-средства, большинство из которых основано на использовании стандартов MDA (Model-driven architecture - архитектура, управляемая моделью). В данной работе предлагается метод создания управляемой программной архитектуры ПС, альтернативный MDA, а также описывается разработанное ПС, реализующее данный метод. Предлагаемый метод состоит в том, что программная архитектура строится автоматически на основе требований к ПС. Программная архитектура - это структура ПС, описанная в терминах среды разработки и той аппаратно-программной платформы, на которой будет развернуто ПС.
Основной целью предлагаемого метода является сокращение времени разработки ПС. На рисунке 1 изображен так называемый треугольник компромиссов [2].
Компоненты треугольника компромиссов представлены площадями соответствующих вложенных треугольников. При изменении одного из компонентов необходима корректировка других. Сокращение времени разработки ПС позволяет расширить функциональность ПС и увеличить количество доступных ресурсов.
Идея создания программной архитектуры на основе требований заключается в том, что каждое
отдельное требование реализуется в виде отдельного концептуального контейнера среды разработки, формирующего программную архитектуру. В процессе разработки ПС полученные концептуальные контейнеры заполняются кодами классов, интерфейсов и другими компонентами, которые непосредственно реализуют требование.
Однако получаемая программная архитектура не была бы управляемой, если бы она не содержала механизма контроля изменения требований. Управляемая программная архитектура ПС - это такая архитектура, которая позволяет автоматически выявлять в исходном коде те сущности (то есть классы, интерфейсы, методы и т.п.), на которые влияет изменение требования. Механизм контроля изменения требований реализуется посредством задания фактов зависимости требований. Так, те контейнеры, которые реализуют зависимые требования, так же должны быть зависимы, и их сборка должна происходить в строго определенном порядке, установленном на основе этих зависимостей.
Управляемая программная архитектура позволяет гарантировать целостность исходного кода ПС при изменении требований, причем поддержка целостности осуществляется автоматически. Целостность означает следующее: код реализации некоторого требования всегда соответствует данному требованию, то есть всегда требование и его реализация согласованы. Если же эта согласованность нарушается, то сборка всего ПС становится невозможной.
Для реализации автоматической поддержки целостности предлагается задавать порядок сборки контейнеров, причем этот порядок должен устанавливаться на основе зависимостей требований. Для сигнализации о несогласованности кода предлагается использовать ошибки или предупреждения на этапе сборки проекта, то есть ошибки и предупреждения, выдаваемые средой разработки. Так, необходимо к каждому концептуальному контейнеру добавлять некоторую метаинформа-цию, которая будет отражать, согласован ли код данного концептуального контейнера с тем требованием, которое он реализует. При сборке отдельного контейнера должен происходить анализ данной информации. В том случае, если код контейнера не соответствует текущему состоянию требования, сборка данного концептуального контейнера и ПС в целом прекращается.
Метаинформацию о согласованности кода требованиям необходимо устанавливать каждый раз при выполнении процедуры регенерирования программной архитектуры. Регенерирование предпо-
\ Время
Ресурсы / \ разработки
l \ пс
Набор функций
Рис. 1. Треугольник
компромиссов
лагает изменение кодов существующих контейнеров, если отображаемые ими требования были изменены, а также добавление или удаление новых концептуальных контейнеров согласно текущему состоянию требований. На рисунке 2 приведены отдельные фазы итерационного процесса разработки ПС в условиях изменяющихся требований к нему.
Регенерирование программной архитектуры (автоматическое применение метода)
Набор концептуальных контейнеров создан
Реализация требований
Рис. 2. Использование метода создания управляемой программной архитектуры
Очевидно, нельзя доказать возможность построения генератора, который реализует предлагаемый метод создания управляемой программной архитектуры, не описав формально процесс управления требованиями и непосредственно сам процесс построения программной архитектуры на основе этой информации. Фактически задача может быть сформулирована следующим образом: на основе некоторого описания требований и связей между ними необходимо установить соответствие данных требований тем концептуальным контейнерам, которые их реализуют, и установить порядок сборки концептуальных контейнеров.
Требования могут быть заданы в виде множества К: К = {г| | 1 = 1,пК }, где пК - количество
требований; г1 =|х] | е А^ = 1,пА } - 1-е требование; пА - количество атрибутов; Aj ={ак| к = 1,п^ } - множество значений
Ч-го атрибута; п^ - количество значений j-го атрибута.
В общем случае отдельное требование представляется как набор значений различных атрибутов. Атрибуты - это элементы данных, которые представляют дополнительную информацию о требовании. Атрибуты используются для того, чтобы соотнести данные о требовании с другими типами информации проекта [3]. Примерами атрибутов могут быть идентификатор требования, текст требования, риск, приоритетность реализации. Требование г1 в простейшем случае может быть представлено как строка текста.
Для задания связей между требованиями используются матрицы трассируемости, или списки
трассируемости. Трассируемость требований документирует зависимости и логические связи отдельных требований и других элементов системы [4]. Матрица трассируемости может быть представлена как квадратная матрица размерностью пКхпК:
М = 1 |тн|| ,
1, айёе г ^ааепео 10 г^
где тП - Л Л О ~..ч 'О V ЛЧ ~Ч Ч ЛЧ
ч 10, апёе г 1а ^ааепео 10 г^
еК - требования; К - множество требований; пК - количество требований.
В таблице 1 приведен пример матрицы трас-сируемости, из которой видно, что требование Г1 зависит от требований г2 и гз, требование г2 зависит от требований гз и г4. Для простоты описания приводимые ниже рассуждения будут ссылаться на этот пример.
Таблица 1
Пример матрицы трассируемости
г1 г2 гз г4
г1 0 0 0 0
г2 1 0 0 0
гз 1 1 0 0
г4 0 1 0 0
Списки трассируемости - это, по сути, упрощенная форма отображения матрицы трассируе-мости. Список трассируемости представляются как описание некоторого требования и всех тех требований, от которых оно зависит. Так, требования из таблицы 1 могут быть записаны в виде списков трассируемости (табл. 2).
Таблица 2
Пример списков трассируемости
Требование Зависимые требования
г1 г2, гз
г2 гз, г4
гз -
г4 -
Описываемый метод создания программной архитектуры предполагает, что отдельное требование (или группа логически связанных требований) реализуется в виде отдельного концептуального контейнера. Пусть С - множество таких контейнеров: С - {с| | 1 — 1,пС }, где с1 - 1-й концептуальный контейнер; пС - количество концептуальных контейнеров.
Необходимо задать отображение множества требований К в множество концептуальных контейнеров С: Г:К^С .
Важно понимать, что отображение Г в общем случае не инъективно. Это означает, что разным требованиям не обязательно соответствуют разные концептуальные контейнеры. Так, логически связанные требования следует реализовывать в одном и том же контейнере. Вместе с тем отобра-
пк хп
К
жение Г является сюръективным, то есть каждый элемент из С является образом некоторого элемента из К. Отображение Г :К ^ С может
быть задано следующим образом: (
Г =
F(ri) F(r2)...F(r„R)y
, где F(ri)eC,i = 1,nR .
Для примера, рассмотренного в таблице 1, отображение Г :К ^ С может быть задано в виде таблицы 3.
Таблица 3
Пример задания отображения множества требований в множество концептуальных контейнеров
Требование ri r2 r3 r4
Концептуальный контейнер Ci C2 C3 C3
Подразумевая, что требования г3 и г4 связаны логически, они могут быть реализованы в одном концептуальном контейнере с3. Связи же между концептуальными контейнерами устанавливаются на основе зависимостей требований, которые они реализуют. Удобно показывать зависимости между контейнерами в виде структур, в которых представлен сам контейнер и список тех контейнеров, от которых он зависит. Этот список также можно называть списком тех контейнеров, на которые ссылается данный контейнер.
Последней нерешенной задачей является определение порядка сборки ПС, то есть порядка построения концептуальных контейнеров. Эта задача может быть сведена к получению ориентированного полугамильтонова графа О: О = О(С), где С - множество концептуальных контейнеров, каждый из которых соответствует вершине графа.
Полугамильтонов граф - это граф, в котором существует гамильтонова цепь. Гамильтоновой цепью в графе называется простая цепь, проходящая через все вершины по одному разу [5]. Ориентированную цепь также называют путем. Вершинами полугамильтонова графа О(С) будут являться концептуальные контейнеры. Тогда порядок, в котором они появляются в пути, и будет соответствовать порядку построения ПС. На рисунке 3 приведен пример полугамильтонова графа для некоторого ПС.
Очевидно, что данный граф строится на основе зависимостей концептуальных контейнеров.
C8
-W ПЛ I-Ы Г'О -1
а
C7 C4 C2
C6 C5 C3
Порядок сборки контейнеров
Зависимости контейнеров
Рис. 3. Пример полугамильтонова графа для некоторого ПС
Предлагаем алгоритм получения графа G(C) на основе этих зависимостей.
1. Начальной вершиной выбирается та, которая соответствует ни от чего не зависящему концептуальному контейнеру. Этот контейнер объявляется текущим.
2. Выбирается контейнер (вершина графа), который не зависит ни от одного контейнера либо зависит только от тех, которые уже есть в пути.
3. Проводится дуга к выбранному контейнеру от текущего контейнера.
4. Выбранный контейнер объявляется текущим.
5. Если все вершины графа присутствуют в пути, то алгоритм завершается. Иначе - переход на этап 2.
Для рассматриваемого примера полугамильтонов граф будет иметь вид, изображенный на рисунке 4.
Таким образом, можно видеть, что предлагаемый метод может быть описан формально и, следовательно, возможна его техническая реализация. В рамках проводимых исследований разработано ПС, реализующее описываемый метод создания программной архитектуры. По сути, это - генератор программной архитектуры, предполагающий применение СУТ DOORS для управления требованиями и использование Visual Studio.NET (VS.NET) для реализации разрабатываемого ПС. На рисунке 5 приведена схема работы генератора.
СУТ DOORS N. Генератор программной архитектуры Г\ Visual Studio .NET
1 > 1 >
И и
Экспортированные
Набор файлов проектов (например, *.csproj файлы)
Исполнимые файлы и библиотеки динамической компоновки
Рис. 5. Автоматическое генерирование программной архитектуры
Система DOORS позволяет экспортировать информацию, представляя ее в различных форматах. DOORS поддерживает экспорт в Microsoft Word, Microsoft Excel, Microsoft Outlook, Microsoft Power Point, HTML, RTF, Microsoft Project, крупноформатные таблицы (CSV или TSV), Frame-Maker, Interleaf. Экспортированные требования содержат информацию о связях. Если говорить об экспорте в формате HTML, то такие данные легко привести к виду матриц трассируемости, которые обрабатываются непосредственно генератором. На выходе генератора получается набор проектных фалов среды VS.NET, описывающих проекты VS.NET. Такие проекты есть ни что иное, как концептуальные контейнеры. Эти проекты связаны в соответствии с требованиями и для них установлен порядок сборки.
Подводя итог, следует отметить некоторые особенности метода создания управляемой программной архитектуры. Очевидно, предполагая автоматическое применение данного метода, становится возможным сократить время разработки ПС. Так, не требуется участия человека для определения программной архитектуры. Данный метод позволяет автоматически гарантировать целостность кода реализации требований, так как зависимости между ними отражаются на программной архитектуре. Описанный метод делает возможным автоматически отражать изменение требований на программной архитектуре. Таким образом, можно
говорить о том, что использование предложенного метода должно положительно отразиться на качестве разрабатываемого ПС.
Список литературы
1. Kotonya G., Sommerville I. Requirements Engineering. Processes and techniques. John Wiley & Sons, 1998.
2. Анализ требований и создание архитектуры решений на основе Microsoft .NET: Учебный курс MCSD /Пер. с англ. -М.: Издат.-торг. дом "Русская Редакция", 2004.
3. Leffingwell D., Widrig D. Managing Software Requirements. Addison Wesley, 1999.
4. Вигерс К. Разработка требований к программному обеспечению. - М., 2004.
5. Оре О. Теория графов. - М.: Наука, 1980.
ОПТИМИЗАЦИЯ ОБРАБОТКИ ИНФОРМАЦИОННЫХ ЗАПРОСОВ В СУБД
Э.П. Голенищев, С.А. Дербанов
С внедрением во все сферы профессиональной деятельности человека автоматизированных информационных систем (АИС), призванных повысить производительность труда или эффективность выполнения должностных обязанностей, повышается актуальность исследований, посвященных поиску высокоэффективных алгоритмов обработки информационных запросов к базам данных (БД), составляющих основу АИС [1,2].
Известно множество различных способов выполнения сложных запросов, поэтому одной из важнейших задач теории обработки запросов является определение наиболее эффективного из них.
В первых поколениях БД низкоуровневый язык обработки запросов обычно встраивался в какой-либо из высокоуровневых языков программирования. В этом случае вся ответственность за выбор оптимальной стратегии обработки запросов возлагалась на программиста. При использовании современных декларативных языков, например SQL, пользователь должен только определить, какие данные ему нужны, не указывая на то, как эти данные могут быть получены.
В результате от пользователя АИС не требуется каких-либо знаний о существующих стратегиях обработки запросов; перенос ответственности за выбор оптимальной стратегии обработки запросов на систему управления базами данных (СУБД) предотвращает выбор пользователем заведомо неэффективных стратегий и предоставляет СУБД больше возможностей контролировать общую производительность всей системы.
По результатам проведенного анализа выявлено два основных метода обработки запросов (на практике чаще используется их комбинация).
Первый метод для определения порядка выполнения запроса предполагает использование эвристических правил [2]. Второй метод заключается в сравнительной оценке стоимости различных вариантов выполнения запроса и выборе того варианта, который предполагает минимальное использование ресурсов [5,6].
Поскольку скорость доступа к данным на диске невелика, в качестве основного показателя оценки стоимости выполнения запроса обосновано использовать количество (время, стоимость) дисковых операций [2].
Целесообразно проанализировать последовательность основных этапов обработки запросов СУБД, представленную на рисунке.
Время обработки запросов в общем случае складывается из времен его компиляции и выполнения. Сокращение любой из этих составляющих должно уменьшать общее время обработки запро-
Запрос на языке высокого уровня (обычно на SQL)
Время обработки запроса
Время компиляции.
Декомпозиция запроса
Выражения реляционной алгебры
Оптимизация запроса
Системный каталог
БД
статистики
План выполнения запроса
Генерация кода
Время выполнения
Сгенерированный код
Выполнение запроса
Основная БД
Результаты запроса
Основные этапы процесса обработки запросов