Разработка и оценка архитектуры на основе сценариев

При проектировании архитектуры системы на основе требований, зафиксированных в виде вариантов использования, первые возможные шаги состоят в следующем:

1. Выделение компонентов

Выбирают набор «основных» сценариев использования — наиболее существенных и выполняемых чаще других. Каждый сценарий использования системы представляют в виде последовательности обмена сообщениями между полученными компонентами. При возникновении дополнительных хорошо выделенных подзадач добавляют новые компоненты, и сценарии уточняют.

2. Определение интерфейсов компонентов

Для каждого компонента в результате выделяют его интерфейс — набор сообщений, которые он принимает от других компонентов и посылает им. Рассматривают «неосновные» сценарии, которые так же разбивают на последовательности обмена сообщениями с использованием, по возможности, уже определенных интерфейсов. Если интерфейсы недостаточны, их расширяют. Если интерфейс компонента слишком велик, или компонент отвечает за слишком многое, его разбивают на более мелкие.

3. Уточнение набора компонентов

Там, где это необходимо в силу требований эффективности, надежности или удобства сопровождения, несколько компонентов можно объединить в один либо разделить на несколько.

4. Достижение нужных свойств.

На основе возможных сценариев использования системы выполняют анализ характеристик архитектуры и оценку ее пригодности для решения поставленных задач или сравнительный анализ нескольких архитектур. Это, так называемый, метод анализа архитектуры ПО (Software Architecture Analysis Method, SAAM).

Алгоритм метода:

ñ Определить набор сценариев действий пользователей или внешних систем на основе возможностей, которые планируются для реализации в системе или являются новыми. Чем полнее набор сценариев, тем выше качество анализа.

ñ Определить архитектуру (или несколько сравниваемых архитектур).

ñ Классифицировать сценарии. Для каждого сценария из набора следует определить, поддерживается ли он данной архитектурой или нужно вносить в нее изменения. Поддержка сценария означает, что лицо, заинтересованное в его выполнении, считает ее степень достаточной, а необходимые при этом действия удобными.

ñ Оценить сценарии. Определить, какие из них полностью поддерживаются рассматриваемыми архитектурами. Для каждого неподдерживаемого сценария надо определить необходимые изменения в архитектуре. К ним относятся внесение новых компонентов, изменения в существующих, а также изменения связей и способов взаимодействия. При наличии возможности стоит оценить трудоемкость внесения таких изменений.

ñ Выявить взаимодействие сценариев.

ñ Оценить архитектуру в целом (или сравнить несколько заданных архитектур), используя оценки важности сценариев и степень их поддержки архитектурой.

Рассмотрим сравнительный анализ двух архитектур на примере индексатора — программы для построения индекса некоторого текста, то есть упорядоченного по алфавиту списка его слов без повторений.

1. Выделим следующие сценарии работы или модификации программы:

– Реализация работы индексатора в инкрементальном режиме, то есть чтении на входе одной фразы за другой и пополнение получаемого в процессе работы индекса.

– Игнорирование индексатором предлогов, союзов, местоимений, междометий, частиц и других служебных слов.

– Возможность обработки индексатором текстов, подаваемых ему на вход в виде архивов.

– Размещение в индексе только слов в основной грамматической форме — существительных в единственном числе и именительном падеже, глаголов в неопределенной форме и т.д.

2. Определим две возможных архитектуры индексатора для сравнительного анализа.

В качестве первой архитектуры рассмотрим разбиение индексатора на два компонента. Один компонент принимает на свой вход входной текст, полностью прочитывает его и выдает на выходе список слов, из которых он состоит. Второй компонент принимает на вход список слов, а на выходе выдает его упорядоченный вариант без повторений. Этот вариант архитектуры построен в стиле «каналы и фильтры» (рисунок 6.9)

 

 

Рисунок 6.9 - Архитектура индексатора в стиле «каналы и фильтры»

Другой вариант архитектуры индексатора устроен следующим образом. Имеется внутренняя структура данных, хранящая подготовленный на настоящий момент вариант индекса, который представляет собой упорядоченный список без повторений всех слов, прочитанных до настоящего момента. Имеются также две переменные — строка, хранящая последнее прочитанное слово, и ссылка на то слово в подготовленном списке, которое лексикографически следует за последним словом

В дополнение к этим данным имеются следующие компоненты:

ñ Первый читает очередной символ на входе и передает его на обработку одному из остальных. Если это разделитель слов (пробел, табуляция, перевод строки), управление получает второй компонент. Если это буква третий. Если входной текст кончается — четвертый.

ñ Второй компонент осуществляет ввод последнего слова — оно помещается в список перед тем местом, на которое указывает ссылка, после чего последнее слово становится пустым, а ссылка начинает указывать на первое слово в списке.

ñ Третий компонент добавляет прочитанную букву в конец последнего слова, после чего перемещает ссылку на следующее за полученным слово в списке.

ñ Четвертый компонент выдает полученный индекс на выход.

Эта архитектура построена в стиле «репозиторий» (рисунок 6.10).

 


Рисунок 6.10 - Архитектура индексатора в стиле репозитория

 

Определим поддерживаемые сценарии из выделенного набора.

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

Обе архитектуры не поддерживают второй сценарий. Для его поддержки в первой архитектуре необходимо изменить первый компонент или вставить после него дополнительный фильтр, отбрасывающий вспомогательные части речи. Для поддержки этого сценария второй архитектурой нужно ввести дополнительный компонент, который перехватывает буквы, выдаваемые модулем их обработки (соответственно, этот модуль больше не должен перемещать указатель по итоговому списку) и сигналы о конце слова от первого компонента, после чего он должен отсеивать служебные слова.

Третий сценарий также требует изменений в обеих архитектурах. Однако в обоих случаях эти изменения одинаковы — достаточно добавить дополнительный компонент, декодирующий архивы, если они подаются на вход.

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

В целом первая архитектура на предложенных сценариях выглядит лучше второй. Единственный ее недостаток — отсутствие возможности инкрементально поставлять данные на вход компонентам. Если его устранить, сделав компоненты способными потреблять данные постепенно, эта архитектура станет почти идеальным вариантом, поскольку она легко расширяется — для решения многих дополнительных задач потребуется только добавлять компоненты в общий конвейер.

Вторая архитектура, несмотря на выигрыш в инкрементальности, проигрывает в целом. Основная ее проблема — слишком специфически построенный компонент — обработчик букв. Необходимость изменить его в нескольких сценариях показывает, что нужно объединить обработчик букв и обработчик конца слов в единый компонент, выдающий слова целиком, после чего полученная архитектура не будет ничем уступать исправленной первой.