|
||||||||||||||||||||
Пособие составлено доц. кафедры СП, канд. физ.-мат. наук Малышко В. В. Размещение на других ресурсах, а также коммерческое использование материалов, опубликованных в данном разделе, возможно только с разрешения авторов. По всем вопросам пишите: |
||||||||||||||||||||
|
||||||||||||||||||||
1. Сведения о работе в среде Topcased |
||||||||||||||||||||
|
||||||||||||||||||||
Topcased (topcased.org) -- среда объектно-ориентированного проектирования с открытым кодом. Среда создана на основе Eclipse. Для установки следует загрузить архив со страницы загрузки, разархивировать его. Поскольку практикум в компьютерных классах проходит под операционной системой Windows, описывается работа в ней. Для запуска среды вызывается исполняемый файл eclipse.exe. Для его работы необходима установить Java SE Runtime Environment 6 с сайта www.java.com. Следует убедиться, что в переменной среды Path прописан путь к файлу java.exe из JRE (что-то вроде C:\Program Files\Java\jre6\bin). Запуск может быть неудачен при сравнительно небольшой памяти. В этом случае следует открыть файл eclipse.ini и исправить ключ -Xmx1024m на -Xmx512m. Запустив среду Topcased, выбираем в левом верхнем углу закладку Topcased Navigator. Если такой закладки нет, значит, не открыт, так называемый, ракурс (Perspective) Topcased Modeling. Чтобы открыть ракурс, выберите в меню Window -> Open Perspective -> Other... . В появившемся списке выберите ракурс Topcased Modeling. Выберите появившуюся в левом верхнем углу закладку Topcased Navigator. Правым щелчком открываем контекстное меню, New -> Project. В открывшемся окне выбираем Topcased Project. Даем имя проекту (например, MyProject). Вызываем контекстное меню папки Models, появившейся в навигаторе, выбираем New -> UML Model with TOPCASED. Даем имя модели (например, MyModel). Также указываем шаблон для создаваемой модели Common approach. В этом шаблоне есть готовая структура модели, нам не придется создавать ее вручную. После создания модели окно примет вид, показанный на рисунке 1.1. Рис. 1.1. Окно Topcased после создания модели. В левой верхней части находится навигатор, показывающий файловую структуру проекта и модели. Данные модели хранятся в файле с расширением uml (MyModel.uml). Модель состоит из 4 пакетов -- 4 архитектурных представлений. Данные диаграмм хранятся в файле с расширением umldi (MyModel.umldi). В модели 4 диаграммы -- по одной для каждого архитектурного представления. Более удобен вид, представленный во вкладке Outline (схеме), которая находится под навигатором. Там показаны и диаграммы, и пакеты, то есть, все составляющие модели. Контекстное меню вкладки Outline позволяет добавлять пакеты и диаграммы в модель. При работе рекомендуется использовать эту вкладку, а не навигатор. Правая часть окна состоит из редактора (вверху) и находящихся внизу окон Свойства (Properties) и Документация (Documentation). В левой части редактора содержится панель инструментов (палитра), на которой представлены элементы и связи, помещаемые на диаграммы. Правую часть окна занимает область редактирования диаграммы. Перед тем как приступить к моделированию, добавим в нашу модель стереотипы. Модель, содержащая профиль с необходимыми стереотипами, можно скачать отсюда. Скачав архив, следует добавить файлы в проект. Для этого в навигаторе выберите проект и вызовите контекстное меню. Import -> General -> Archive File. Укажите полное имя архива (C:\Temp\oldstereotypes.zip), и выделите оба файла, содержащихся в нём. В качестве целевого каталога укажите MyProject/Models. По окончании импорта в проект добавятся файлы модели 4prak.uml, 4prak.umldi, описывающий UML-профиль со стереотипами. Для отображения стереотипов в виде пиктограмм следует скачать архив с пиктограммами. Точно также, как описано выше, добавьте в каталог Plugin_Resources каталог icons из архива вместе со всем его содержимым. Далее в Outline вызовите контекстное меню модели MyModel. Load Resourse... -> Browse Workspace... Выберите файл модели 4prak.uml. После загрузки ресурсов двойным кликом выделите MyModel в Outline. В разделе Properties выберите закладку Profiles. Добавьте профиль 4prak в список Applied Profiles. Если все проделано успешно, под пакетами в Outline появится ссылка на профиль (<Profile Application>). Для отображения пиктограмм на диаграммах вызовите в меню Window -> Preferences выберите пункт Topcased -> Editors -> UML/SysML -> All Diagram -> Stereotype и установите значение As Icon... Предварительные приготовления закончены, можно переходить к моделированию.
Рис. 1.2. Окно Topcased после предварительных приготовлений.
|
||||||||||||||||||||
|
||||||||||||||||||||
"Опять!" - сказал Боб, повесив телефонную трубку. Robertson's Cabinets, Inc. - это маленькая компания, специализирующаяся на производстве стандартных и нестандартных кухонных шкафов. Компания началась с небольшой группы собравшихся вместе предпринимателей. Когда дело началось три года назад, поступало слишком мало заказов, и они вполне могли управляться с ними на бумаге. С ростом их репутации число заказов возрастало. Пришлось нанять новых рабочих, и за три года фирма выросла до магазина с более чем 50 сотрудниками. Хотя это еще все-таки небольшая компания, но она выросла уже настолько, что уже не могла больше полагаться на обработку заказов вручную. Владельцы фирмы Боб и Мэри Робертсоны решили поговорить со Сьюзан, чтобы решить эту проблему. Сьюзан -- это одна из небольшого числа специалистов по компьютерам, входящих в отделение этой фирмы, занимающееся информационными технологиями. Из этого разговора Сьюзан смогла понять, что система должна обеспечивать возможность добавления новых заказов, изменения старых, выполнения заказов, проведения учета на складе с составлением инвентарных описей. При получении заказа система должна также послать сообщение бухгалтерской системе, которая выписывает счет. Если требуемого товара нет на складе, заказ должен быть задержан. Затем Сьюзан преобразовала требования в диаграмму Вариантов Использования, с помощью которой начала моделировать систему. |
||||||||||||||||||||
|
||||||||||||||||||||
Выполняя упражнения, мы сразу переходим к определению требований, минуя моделирование бизнес-процессов. Позволительно так поступать в случаях, когда предметная область, для которой разрабатывается ПО, сравнительно проста или хорошо знакома разработчикам. Определение требований -- процесс, в ходе которого определяются задачи, поставленные перед разработчиками, и создаются модели, на основе которых планируется разработка системы. Требование -- это условие, которому должно удовлетворять программное обеспечение, или свойство, которым оно должно обладать, чтобы удовлетворить потребность пользователя в решении некоторой задачи, или чтобы соответствовать условиям контракта, спецификации или стандарта. Все требования делятся на функциональные и нефункциональные. Функциональные требования определяют действия, которые должна выполнять система, без учета ограничений, связанных с ее реализацией. Нефункциональные требования не определяют поведение системы, но описывают ее атрибуты или атрибуты системного окружения. Требования оформляются в виде ряда документов и моделей. К основным документам, регламентируемым технологией Rational Unified Process, относятся: концепция, глоссарий предметной области, дополнительная спецификация. Концепция определяет глобальные цели проекта и основные особенности разрабатываемой системы. Существенной частью концепции является постановка задачи разработки, определяющая требования к функциям системы. Словарь предметной области (глоссарий) определяет общую терминологию для всех моделей и описаний требований к системе. Дополнительная спецификация (технические требования) содержит описание нефункциональных требований к системе, таких, как надежность, удобство использования, производительность, сопровождаемость и др. Постановка задачи разработки системы обработки заказов: Пользователями новой системы будут продавцы и работники склада (заведующий и кладовщики). База данных системы будет поддерживаться реляционной СУБД. Система должна обеспечивать возможность продавцам вводить новые заказы и изменять заказы, хранящиеся в системе. Заказ может быть изменен до тех пор пока не закончились работы на складе по его сборке. Собранные заказы поставляются заказчикам, внесение в них изменений запрещено. Дата окончания сборки заказа хранится в системе. По её наступлении заказ считается выполненным. Не выполненный заказ может быть отменен. При вводе заказа важно сохранить дату, когда был принят заказ, и дату, до которой нужно осуществить сборку и доставку заказа. Каждый заказ содержит одну или несколько позиций. В любой позиции указывается наименование предмета мебели и количество штук. После ввода заказа данные передаются в бухгалтерскую систему для составления счёта на оплату. Работают несколько продавцов, поэтому необходимо обеспечить защиту данных таким образом, чтобы продавец мог работать только с собственными заказами, и не имел доступа к данным чужих заказов. Продавец может удалить данные о любом из своих заказов. Заведующий складом использует систему, чтобы напечатать остатки -- опись, в которой указывается текущее количество предметов мебели на складе. Остатки определяются системой по данным последней инвентаризации и данным о выполнении позиций заказов. Например, если по данным инвентаризации было 10 стульев и 8 стульев отмечены как выполненные позиции заказов введенных после инвентаризации, (т. е. стулья переданы заказчикам или отложены в собираемые заказы), то текущий остаток -- 2 стула. При проведении инвентаризации для каждого предмета мебели со склада вводится текущее его количество, относительно которого будут рассчитываться остатки до следующей инвентаризации. Кладовщики отмечают в системе ход выполнения заказов. Любой кладовщик может работать с любым заказом. Кладовщик может пометить какую-либо позицию заказа как выполненную. При этом соответствующее количество предметов мебели вычитается при расчёте текущих остатков. Если выполнены все позиции заказа, он также считается выполненным. Кладовщик может пометить заказ как задержанный, если нужной для выполнения заказа мебели на складе нет, а дата поставки заказа уже прошла. Глоссарий предметной области создается на основе описания системы выполнения заказов и постановки задачи, а также глоссария деятельности предприятия, созданного в ходе бизнес-моделирования, и концепции. Глоссарий предназначен для описания терминологии области, в которой будет работать ПО. Выделяются термины, им дается описание, рассчитанное на широкий круг читателей (пользоваться этим описанием будут все лица, заинтересованные в разработке системы). Глоссарий составляется на русском языке. Термины сопровождаются переводом на английский на тот случай, если термин будет использован в модели системы как название класса, пакета и т. п. Глоссарий:
Дополнительная спецификация определяет нефункциональные требования к системе, такие, как надежность, удобство использования, производительность, сопровождаемость, а также ряд функциональных требований, являющихся общими для нескольких вариантов использования. Назначение дополнительных спецификаций -- определить требования к системе обработки заказов, которые не отражены в других документах и моделях. Вместе они образуют полный набор требований к системе. Рассмотрим дополнительную спецификацию:
Функциональные требования к системе моделируются и документируются с помощью вариантов использования (use case). Вариант использования (use case) -- связный элемент функциональности, предоставляемый системой при взаимодействии с действующими лицами. Действующее лицо (actor) -- роль, обобщение элементов внешнего окружения системы, ведущих себя по отношению к системе одинаковым образом. В контексте процесса управления требованиями варианты использования трактуются следующим образом:
Модель вариантов использования состоит из диаграмм вариантов использования, текстовых описаний вариантов использования и диаграмм деятельности, моделирующих потоки событий вариантов использования. Диаграмма вариантов использования составляется системным аналитиком, который сначала выявляет элементы модели, а затем устанавливает связи между ними. Элементами диаграмм вариантов использования являются варианты использования и действующие лица, соединенными разного рода связями. Из постановки задачи разработки и глоссария системный аналитик может выделить список действующих лиц и их интересов:
| ||||||||||||||||||||
|
||||||||||||||||||||
1. На вкладке Outline находим пакет UseCaseView. Правым щелчком вызываем контекстное меню. Create child -> Nested Package -> Model. Вложенной модели дадим имя UseCase Model (модель вариантов использования). Перемещаем на вкладке Outline диаграмму UseCaseView внутрь созданной модели. Двойным щелчком открываем диаграмму UseCaseView в редакторе. 2. В палитре редактора выберем инструмент Actor и добавим действующее лицо на диаграмму. Введем имя актора: Продавец. Повторим те же действия для добавления оставшихся действующих лиц: заведующего складом, кладовщика, бухгалтерскую систему. 3. С помощью инструмента Boundary Box обозначим границы проектируемой системы. Получившаяся диаграмма примет вид, показанный на рисунке 3.1. Рис. 3.1. Диаграмма вариантов использования после добавления действующих лиц. Исходя из потребностей действующих лиц, системный аналитик может предложить следующие варианты использования: Войти в систему, Ввести заказ, Изменить заказ, Удалить заказ, Распечатать остатки, Провести инвентаризацию, Выполнить заказ, Задержать заказ. Вариант использования «Войти в систему» не соответствует какой-либо явной цели какого-нибудь действующего лица. Он описывает функциональные требования к системе по обеспечению защиты данных. Про каждого своего пользователя система должна знать, какую роль по отношению к ней он выполняет: продавца, кладовщика или заведующего, к каким функциям и данным ему можно предоставлять доступ. |
||||||||||||||||||||
|
||||||||||||||||||||
Рис. 3.2.1. Диаграмма вариантов использования для системы обработки заказов. 1. В палитре редактора выберем инструмент Use Case и добавим вариант использования на диаграмму (внутрь рамки). Введем название: Ввести заказ. Повторим те же действия для добавления оставшихся вариантов использования: Войти в систему, Изменить заказ, Удалить заказ, Распечатать остатки, Провести инвентаризацию, Выполнить заказ, Задержать заказ. Размещаем варианты примерно так, как показано на рисунке 3.2.1. 2. В палитре редактора выберем инструмент Associations и свяжем действующее лицо Продавец с вариантом использования Ввести заказ. В свойствах (закладка Second end) укажем направление с помощью флажка isNavigable. В свойствах (закладка Graphics) скрываем имя связи, перемещая элемент NameEdgeObject в список скрытых. 3. Повторим те же действия для добавления связей других действующих лиц и вариантов использования. Обратите внимание, что можно выделить несколько ассоциаций (shift+клик) и изменить одновременно их свойства. Получившаяся диаграмма изображена на рис. 3.2.1. Направления связей между действующими лицами и вариантами использования показывают, какое лицо является основным, а какое второстепенным. Для варианта использования Ввести заказ Продавец -- основное действующее лицо, а Бухгалтерская система -- второстепенное (в ходе ввода заказа в бухгалтерскую систему передаются данные о заказе). 4. Вариант использования Задержать заказ свяжем с вариантом Выполнить заказ связью расширения (Extend). Скройте точку расширения, выделив связь Extend и убрав в закладке Graphics из списка видимых элементов ExtensionEdgeObject. Связь расширения между вариантами использования означает, что в ходе потока событий варианта использования Выполнить заказ при некоторых условиях может произойти переключение на выполнение варианта использования Задержать заказ. Заметим, что переключение происходит не всегда, а только если не удалось выполнить заказ до истечения даты его поставки. 5. Созданная диаграмма имеет недостаток в том, что у варианта использования Войти в систему несколько основных действующих лиц. Полагая поведение системы одинаковым при входе любого пользователя, введем абстрактное действующее лицо Пользователь, подвидами которого будут лица Продавец, Кладовщик, Заведующий складом. Диаграмма примет вид, изображенный на рисунке 3.2.2. Для добавления связей обобщения используйте инструмент палитры Generalization. Лишние ассоциации удалите из модели Shift+Del. Нажатие только на Del удалит связи только с диаграммы, в модели они останутся, что может привести к ошибкам. У действующего лица Пользователь на закладке Model пометьте флаг isAbstract. Рис. 3.2.2. Модифицированная диаграмма вариантов использования Теперь на нашей диаграмме каждый вариант использования связан ровно с одним действующим лицом, которое для него является основным, и с произвольным количеством дополнительных действующих лиц. Каждое действующее лицо связано хотя бы с одним вариантом использования. Никакие два варианта использования между собой не связаны ассоциацией. Лишь два варианта использования соединены связью расширения. Допускаются также связи обобщения и включения. О них рассказывается на лекциях. Системный аналитик с их помощью производит структурирование модели вариантов использования. Модель с большим количеством вариантов использования может быть разбита им на части -- пакеты. Никакие действующие лица не связаны между собой ассоциацией. Между ними допускаются лишь связи обобщения. Самостоятельно создавая диаграммы вариантов использования, старайтесь, чтобы их элементы и связи удовлетворяли таким же ограничениям. Получившаяся диаграмма является примерным оглавлением проекта. Мы видим, какие функции и кому предоставляет система. По ней архитектор проекта может составить оценку трудоемкости проекта, основанную на прогнозируемой трудоемкости реализации вариантов использования. Также архитектор ранжирует варианты использования по приоритету -- более важными вариантами использования будут заниматься в первую очередь. Для каждого варианта использования составляется описание. Выполняют эту работу use-case писатели.
| ||||||||||||||||||||
|
||||||||||||||||||||
Функциональные требования подробно фиксируются в описаниях вариантов использования. Описания составляются специальным образом, чтобы уменьшить вероятность неверного толкования и облегчить восприятие текста. Каждое описание включает в себя: Каждый поток событий задаётся перенумерованным набором шагов. Используются шаги трёх типов: действие системы (например, «Система запрашивает имя пользователя и пароль»); реакция действующего лица («Пользователь вводит имя и пароль»); управление потоком («Выполнение переходит на начало основного потока«). Структура предложений, описывающих шаги, одинакова: подлежащее, сказуемое, остальные части речи. От неё отходят лишь при описании циклов и ветвлений. Цикл задается составным описанием, в начале которого указывается условие цикла («Для каждого ... выполняется») или количество повторений. Далее следует тело цикла -- последовательность вложенных шагов (см. шаг 4 основного потока варианта использования «Ввести заказ»). Ветвление в тривиальных случаях, когда альтернативная ветвь пуста, допускается описывать предложением с союзом если («...»). Чаще ветвление описывают с помощью альтернативных потоков. В основном потоке варианта использования «Войти в систему» 3-ий шаг указывает основное продолжение потока, а альтернативный поток «3А. Неправильное имя/пароль» содержит второй вариант развития событий. Как правило, действия по проверке условия ветвления не описывают. Вместо этого указывается шаг, на котором система (или действующее лицо) подтверждает, что условие выполнено, в основном потоке, или обнаруживает, что условие нарушено, в альтернативном потоке. Создайте файлы с описаниями вариантов использования, приведенными ниже, и добавьте их в модель (окно Documentation, закладка Resourses). Обратите внимание, что в описании любого варианта использования должен присутствовать хотя бы один шаг для каждого действующего лица, связанного с ним. Постусловие состоит из двух частей: гарантии успеха и минимальных гарантий. Первая часть описывает, что должно быть истинно при успешном завершении варианта использования. Вторая часть -- это гарантии системы в случаях неуспеха. Например, при успешном входе в систему гарантируется доступ пользователя к главному меню, при неуспешном -- гарантируется, что такой доступ не будет предоставлен. Пустое постусловие допускало бы произвольное поведение системы и не пригодно как основа для тестирования. Описания составляются для всех вариантов использования. Выполняя упражнения, мы создадим лишь два описания. Вариант использования «Войти в систему»: Краткое описание Обратите внимание на номер альтернативного потока. Цифра указывает номер шага основного потока, на котором может произойти переключение на альтернативный поток, буква позволяет различить несколько альтернативных потоков, на которые можно переключиться на одном и том же шаге. Если переход на альтернативный поток может происходить в течение нескольких подряд идущих шагов, указывают их номера через дефис. Например, 1-3Б. Если поток вызывается из разных шагов, он может иметь несколько номеров, перечисленных через запятую. Вариант использования «Ввести заказ»: Краткое описание |
||||||||||||||||||||
|
||||||||||||||||||||
Все потоки событий одного варианта использования, сценарии двух и более взаимосвязанных вариантов использования или отдельный поток событий могут быть смоделированы на диаграммах деятельности. Построим диаграмму деятельности для варианта использования «Войти в систему». Предварительно настроим редактор для более удобной работы. Меню Window -> Preferences. В открывшемся окне в поле фильтра вводим Control, в дереве настроек находим Control Flow. Скрываем стереотип ребра, имя ребра и вес ребра. Рис. 3.4.1. Окно настроек 1. На вкладке Outline вызываем контекстное меню варианта использования Войти в систему и выбираем Add diagram -> Activity diagram. 2. На появившейся в редакторе диаграмме создаем два раздела (Activity Partition) -- Пользователь и Система -- каждый из которых обозначает область ответственности. Деятельности, соответствующие узлам, которые будут расположены в области ответственности пользователя, будут выполняться пользователем, остальные -- системой. Входной узел (Initial Node) помещаем в раздел Система. 3. Согласно описаниям потоков событий варианта использования создаем узлы действий (Opaque Action): Запрос имени и пароля; Ввод имени и пароля; Проверка имени и пароля; Вывод главного меню; Вывод предупреждения; Выбор действий. Узлы действий размещаем по разделам в соответствии с тем, кто выполняет действия. 4. Добавляем узлы разветвления (Decision Node). Соединяем узлы ребрами потоков управления (Control Flow). Скрыть имена ребер и тривиальные сторожевые условия можно с помощью окна Свойства (закладка Graphics). Задать нетривиальные сторожевые условия можно на закладке Guard. Тип создаваемого условия <Literal String>, текст условия задается в поле Value. 5. Добавляем два финальных узла (Activity Final), комментариями указываем на успешное и безуспешное окончание потоков событий. Привязка комментария к узлу осуществляется с помощью Comment Link. Вид получившейся диаграммы представлен на рис. 3.4.2.
Рис. 3.4.2. Диаграмма деятельности с ошибкой Диаграмма деятельности задает потоки управления между узлами. Изначально курсор управления порождается во входном узле. Оттуда он передается по ребру на вход узла действия (Запрос имени и пароля). Узел действия ждет, когда курсоры управления придут на все входящие ребра, после чего запускается действие, а по окончании действия курсоры управления подаются на все исходящие ребра. Очевидно, наша диаграмма содержит ошибку. По второму ребру курсор управления придет не раньше, чем узел действия выдаст его на выход. Тупик. Чтобы исправить ошибку, добавим узел объединения (Merge Node), чтобы в узел действия входило одно ребро (и чтобы для выполнения действия требовался один входящий курсор). Узел объединения принимает курсор с любого входящего ребра и сразу передает его на исходящее ребро, которое у него одно. Исправленная диаграмма показана на рисунке 3.4.3.
Рис. 3.4.3. Исправленная диаграмма Когда курсор попадает в узел разветвления, проверяются сторожевые условия на исходящих ребрах этого узла. Исходящих ребер может быть два и более. По одному из ребер, на котором сторожевое условие истинно, курсор управления передается дальше. Если таких ребер несколько -- произвольным образом выбирается одно. Если все сторожевые условия ложны, курсор не может быть передан дальше, поток управления заходит в тупик. Во избежание ошибок следует внимательно формулировать сторожевые условия. Рекомендуется делать их взаимоисключающими и покрывающими все возможные случаи. Часто используется условие [else], способствующее выполнению этих требований. При попадании курсора управления в финальный узел (любой) вся деятельность прекращается. Уничтожаются все курсоры управления на всех ребрах диаграммы. В случаях, когда требуется остановить один поток, оставив другие активными, применяется узел завершения потока (Flow Final), изображаемый кружком с крестиком. Самостоятельно постройте диаграмму для варианта использования «Ввести заказ».
Рис. 3.4.4. Диаграмма деятельности варианта использования «Ввести заказ». Моделирование требований следовало бы продолжить дальше, описав все варианты использования и построив для них диаграммы деятельности. Однако, не имеет смысла сразу описывать все требования. Работа осуществляется последовательными итерациями, в ходе которых составляются описания отдельных вариантов использования в порядке их важности. Когда описания важных вариантов использования составлены, выполняются работы по анализу и проектированию частей системы, реализующих их. Use-case писатели приступают к работе над менее приоритетными вариантами использования во время последующих итераций, или занимаются ими на той же итерации, если они мало загружены во время анализа и проектирования. Следует быть готовыми к пересмотру требований в ходе проекта. Изменчивость требований обусловлена тем, что заказчики и будущие пользователи системы не могут сразу точно указать свои пожелания, и тем, что по ходу проекта разработчики лучше узнают предметную область и контекст системы. Перейдём к анализу.
|
||||||||||||||||||||
|
||||||||||||||||||||
При анализе системы производится трансформация требований в системный проект, создание эскизной архитектуры, соответствующей функциональным требованиям. Эскизная архитектура включает в себя набор ключевых абстракций, набор классов анализа, перечень механизмов анализа, иерархию уровней системы, реализации вариантов использования. В ходе жизненного цикла эскизная архитектура подлежит уточнению, на ее основе создается проектная архитектура, учитывающая нефункциональные требования и подлежащая реализации в коде. Анализ нацелен на прояснение проблемы, решаемой в проекте, построение ее решения, простого насколько это возможно, но удовлетворяющего функциональным требованиям. Анализ разбивается на несколько итераций, в ходе которых выполняется анализ части вариантов использования. Работа ведется в соответствии с приоритетом вариантов использования, самые важные анализируются в первую очередь. Результаты каждой итерации интегрируются в общую модель. При анализе последовательно выполняются два вида работ: архитектурный анализ и анализ вариантов использования. Исполнителями процесса анализа являются архитектор, разработчик. Обязанности архитектора состоят в координации и руководстве процессом, определении структуры каждого архитектурного представления, осуществлении архитектурного анализа. Обязанности разработчика включают анализ вариантов использования, определение обязанностей, поведения, свойств классов и связей между классами. Архитектурный анализ выполняется архитектором и включает в себя следующие технологические операции:
Соглашения моделирования фиксируются в документе «Руководящие указания по проектированию» (Design Guidelines). Они определяют: перечень используемых диаграмм и элементов модели; правила применения диаграмм; соглашения по именованию элементов модели; организацию модели (пакеты). Будем придерживаться следующих соглашений:
| ||||||||||||||||||||
|
||||||||||||||||||||
Рис. 4.1.1. Структура модели анализа 1. Создадим модель Analysis Model. Вкладка Outline, контекстное меню пакета Logical View, Create child -> Packaged Element -> Model. Аналогично создадим проектную модель (Design Model). 2. Создадим пакет UseCase Realizations. Вкладка Outline, контекстное меню пакета Analysis Model, Create child -> Packaged Element -> Package. 3. Создадим реализацию варианта использования ход в систему (Login). Вкладка Outline, контекстное меню пакета UseCase Realizations, Create child -> Packaged Element -> Collaboration. В свойствах кооперации на вкладке Stereotypes укажем стереотип <<use case realization>>. На вкладке Advanced укажем Use Case Войти в систему. Кооперации дадим имя Login в соответствии с соглашениями моделирования. Аналогичным образом создадим реализацию варианта использования Ввести заказ (CreateOrder). 4. Создадим диаграммы классов VOPC. Вкладка Outline, контекстное меню пакета UseCase Realizations, Add diagram -> Class Diagram. 5. Создадим диаграмму классов Key Abstractions. Вкладка Outline, контекстное меню пакета Analysis Model, Add diagram -> Class Diagram. Структура модели в папке Outline должна соответствовать рис. 4.1.1. Ключевые абстракции -- основные понятия предметной области -- архитектор выделяет, анализируя требования и пользуясь, глоссарием и моделью бизнес-анализа, если таковая была создана. Каждый термин из глоссария является кандидатом для того, чтобы быть трансформированным в класс ключевой абстракции (или в несколько классов, если структура данных, связанная с ним, слишком сложна для представления одним классом). Некоторые термины могут быть источником для атрибутов классов. В системе обработки заказов можно выделить следующие ключевые абстракции: Order (данные о заказе), OrderItem (данные о позиции заказа), ArticleOfFurniture (данные о предмете мебели), Customer (данные о заказчике), User (учетная запись пользователя системы). Ассоциации между абстракциями показывают типы соединений между экземплярами ключевых абстракций. Мощности у полюсов указывают ограничения на количество соединений у одного экземпляра. Ассоциация может быть рефлексивной, т. е. соединяющей класс с ним самим. Такая связь описывает соединения между экземплярами одного класса. Чтобы различать роли объектов, участвующих в таких соединениях, при полюсах рефлексивных ассоциаций обязательно дают имена ролей. Также поступают при наличии двух ассоциаций между одной парой классов. Иногда роли указывают, чтобы пояснить назначение конкретной ассоциации. Рис. 4.1.2. Диаграмма ключевых абстракций Предварительно настроим редактор для более удобной работы. Меню Window -> Preferences. В открывшемся окне в дереве настроек найдем диаграмму классов: Topcased -> Editors -> UML/SysML -> Class Diagram. Изменим фон класса на белый. У ассоциации оставим видимыми лишь srcCountEdgeObject и targetCountEdgeObject. 1. Откроем в редакторе диаграмму Key Abstractions. Выберем в палитре инструмент Class. Добавим классы Order, OrderItem, ArticleofFurniture, Customer, User. 2. Добавим перечислимый тип (Enumeration) TypeOfUser (Тип пользователя). Внутри него расположим значения перечислимого типа (enumeration literal). 3. Выберем в палитре инструмент Association. Проведем связи между классами. Укажем мощности у полюсов. Укажем имя полюса type (поле Role в закладках First End, Second End) ассоциации между классом User и типом TypeOfUser. Отобразим имя полюса на диаграмме (закладка Graphics, элементы srcNameEdgeObject и targetNameEdgeObject). Связь между классами User и Order указывает, кто из пользователей является составителем того или иного заказа. 4. Добавим атрибуты (Property) классов. Укажем, что все атрибуты закрытые (поле Visibility в закладке Model). В итоге диаграмма должна соответствовать рисунку 4.1.2. Нет необходимости сразу указывать все детали ключевых абстракций, следует указывать только самое важное. В ходе проекта возможности уточнить набор ключевых абстракций ещё представятся.
Анализ вариантов использования выполняется разработчиками и включает в себя следующие технологические операции:
Классы анализа отражают функциональные требования к системе и моделируют типы объектов предметной области. Совокупность классов анализа представляет собой начальную концептуальную модель системы. Эта модель проста и позволяет сосредоточиться на реализации функциональных требований, не отвлекаясь на детали реализации, обеспечение эффективности и надежности. Для решения этих вопросов в последствии модель анализа будет трансформирована в проектную модель. В ходе анализа вариантов использования в их потоках событий выявляются классы трех типов:
Правило выделения граничных классов: для каждой связи между действующим лицом и вариантом использования создается граничный класс, отвечающий за данное взаимодействие. Правило выделения классов-сущностей: классы-сущности -- это, как правило, классы, представляющие ключевые абстракции системы. Правило выделения управляющих классов: для каждого варианта использования создается ответственный за его реализацию класс управления. Выполним анализ варианта использования Ввести заказ.
| ||||||||||||||||||||
|
||||||||||||||||||||
Идентифицируем классы анализа. Согласно диаграмме вариантов использования имеются два действующих лица (Продавец и Бухгалтерская система), связанных с нашим вариантом использования. Создадим граничные классы: CreateOrderForm -- экранную форму, отвечающую за взаимодействие с Продавцом при вводе заказа, MainMenuForm -- форму главного меню, AccountingSystem -- класс-посредник, реализующий протокол взаимодействия с Бухгалтерской системой. Вкладка Outline, контекстное меню пакета Analysis Model, Create child -> Packaged Element -> Class. Не забудьте указать стереотип <<boundary>>. Создадим управляющий класс OrderController, отвечающий за реализацию бизнес-логики (действия аналогичны, стереотип <<control>>). Классам -- ключевым абстракциям -- назначим стереотип <<entity>>. Из описания варианта использования следует, что в потоках событий будут задействованы экземпляры классов Order, OrderItem, ArticleOfFurniture, Customer, User. Открываем в редакторе диаграмму классов VOPC CreateOrder. Перетаскиваем на нее вышеупомянутые классы (граничные, управляющие и сущности). Вид диаграммы изображен на рис. 4.2.1.
Рис. 4.2.1. Диаграмма VOPC CreateOrder Распределение поведения, предусматриваемого вариантом использования, между классами анализа реализуется при построении диаграмм взаимодействия. На основе описания варианта использования для каждого потока событий (основного, альтернативных, подчиненных) строится отдельная диаграмма взаимодействия. Topcased поддерживает один вид диаграмм взаимодействия -- диаграммы последовательности. Перейдем к моделированию. Создадим внутри кооперации CreateOrder элемент внутреннего поведения BasicFlow (основной поток). Create child -> Owned Behavior -> Interaction. Внутри созданного взаимодействия создадим одноименную диаграмму последовательности (Sequence Diagram). Откроем ее в редакторе. Добавим объекты с линиями жизни (Lifeline). Левый представляет собой экземпляр действующего лица Продавец (свойства, вкладка Model, поле Represents). Остальные являются экземплярами классов MainMenuForm, CreateOrderForm, OrderController, Order, Customer, OrderItem, ArticleOfFurniture. Самый правый -- экземпляр действующего лица CatalogSystem. Все объекты анонимны. Как правило, имена дают в том случае, если на диаграмме есть несколько объектов одного типа, чтобы их различать. Добавим активацию (Execution) а линию жизни Продавца. Затем выберем на палитре синхронное сообщение (Call synch.) и проведем его от первой линии жизни ко второй. Дадим имя сообщению //createOrder. Два слэша указывают, что это предварительное имя сообщения, которое в дальнейшем будет уточнено. Аналогично добавим второе сообщение //open, его тип в отличие от первого -- Create Message. После создания такого сообщения появляется возможность сдвигать экземпляр-получатель вниз, указывая тем самым, что выше он не существовал.
Рис. 4.2.2. Диаграмма BasicFlow Рассмотрим дальнейшее взаимодействие объектов на диаграмме. В форму CreateOrderForm Продавец посылает дату поставки и сведения о заказчике. Форма, получив эти данные, передает запрос о создании заказа OrderController'у. Он создает экземпляр класса Order и проверяет, есть ли в системе данные о заказчике. Если их нет, выполняется взаимодействие описанное комбинированным фрагментом взаимодействия (Combined Fragment), кратко называемым блоком. Его тип -- Optional (свойства, закладка Model, поле Interaction Operator). После его добавления на диаграмму следует в Outline выделить операнд взаимодействия (Interaction Operand), вложенный в комбинированный фрагмент. С помощью контекстного меню следует добавить сторожевое условие [заказчик не найден] (Create child -> Guard -> Interaction Constraint). Указать значение и тип сторожевого условия (Literal String) можно в окне свойств на закладке Specification. Следует добавить активацию на линию жизни контроллера, создать новую линию жизни, представляющую новый экземпляр Customer, дать ему имя New, чтобы он отличался от использованного ранее экземпляра того же класса. Следует создать сообщение создания //new передвинуть экземпляр внутрь фрагмента. Так как Topcased не позволяет сразу расположить экземпляр в нужном месте, следует сдвинуть правую границу блока, чтобы освободить место, затем поместить туда объект и сдвинуть границу блока обратно. Ниже блока находится сообщение от OrderController, записывающее в заказ дату его поставки и ссылку на его заказчика. Пунктирами обозначены сообщения-возвраты (return). Тут они указаны явно, но делать так всюду не обязательно, так как загромождается диаграмма. Всюду предполагается, что цепочка возвратов является "зеркальной" копией цепочки синхронных вызовов. Ниже расположен блок loop. Создание его аналогично. Сначала создается блок и указывается его тип -- Loop (свойства, закладка Model, поле Interaction Operator). Во вложенном в блок операнде взаимодействия создается сторожевое условие (Create child -> Guard -> Interaction Constraint). В окне свойств на закладке Specification задаётся значение и тип условия. Блок описывает, что для каждой позиции заказа Продавец вводит данные. Данные из формы попадают к контроллеру. Он проверяет, что введённая позиция есть в перечне предметов мебели. По результатам проверки есть два варианта действий. Если проверка успешна, контроллер запрашивает у Order добавление новой позиции. Логично возложить эту обязанность на сам заказ, чтобы оградить контроллер от лишних знаний о внутреннем устройстве заказа. Как заказ работает с собственными позициями -- это его личное дело. Если данные от Продавца ошибочны, происходит возврат в форму в ответ на сообщение //new item (неявный), и форма сообщает об ошибке. Для создания блока с альтернативой следует поместить внутри операнда взаимодействия вложенный комбинированный фрагмент. Укажите его тип (Alternative). Добавьте еще один операнда взаимодействия внутрь созданного комбинированного фрагмента. Среда автоматически укажет ему сторожевое условие [else]. Добавьте первому операнду сторожевое условие [данные верны]. Работа с сообщениями внутри второго операнда, имейте в виду, что сообщение-возврат имеет тип Reply Message, а рефлексивное сообщение //display error создается, если провести синхронное сообщение от линии жизни к самой себе. К сожалению, диаграмма грозит выйти за пределы экрана. Поэтому следует разбить её на две. Текущая версия Topcased не поддерживает должным образом элемент interaction use, который мы могли бы использовать для ссылки на взаимодействия, моделирующие окончание основного потока варианта использования. Поэтому мы воспользуемся примечанием. Внутри примечания (Body) укажем подчиненный поток Rest of BasicFlow. Диаграмма примет вид, указанный на рисунке 4.2.2. Если не хватает ширины для размещения всех линий жизни, щелкните по пустому месту на диаграмме, в окне Properties выберите закладку Graphics, измените ориентацию листа с вертикальной на горизонтальную, при желании измените формат листа на больший. Для моделирования окончания потока создадим внутри взаимодействия BasicFlow дочернее взаимодействие Rest of BasicFlow. Внутри взаимодействия создадим одноимённую диаграмму последовательности. Отредактируем их так, чтобы она приняла вид, показанный на рисунке 4.2.3. Рассмотрим в чём заключается изображенное там взаимодействие. Продавец нажимает кнопку Сохранить заказ в форме. Форма передаёт сообщение об этом контроллеру. Контроллер запрашивает данные заказа в виде строки для передачи в бухгалтерскую систему. Требуемая строка строится экземпляром заказа, который опрашивает все свои позиции, которые, в свою очередь, опрашивают связанные с ними объекты ArticleOfFurniture. Контроллер, получив строку передает её в сообщении экземпляру AccountingSystem. Если удаётся установить связь с Бухгалтерской системой, данные передаются, и соединение разрывается. В другом случае объекты, которые были созданы для представления нового заказа удаляются, и форма выдает сообщение об ошибке. Обратите внимание на фрагмент диаграммы Rest of BasicFlow, где удаляются данные заказа. Очевидно, что в потоке событий варианта использования Удалить заказ будет такое же взаимодействие. Чтобы не моделировать его дважды, можно оформить его как отдельное взаимодействие, вынести на отдельную диаграмму, и всюду, где потребуется, давать ссылаться на него.
Рис. 4.2.3. Диаграмма Rest of BasicFlow Каждое сообщение на диаграмме последовательности дает экземплярам классов обязанности по отправке и приему сообщения. Для приема сообщения в классе объекта-приемника должна быть одноименная операция. Для отправки сообщения между экземплярами классов должно быть соединение, т. е. между классами должна быть ассоциация. Рассмотрим пример. На диаграмме 4.2.2. BasicFlow форма отправляет сообщение //new order контроллеру. Найдем в Outline класс OrderController. Добавим операцию //newOrder (контекстное меню, Add child -> Owned Operation -> Operation). Поскольку профиль операции до конца не определен, она -- лишь заготовка будущей операции (операция анализа). Укажем несколько параметров. Продавец задает дату поставки заказа и название заказчика. Также форма передаёт ссылку на данные текущего пользователя, чтобы пометить, кто является автором заказа. На диаграмме последовательности следует связать сообщение и операцию. Для этого выделите сообщение в редакторе, в окне Свойства откройте закладку Model, заполните поле Operation. На диаграмме VOPC CreateOrder проведите ассоциацию между классом-формой и классом-контроллером, чтобы их экземпляры могли взаимодействовать. Самостоятельно создайте остальные операции анализа, свяжите с ними сообщения, проведите ассоциации между классами анализа. Диаграмма VOPC RegisterForCourses примет вид, показанный на рисунке 4.2.4. Рис. 4.2.4. Диаграмма VOPC CreateOrder с заготовками операций и ассоциациями, добавленными по диаграммам последовательности Укажите, что связь Order с OrderItem -- композиция (в Свойствах для одного из концов укажите Assotiation Type = composite), т. е. никакие два заказа не имеют общих позиций, и никакие позиции не существуют без своих заказов. Добавьте зависимость от OrderController к User (при создании заказа ссылка на данные текущего пользователя должна передаваться как параметр, чтобы правильно указать автора создаваемого заказа). Диаграмма должна выглядеть как на рис. 4.2.5. Рис. 4.2.5. Диаграмма VOPC CreateOrder |
||||||||||||||||||||
|
||||||||||||||||||||
Во время анализа мы уделяли внимание реализации функциональных требований, при проектировании учитываются нефункциональные требования, проект адаптируется к каркасам, библиотекам, языкам, которые будут использованы при реализации. Проектирование возглавляется архитектором, под руководством которого работают разработчики, к которым при необходимости подключают разработчиков БД и систем реального времени. Проектирование системы осуществляется итерационно. На каждой итерации ставится цель с проектировать часть системы. Для достижения этой цели друг за другом выполняются два вида работ: проектирование архитектуры системы и проектирование элементов системы. Т. е. сначала определяются части системы и их взаимодействие, а потом детально проектируется внутреннее устройство и поведение частей. При проектировании архитектуры выделяются проектные элементы (классы, интерфейсы, подсистемы), формируется иерархия архитектурных уровней, идентифицируются проектные механизмы, создается структура потоков управления, разрабатывается конфигурация системы на вычислительной среде.
| ||||||||||||||||||||
|
||||||||||||||||||||
Система обработки заказов будет работать с реляционной базой данных, где будут храниться сведения об экземплярах устойчивых объектах -- заказах, остатках и проч. Следовательно при проектировании мы будем использовать механизм обеспечения устойчивости RDBMS (relational database management system). Существуют готовые каркасы, обеспечивающие доступ к реляционным БД. К таким относится JDBC (Java Database Connectivity). Добавим в нашу модель проектный механизм. Для этого следует скачать архив с моделью. Вызовите контекстное меню в навигаторе Topcased Import -> General -> Archive File. Укажите persistency.zip. Поместите файлы Persistency.uml и Persistency.umldi в папку Models. Далее в Outline Вашей модели выберите пакет Logical View, вызовите его контекстное меню. Import From Model... -> Persistency.uml -> Design Model. Лишний (пустой) пакет Design Model удалите. В появившейся проектной модели есть два пакета: первый с описанием механизма JDBC, второй с библиотечными пакетами java. Добавление проектного механизма закончено. В Design Model создадим еще два пакета: Application и BusinessServices. Назначим пакетам Application, BusinessServices и Middleware стереотип <<layer>> -- архитектурный уровень. На уровень приложения мы будем размещать элементы пользовательского интерфейса. На уровень бизнес-служб -- элементы, относящиеся к предметной области. Уровень промежуточного ПО содержит элементы, обеспечивающие сервисы, независимые от платформы. В Design Model создадим диаграмму классов Main. Вытащим на нее все три архитектурных уровня и соединим их зависимостями, как указано на рис. 5.1.1. Чтобы содержимое пакета Middleware не мешалось, при перетаскивании его на диаграмму нажмите и удерживайте клавишу Ctrl. Если содержимое пакета Middleware всё же отобразилось, его можно убрать с диаграммы Del'ом (но не следует его удалять из модели!). Мы создали иерархию уровней системы, т. е. её устройство с точки зрения самых крупных блоков. Рис. 5.1.1. Диаграмма Main Следующие наши действия нацелены на трансформацию классов анализа в проектные элементы (классы, интерфейсы и подсистемы) и распределение проектных элементов по уровням системы. При трансформации простые классы анализа преобразуются в проектные классы один в один. Сложный класс анализа может преобразовываться в несколько связанных проектных классов или в подсистему. При анализе мы не учли вопросы, связанные с обеспечением устойчивости данных. В потоке событий система не предпринимала никаких действий, чтобы введённые данные были доступны не только в текущем сеансе работы, но и в последующих. В этом нет ошибки, во время анализа эти вопросы рассматривать рано, надо сосредоточиться на основных функциях системы. Начиная проектирование мы обращаемся к этим вопросам и должны предложить класс, ответственный за общение с базой данных системы. Таким классом может быть OrderController, так как он связан со всеми классами, данные об экземплярах которых надо будет сохранять, и манипулирует этими экземплярами -- создает заказы, удаляет и т. п. Добавление обязанностей классу OrderController делает его сложным. Поэтому при отображении в проектные классы мы переводим его в два проектных элемента -- одноимённый проектный класс OrderController и подсистему обеспечения устойчивости DBAccess. Остальные классы анализа переведем в проектные один в один. Заметим, что можно было бы отобразить класс AccountingSystem в подсистему для того, чтобы возможные изменения во взаимодействии с бухгалтерской системой мало затрагивали остальные части системы и были локализованы в подсистеме. Так как цель наших упражнений -- знакомство с Topcased и процессом разработки, мы этого делать не будем. Чтобы не испортить модель анализа, скопируем ее, чтобы из копии перенести классы в проектную модель. Outline, контекстное меню Analysis Model -> Duplicate subtree. Появился пакет Copy Of Analysis Model. Создадим в пакете Application пакет CRUDofOrders (классы не могут быть вложены непосредственно в слой, дочерними элементами слоя являются только пакеты). Сокращение CRUD расшифровывается как Create, Read, Update и Delete (создание, чтение, обновление и удаление). В созданный пакет перетащим классы MainMenuForm, CreateOrderForm, OrderController и их связи. Ассоциации, соединяющие эти классы с другими можете найти в пакете UseCase Realizations. Заметим, что стереотипы анализа в проектной модели смысла не имеют, их нужно убрать. В пакете BusinessServices создадим пакеты WarehouseArtefacts (т. е. артефакты склада, в нем разместим классы-сущности предметной области и их связи), пакет Interfaces (где будут находиться все интерфейсы), пакет DBAccess со стереотипом <<subsystem>> (в нем создадим одноименный класс). Классу DBAccess назначим стереотип <<subsystem proxy>> -- это означает, что он принимает все сообщения, идущие внутрь подсистемы. Перенесем пакет UseCase Realizations из Copy Of Analysis Model в Design Model. Диаграмму классов Copy of Key Abstractions перенесем в пакет WarehouseArtefacts. Удалим опустевший Copy Of Analysis Model. В пакете Interfaces создадим интерфейс IDBAccess. Структура проектной модели в Outline примет вид похожий на рис. 5.1.2.
Рис. 5.1.2. Структура проектной модели Создадим диаграмму классов Main в пакете BusinessServices. Разместим на ней пакеты этого архитектурного уровня, укажем их зависимости. Перетаскивая пакеты, держите нажатым Ctrl, чтобы их содержимое на диаграмме не отображалось. Подсистема реализует интерфейс, отсюда верхняя зависимость. Для описаний в верхних пакетах понадобятся классы-артефакты, отсюда две другие зависимости. Диаграмма примет вид, представленный на рис. 5.1.3.
Рис. 5.1.3. Структура уровня BusinessServices Моделировать структуру потоков управления системы не будем. Этот вопрос будет рассматриваться на лекции. Перечислим лишь виды процессов в нашей системе: WarehousemanApplication -- пользовательский процесс рабочего места заведующего складом; SalespersonApplication -- пользовательский процесс рабочего места продавца; StockmanApplication -- пользовательский процесс рабочего места кладовщика; OrderProcess -- общий процесс, управляющий обработкой заказов; AccountingSystemAccess -- процесс обеспечивающий связь с бухгалтерской системой; DBAccessProcess -- процесс, обеспечивающий связь с реляционной СУБД. Последние два нужны для обеспечения эффективности, т. е. поддержки кэшей данных. Перейдем к моделированию конфигурации на вычислительной среде. Вычислительная среда состоит из двух типов узлов -- процессоров (ExecutionEnvironment) и устройств. На процессорах можно разместить части системы -- артефакты, соответствующие рассмотренным нами процессам. Связи между узлами описывают пути коммуникации (CommunicationPath). Откроем в редакторе диаграмму размещения DeploymentView из одноименного пакета. Артефакты следует создавать, размещая их внутри узла. Окончательный вид диаграммы приведен на рис. 5.1.4. На ней показано, что в среде есть сервер обработки заказов, к которому подключен принтер и три типа рабочих станций. Для соединения рабочих станций с сервером используется локальная сеть склада. Также на диаграмме указаны узел, относящийся к окружению системы -- узел бухгалтерской системы, подключенный к серверу обработки заказов. СУБД развёрнута на сервере обработки заказов.
Рис. 5.1.4. Диаграмма размещения На этом проектирование архитектуры завершено, переходим к проектированию элементов системы. | ||||||||||||||||||||
|
||||||||||||||||||||
Проектирование элементов системы включает в себя следующие виды работ: уточнение реализаций вариантов использования; проектирование подсистем; проектирование классов и проектирование баз данных. Проектные реализации вариантов использования являются более полными, чем реализации, созданные в ходе анализа. В них вместо экземпляров классов анализа должны присутствовать экземпляры проектных классов и интерфейсов, т. е. должны быть учтены трансформации классов анализа в проектные элементы. Проведем уточнение реализаций вариантов использования. Откроем диаграмму последовательности BasicFlow из кооперации CreateOrder в пакете LogicalView::Design Model::UseCase Realizations. Классы у объектов должны быть проектными. Убедитесь в этом (см. поле Represents в окне Properties, закладка Model). Убедитесь, что все сообщения, получаемые этими объектами, связаны с операциями проектных классов. При необходимости исправьте выявленные несоответствия. На диаграмме BasicFlow следует учесть, что экземпляры классов Customer, ArticleOfFurniture являются устойчивыми, следовательно их надо запрашивать из базы данных. На диаграмму BasicFlow следует добавить линию жизни экземпляра интерфейса IDBAccess и направить к нему сообщения для поиска заказчика (findCustomer(cName:String):Customer), создания записи о новом заказчике (createCustomer(addr:String, name:String, phone:String):Customer) и проверки предмета мебели, введённого в позиции заказа (checkArticle(description:String, qty:Int):Boolean). Тем самым мы показываем, что происходит обращение к экземпляру класса, реализующему интерфейс подсистемы, отвечающей за доступ к базе данных. Какой именно это будет класс -- это для реализации варианта использования неважно. Реализация варианта использования не определяет, как подсистема DBAccess должна обрабатывать такие вызовы. Эта часть относится к проектированию подсистемы и может варьироваться в зависимости от реализации подсистемы. Внутреннее поведение подсистемы скрыто, чтобы обеспечить возможность легкой модификации ее реализации. Ненужные линии жизни экземпляров классов Customer и ArticleOfFurniture следует удалить. Диаграмма BasicFlow примет вид, представленный на рисунке 5.2.1. Не забудьте создать операции в интерфейсе и связать с ними сообщения на диаграмме. Рис. 5.2.1. Уточненная диаграмма BasicFlow На диаграмме Rest of BasicFlow следует добавить линию жизни экземпляра интерфейса IDBAccess и сообщение от экземпляра класса OrderController createOrder(o:Order) внутри первой альтернативы alt-блока. Диаграмма Rest of BasicFlow примет вид, представленный на рисунке 5.2.2. Не забудьте создать операцию в интерфейсе и связать с ней сообщение на диаграмме.
Рис. 5.2.2. Уточненная диаграмма Rest of BasicFlow Обычно при проектировании граничные классы, отвечающие за взаимодействие с пользователем, трансформируются не в один класс, а в группу классов GUI, но мы в своих упражнениях проектирование пользовательского интерфейса рассматривать не будем. Переходим к следующей технологической операции -- проектированию подсистем. Подсистема DBAccess пока содержит один класс со стереотипом <<subsystem proxy>>. Класс отвечает за реализацию интерфейса подсистемы. Объекты этого класса будут принимать и обрабатывать все входящие сообщения. Класс создается для удобства тестирования сопряжений при сборке системы. При реализации подсистемы мы воспользуемся механизмом RDBMS-JDBC. При использовании механизма классы-роли следует заменить на проектные классы системы. Среда Topcased пока не поддерживает автоматическое создание экземпляра механизма и постановку проектных классов вместо ролей. Придется вручную создать экземпляр механизма RDBMS-JDBC с подстановкой класса DBOrder вместо роли DBClass, Order – вместо PersistentClass, OrderList – вместо PersistentClassList, DBAccess вместо PersistencyClient. Продублируем на Outline пакет RDBMS-JDBC (контекстное меню, Duplicate subtree). Копию перемещаем в пакет DBAccess и переименовываем в Interface Realization. Кооперацию внутри пакета Interface Realization переименовываем в IDBAccess и указываем ей стереотип <<interface realization>> вместо <<mechanism>>. В интерфейсе IDBAccess должны быть четыре операции IDBAccess::createOrder(o:Order), IDBAccess::createCustomer(addr:String, name:String, phone:String):Customer, IDBAccess::findCustomer(cName:String):Customer, IDBAccess::checkArticle(description:String, qty:string):Boolean. Их вызовы мы ранее добавили на диаграммы последовательности. Добавим в интерфейс две операции IDBAccess::init() и IDBAccess::close(). Первая операция нужна для установления соединения с СУБД. Это соединение может устанавливаться, например, при выполнении сценария варианта использования Войти в систему. Вторая операция закрывает соединение с СУБД. Её вызов может происходить при закрытии пользователем приложения, т. е., предположительно, при выполнении сценария не учтённого нами варианта использования Выйти из системы. Диаграмму классов RDBMS-JDBC из пакета Interface Realization перенесите в пакет DBAccess и переименуйте в DBAccess. Также поступите со всеми классами и связями из пакета Interface Realization. Переименуйте класс DBClass в DBOrder. Поместите классы DBAccess, Customer и Order на диаграмму классов DBAccess. Создайте для DBAccess ассоциацию к классу DBOrder, а для Customer и Order -- те же связи, что имеют соответствующий им класс-роль PersistentClass. Удалите модели PersistencyClient. Удалите с диаграммы, но не из модели PersistentClassList и PersistentClass. Добавьте на диаграмму интерфейс IDBAccess. Укажите связью реализации, что класс DBAccess реализует интерфейс подсистемы. Переименуйте операции класса DBOrder: create -- в createCustomer(addr:String, name:String, phone:String):Customer, read -- в findCustomer(cName:String):Customer, update в checkArticle(description:String, qty:string):Boolean, delete в createOrder(o:Order). Добавьте на диаграмму класс Order и связи с ним. Укажите зависимости интерфейса от классов, чьи имена используются в сигнатурах его операций. Диаграмма классов и структура подсистемы должны быть похожи на изображенные на рисунках. Обратите внимание, что связи импорта, ассоциация и зависимости находятся в корне подсистемы. Рис. 5.2.3. Диаграмма классов подсистемы DBAccess Рис. 5.2.4. Структура подсистемы DBAccess в Outline Структура подсистемы создана. Благодаря использованию механизма мы затратили меньше сил на обдумывание и моделирование, чем если бы делали подсистему с чистого листа. Переходим к моделированию внутреннего поведения подсистемы. Внутри кооперации IDBAccess оставьте только четыре взаимодействия Initialize, Add (переименуйте в CreateCustomer), Disconnect (переименуйте в Close) и Read (переименуйте в FindCustomer). Каждое взаимодействие будет описывать, что делают объекты подсистемы при вызове соответствующей операции. Реализацию оставшихся операций createOrder и checkArticle мы моделировать не будем. На диаграмме последовательности внутри взаимодействия Initialize замените тип у экземпляра DBClass на DBOrder. Добавьте экземпляр класса DBAccess, входящее сообщение init, принимаемое им, и сообщение init от него к объекту DBOrder. Диаграмма примет вид, изображенный на рисунке 5.2.5.
Рис. 5.2.5. Диаграмма последовательности, описывающая реализацию операции initialize() Схожим образом приведите диаграмму Close в вид, изображенный на рисунке 5.2.6.
Рис. 5.2.6. Диаграмма последовательности, описывающая реализацию операции close() На диаграмме последовательности CreateOrder (бывшей Create) замените типы объектов: у экземпляра DBClass -- на DBOrder, у экземпляра PersistencyClient (самая левая линия жизни) -- на DBAccess, у экземпляра PersistentClass -- на Customer. Добавьте экземпляру класса DBAccess, входящее сообщение createCustomer, принимаемое им, и сообщение createCustomer от него к объекту DBOrder. Добавьте классу Customer новые операции: new() и setData(addr:String, name:String, phone:String). Свяжите с ними сообщения на диаграмме последовательности. Диаграмма примет вид, изображенный на рисунке 5.2.7.
Рис. 5.2.7. Диаграмма последовательности, описывающая реализацию операции createCustomer() Реализация операции createOrder будет отличаться от createCustomer тем, что не надо будет создавать экземпляры классов Order и OrderItem, так как они созданы в ходе базового потока варианта использования Ввести заказ, но для составления запроса или группы запросов к БД надо будет запросить сведения и у объекта Order и у его составных частей -- экземпляров OrderItem. На диаграмме последовательности FindCustomer (бывшей Read) замените типы объектов: у экземпляра DBClass -- на DBOrder, у экземпляра PersistencyClient (самая левая линия жизни) -- на DBAccess, у экземпляра PersistentClass -- на Customer. Добавьте экземпляру класса DBAccess, входящее сообщение findCustomer, принимаемое им, и сообщение findCustomer от него к объекту DBOrder. Удалите линию жизни PersistentClassList. Исправьте тип внешнего блока на opt. Уточните сторожевое условие внутреннего блока. Диаграмма примет вид, изображенный на рисунке 5.2.8.
Рис. 5.2.8. Диаграмма последовательности, описывающая реализацию операции findCustomer() Удалите из подсистемы классы PersistentClass и PersistentClassList. Проектирование подсистемы завершено. Переходим к проектированию классов. Проектирование классов включает следующие действия: детализацию проектных классов; уточнение операций и атрибутов; моделирование состояний для экземпляров классов; уточнение связей между классами. При детализации проектный класс может быть разбит на несколько классов из соображений, связанных с его реализацией в коде. Класс может быть удален из модели, если его экземпляры являются посредниками, не несущими содержательных обязанностей. Обязанности классов, определенные в процессе анализа и документированные в виде операций анализа, преобразуются в операции, которые будут реализованы в коде. При этом каждой операции присваивается краткое имя, характеризующее её, определяется полная сигнатура операции, создается краткое описание операции, содержащее смысл всех её параметров, определяется видимость операции, определяется область действия операции (операция экземпляра или операция класса). Уточнение атрибутов классов заключается в следующем: задается типы атрибутов, их множественность и значения по умолчанию (необязательно); задается видимость атрибутов; при необходимости определяются производные (вычисляемые) атрибуты, статические атрибуты. Если экземпляры некоторого класса реализуют сложное поведение, меняют своё поведение в зависимости от состояния, то для этого класса строят диаграмму состояний. При построении диаграммы уточняются операции, так как они могут быть связаны с событиями, вызывающими смену состояний, и с действиями на переходах и внутри состояний. Уточняются атрибуты, так как текущее состояние экземпляра определяется совокупностью значений его атрибутов. Затем производится уточнение связей между классами. Ассоциации, созданные на этапе анализа, которые соответствуют временным соединениям между объектами, заменяются на зависимости. Оставшиеся ассоциации заменяются на агрегации или композиции. Указываются мощности на полюсах, направления связей, типы множественных связей (set, ordered, bag, sequence), квалификаторы. Классы ассоциаций преобразуются в обычные с помощью материализации связей. Некоторые связи обобщения могут быть преобразованы путем метаморфозы подтипов. Рассмотрим проектирование классов на примере системы обработки заказов. Создайте в пакете WarehouseArtefacts диаграмму классов Order. Поместите классы Order и OrderItem на диаграмму. Добавьте и уточните его атрибуты и операции, чтобы придать ему вид, схожий с рисунком 5.2.8. Статические (подчеркнутые) и выводимые (начинающиеся со слэша) атрибуты и операции пометьте специальным флажком. Типы Int, Boolean и String используйте из пакета java.lang, Date -- из java.sql. Рис. 5.2.9. Диаграмма классов Order Экземпляры класса Order должны по-разному обрабатывать вызовы их операции в зависимости от состояния заказа. Например. если сборка заказа закончена, то в него нельзя добавлять новые позиции. Это признак сложного поведения и причина для создания диаграммы состояний. Добавьте классу диаграмму состояний LifeCycle (контекстное меню, Add diagram -> State Machine Diagram). Откройте диаграмму в редакторе. Создайте начальное состояние (Initial), финальное состояние (FinalState) и суперсостояние Active (Composite State). Внутри состояния Active разместите подсостояния InProcess, Canceled, Filled, Delivered и псевдосостояние выбора (Choice). Соедините состояния переходами, как указано на рисунке 5.2.10. Для добавления переходу события в окне Properties на вкладке Triggers создайте триггер. Выделив созданный триггер, создайте событие, укажите его имя и тип (CallEvent). Обратите внимание, что событие when(numOfFilledItems=numOfItems) является событием изменения (ChangeEvent). Контейнером всех событий является пакет WarehouseArtifacts. Действия на переходах создаются на вкладке Effect. Тип действий Opaque Behavior. Выделив действие в окне Outline, следует задать его тело. Особенность среды Topcased в том, что для переходов между состояниями тело действия следует указывать, в поле Name на вкладке Model окна Properties. Чтобы заставить Topcased перерисовать диаграмму состояний и отобразить внесенные Вами изменения в Outline дважды щелкните по любой другой диаграмме (например, Key Abstractions) а затем снова откройте диаграмму состояний. Сторожевые условия создаются на закладке Guard. Тип всех условий Constraint. Содержимое условия следует задавать с помощью окна Outline. Раскройте переход, выделите условие. В окне Properties на вкладке Specification создайте Literal String и введите текст условия в поле Value. Обратите внимание, что один переход является внутренним в состоянии InProcess. Его следует добавлять в окне Properties (при выделенном состоянии InProcess в Outline) на закладке Internal Transition. Тригер, сторожевое условие добавляются к внутреннему переходу также, как к обычному. Работа с действием имеет отличия. Действие на внутреннем переходе создаётся на вкладке Effect. Тип действия Opaque Behavior. Выделив действие в окне Outline, следует задать его тело. Перейдите на вкладку Advanced окна Properties. Выделите свойство Body, откройте вспомогательное окно кнопкой «...». Введите текст тела в левое поле и переместите его в поле Feature кнопкой «Add». Постройте модель состояний в соответствии с рисунками 5.2.10, 5.2.11. Учтите на будущее, если одно и то же событие присутствует на разных переходах, то создать его надо один раз, затем следует лишь связывать событие с триггером. Имена переходов в Вашей модели могут не совпадать с рис. 5.2.11.
Рис. 5.2.10. Диаграмма состояний класса Order Рис. 5.2.11. Структура модели состояний в Outline Уточним связи между классами на диаграме VOPC CreateOrder проектной реализации варианта использования Ввести заказ. Откроем диаграмму (из Design Model). Чтобы на диаграмме отобразились изменения, внесённые в ходе проектирования, удалим классы с диаграммы, но не из модели (выделите все и нажмите Del). Заново перетащите классы MainMenuForm, CreateOrderForm, OrderController, Order, OrderItem, User, Customer и интерфейс IDBAccess из Outline на диаграмму (см. рис. 5.2.12). Уточните связи. Зависимость (пунктирная стрелка) указывает на то, что связи между экземплярами временные, а не постоянные как в случае ассоциации. OrderController хранит ссылку на объект с данными текущего пользователя и на текущий заказ (агрегации -- AssotiationType: shared). Укажите направления ассоциаций (флажок isNavigable) и типы. Рис. 5.2.12. Уточненная диаграмма классов VOPC CreateOrder Если среди проектных классов есть устойчивые, чьи экземпляры должны сохраняться в периодах между запусками системы, следует обеспечить сохранение их в базе данных (например, реализовав подсистему обеспечения устойчивости на базе JDBC) и создать схему базы данных. Фактически, следует отобразить объектную модель в реляционную. Одна из стратегий при этом состоит в том, что для каждого устойчивого класса создается собственная таблица. Атрибуты класса переводятся в столбцы таблицы. Атрибут-идентификатор становится первичным ключом. Ассоциации моделируются с помощью связей между таблицами (связывающими значения первичного ключа записей одной таблицы со значениями внешнего ключа другой таблицы). Заметим, что связи между таблицами всегда двунаправленные, по записям любой из связанных таблиц можно найти соответствующие записи другой таблицы. Связи между таблицами могут быть идентифицирующими и неидентифицирующими. Идентифицирующая связь указывает, что внешний ключ включает в себя часть первичного ключа. Связь отображается как композиция, если требуется указать на зависимость по существованию. В некоторых случаях для ассоциации (например, * к *) требуется создавать таблицу, хранящую соединения между объектами. Для отображения обобщений используются разные способы. Один из них -- "отдельная таблица для каждого класса". В этом случае у всех получившихся таблиц будет один и тот же первичный ключ, который в таблицах подклассов будет также внешним ключом. В таблицах моделируются ограничения в виде «операций». Т. е. ограничения первичного ключа, ограничения внешнего ключа, ограничения индекса, ограничения уникальности указываются в разделе, предназначенном для операций. Осуществим проектирование базы данных. В корне Design Model создайте диаграмму классов DataBase Schema. Создайте 2 класса со стереотипом <<table>>. См. рисунок 5.2.13. Эту схему можно использовать для хранения экземпляров класса Order и их составных частей. Каждая запись о заказе состоит из 6 столбцов, один из которых является первичным ключом (<<PK>>). Столбцы для хранения выводимых атрибутов можно не заводить. Как "операция" таблицы TableOrder моделируется ограничение первичного ключа. Позиции заказа хранятся в отдельной таблице TableOrderItem. В этой таблице 5 столбцов, один из которых является частью первичного ключа (<<PK>>), а другой -- внешним ключом (<<FK>>) и частью первичного ключа. В таблицу добавлены ограничения первичного и внешнего ключа и ограничение индекса. Связь между таблицами идентифицирующая, так как часть первичного ключа входит во внешний ключ. Согласно этой схеме одному объекту -- экземпляру класса Order -- будут соответствовать одна запись в таблице TableOrder и связанные с ней записи в таблице TableOrderItem. Во всех этих записях будет одно и то же значение номера заказа. Для любой записи в таблице TableOrderItem можно найти связанную с ней запись из таблицы TableOrder о заказе, к которому относится эта позиция. И наоборот, для любой записи из таблицы TableOrder можно найти связанные с ней записи из таблицы TableOrderItem о позициях этого заказа. Очевидно, связь между таблицами двунаправленная.
Рис. 5.2.13. Диаграмма классов DataBase Schema Упражнения по анализу и проектированию системы обработки заказов на этом закончены. Остались не реализованными остальные варианты использования, но мы не ставили целью полностью спроектировать систему, лишь рассмотрели работы, выполняемые в рамках разных процессов жизненного цикла. Перед тем как сдавать полученную модель, попробуйте ответить на вопросы из списка. |
||||||||||||||||||||
|
||||||||||||||||||||
Размещение на других ресурсах, а также коммерческое использование материалов, опубликованных в данном разделе, возможно только с разрешения авторов. По всем вопросам пишите: |
||||||||||||||||||||
|