Главная страница « Информация « ООАП«

Работа над учебной UML-моделью в среде Visual Paradigm 16.2. Система регистрации на курсы


Пособие составлено доц. кафедры СП, канд. физ.-мат. наук Малышко В. В.

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

Содержание


1. Вводные сведения о среде Visual Paradigm
2. Начальное описание создаваемой системы
3. Моделирование требований к системе регистрации на курсы
      Упражнение 3.1. Создание начальной версии UML-диаграммы вариантов использования
      Упражнение 3.2. Создание уточнённой версии UML-диаграммы вариантов использования
      Упражнение 3.3. Составление описаний вариантов использования
      Упражнение 3.4. Создание UML-диаграмм деятельности
4. Эскизное моделирование системы
      Упражнение 4.1. Создание структуры логического архитектурного представления в соответствии с соглашениями моделирования
      Упражнение 4.2. Анализ варианта использования «Войти в систему»
      Упражнение 4.3. Анализ варианта использования «Зарегистрироваться на курсы»
      Упражнение 4.4. Анализ варианта использования «Закрыть регистрацию»
5. Проектное моделирование системы
      Упражнение 5.1. Проектирование архитектуры системы
      Упражнение 5.2. Проектирование элементов системы
      Упражнение 5.3. Создание UML-диаграммы классов, моделирующей схему реляционной базы данных

1. Вводные сведения о среде Visual Paradigm


      Visual Paradigm [www.visual-paradigm.com] версии 16.2 -- среда моделирования, поддерживающая работу с несколькими визуальными нотациями, в том числе с UML. Версия Community Edition предоставляется бесплатно для некоммерческого использования. Для установки следует загрузить дистрибутив со страницы загрузки, установить его. Среда является многоплатформенной. GUI среды для разных платформ различается. В пособии описана реализация для Windows. При установке укажите путь, например, C:\Program Files\Visual Paradigm CE. Для запуска среды вызывается исполняемый файл Visual Paradigm.exe из директории C:\Program Files\Visual Paradigm CE\bin. При первых запусках среда может предлагать сообщить своё имя и e-mail для получения регистрационного кода. Получив код по электронной почте, следует активировать лицензию. Некоторые функции среды доступны только в её платных версиях. Упражнения составлены с таким расчётом, что для их выполнения достаточно возможностей бесплатной версии (Community Edition).

      Запустив среду, указываем путь к рабочей области (workspace), в которой будет находиться файл нашего проекта. Если автоматически не появилось окно Workspace Launcher, Вы можете самостоятельно настроить путь к рабочей области через меню Help -> Switch Workspace (или возможный вариант: File -> Switch Workspace). Настроим вид окна приложения. Вкладка меню Window -> Application options -> General -> вкладка Appearance (или возможный вариант: меню -> Tools -> Application options -> General -> вкладка Appearance). Устанавливаем User Interface: Sleek; Look & Feel Theme: Xetro LookAndFeel. Можно видеть настройку, якобы позволяющую русифицировать среду. Лучше её не использовать и оставить англоязычную версию, так как русификация выполнена из рук вон плохо. Чтобы настройки вступили в силу, применяем их (кнопка Apply) и перезапускаем среду. Если Вы оставите настройки по умолчанию, то вид окон и меню и названия опций будут отличаться. Далее в пособии будут приводиться скриншоты для настроек Sleek+Xetro L&F+English.

      Необходимо начинать не с пустого проекта, а с шаблона проекта, в котором уже содержится дерево будущей модели, добавлены стереотипы и проектные механизмы JDBC и XMLRPCInterchange. Загружаем архив шаблона [zip] с веб-странички курса. Разворачиваем его в рабочую область. В рабочей области появился каталог с пиктограммами стереотипов, файл с описанием стереотипов stereotypes.xml и файл проекта myProject.vpp. Откроем проект Project -> Open (перед открытием Вы можете переименовать файл проекта так, чтобы в имени была Ваша фамилия, номер группы и номер варианта первого задания, например, Obraztsov630var1.vpp). Если появилось окно Project Browser с эскизами диаграмм, то выбираем двойным щелчком какую-либо диаграмму, например, диаграмму вариантов использования Main. Чтобы использовать набор стереотипов технологии Unified Process, осуществляем настройку. Вкладка меню Window -> Configuration -> Manage Stereotypes... -> Import. Файл с описаниями стереотипов находится в workspace. Он называется stereotypes.xml. При импорте выбираем способ разрешения конфликтов Overwrite All. Закрываем вкладку Diagram Navigator (если она открыта) и открываем вкладку Model Explorer (меню View -> Panes -> Model Explorer). После этого Окно Visual Paradigm примет вид, показанный на рисунке 1.1.


Рис. 1.1. Окно Visual Paradigm после открытия шаблона проекта с проводником моделей

Рис. 1.1. Окно Visual Paradigm после открытия шаблона проекта с проводником моделей

      В левой верхней части находится проводник, показывающий структуру проекта в виде дерева. Для наших целей больше всего подходит Model Explorer. Преимущественно будем использовать его. В этот проводник мы будем добавлять диаграммы, пакеты, и другие составляющие модели с помощью контекстного меню. С его помощью будет удалять из проекта элементы и/или связи, ставшие ненужными или созданные по ошибке. Правая часть окна состоит из редактора диаграмм. Помимо проводника может быть полезен Diagram Navigator (меню View -> Panes -> Diagram Navigator). В нём можно быстро найти и открыть нужную диаграмму, если известен её тип (например, диаграмма вариантов использования) и её название (например, Main).


Рис. 1.1a. Окно Visual Paradigm после открытия шаблона проекта с навигатором диаграмм

Рис. 1.1a. Окно Visual Paradigm после открытия шаблона проекта с навигатором диаграмм

      Согласно технологии Unified Process на верхнем уровне модель должна состоять из четырёх пакетов, называемых архитектурными представлениями (см. Рисунок 1.1). Каждый из них показывает будущую систему с определённой точки зрения. Представление вариантов использования (Use Case View) содержит модель требований к системе. Логическое представление (Logical View) содержит логическую структуру системы, её организацию в классы и пакеты. Представление реализации (Component View) описывает организацию компонент, из которых осуществляется сборка системы. Представление размещения (Deployment View) содержит модель вычислительной среды, в которой будет функционировать система.

      Выделим в проводнике элемент Use Case View. Вызвав контекстное меню элемента Use Case View в Model Explorer правым кликом, выберите пункт Open Use Case View Specification. Откроется полная спецификация элемента в виде отдельного окна с вкладками. На вкладке General указано имя элемента и его основные свойства. На вкладке Stereotypes -- его стереотипы. Видно, что к этому элементу применён стереотип «architectural view», указывающий, что пакет является архитектурным представлением.

      Вводные сведения даны, переходим к моделированию.

2. Начальное описание создаваемой системы


       Перед руководителем IT-службы университета ставится задача разработки программной системы регистрации студентов на курсы. Предполагается, что учебный план (расписание на текущий семестр) студентов не является единым и определяется индивидуально для каждого студента перед началом семестра по заявкам студентов и профессоров.

      Регистрация на курсы происходит следующим образом: в начале каждого семестра профессора обращаются в учебный отдел, чтобы указать, по каким учебным дисциплинам они собираются прочитать лекции в новом семестре. Про каждую такую дисциплину профессор сообщает её название, длительность и требования к предварительному уровню подготовки (т. е. перечень дисциплин, которые необходимо освоить прежде, чем слушать лекции по данной дисциплине). Все эти данные собирают и хранят сотрудники учебного отдела. Для каждой дисциплины назначается время лекции -- день недели и номер пары -- и фиксируется в расписании как предлагаемый курс. Каждый студент может ознакомиться со списком предлагаемых курсов и составить из них свой индивидуальный план. Студент может выбрать 4 предлагаемых курса, которые в его плане будут основными. Дополнительно студент может указать 2 альтернативных курса на тот случай, если какой-либо из основных курсов окажется уже заполненным или отменённым. Студент может вносить курс в план только в том случае, если им выполнены требования к предварительному уровню подготовки (т. е. им ранее прослушаны и сданы курсы по дисциплинам, освоение которых необходимо перед изучением выбранного курса). На каждый курс может записаться не более 10 студентов. Если курс окажется заполненным (предоставленные 10 мест исчерпаются) в процессе регистрации, регистрирующиеся студенты должны быть извещены об этом, лишние заявки на курс не принимаются. В ходе регистрации профессор может выбрать другой набор читаемых им дисциплин в текущем семестре, т. е., фактически, отказаться от чтения некоторого курса, отменить его. Также курс, ранее не выбранный ни одним другим профессором, может быть выбран для чтения. В ходе регистрации студенты могут изменить свои планы (отказаться от ранее выбранных курсов, добавить новые). Всего на процесс регистрации отводится две недели. Регистрация на отдельный курс может быть закончена раньше по решению учебной части. Курс считается отменённым по окончании регистрации, если на него записалось менее 4 студентов.

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

3. Моделирование требований к системе регистрации на курсы


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

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

      Требования оформляются в виде ряда документов и моделей. К основным документам, согласно технологии Unified Process, относятся: концепция, глоссарий предметной области, дополнительная спецификация. Концепция определяет глобальные цели проекта и основные особенности разрабатываемой системы. Существенной частью концепции является постановка задачи разработки, определяющая требования к функциям системы. Словарь предметной области (глоссарий) определяет общую терминологию для всех моделей и описаний требований к системе. Дополнительная спецификация (технические требования) содержит описание нефункциональных требований к системе, таких, как надёжность, удобство использования, производительность, сопровождаемость и др.

      Постановка задачи разработки системы регистрации на курсы:

      Необходимо разработать систему регистрации студентов на курсы. Пользователями новой системы будут студенты, профессора, а также регистраторы -- работники учебного отдела, управляющие ходом регистрации, ведущие работу с данными о студентах, профессорах, предлагаемых курсах, дисциплинах.
      В начале каждого семестра студенты могут запросить список курсов, предлагаемых для изучения в данном семестре. Данные о каждом курсе должны включать название дисциплины, его длительность, время проведения занятий (день недели и номер пары), имя профессора-лектора (если назначен) и требования к предварительному уровню подготовки (т. е. перечень дисциплин, которые необходимо пройти прежде, чем слушать курс по выбранной дисциплине).
      Система должна позволять студентам составлять индивидуальный план из 4 основных курсов и 2 альтернативных курсов. На каждый курс может записаться не более 10 студентов. Студент может регистрироваться на курс только, если выполнены требования к предварительному уровню подготовки. До окончания регистрации студенты могут изменить свои индивидуальные учебные планы. В это время студенты должны иметь доступ к системе, чтобы добавить или удалить из своего плана выбранные курсы. После того, как процесс регистрации некоторого студента завершён, система регистрации направляет данные об учебном плане студента в расчётную систему, функционирующую в бухгалтерии, чтобы студент мог внести плату за семестр. Если все 10 мест на курсе окажутся заполненными в ходе регистрации, то студент должен быть извещён об этом до окончательного формирования его учебного плана. Лишние заявки на курс не принимаются.
      Студенты должны иметь возможность просмотра своих электронных табелей успеваемости за текущий семестр. Поскольку данные об успеваемости конфиденциальны, система должна обеспечивать их защиту от несанкционированного доступа. Доступ на чтение своих оценок предоставляется самому студенту. Профессора имеют доступ на чтение, изменение, добавление данных об оценках по читаемым ими курсам только тех студентов, что записались на курсы этих профессоров.
      Профессора должны иметь доступ к онлайновой системе, чтобы выбрать дисциплины, по которым они будут читать лекционные курсы. Для каждого курса система хранит день недели и номер пары, когда проводятся лекции.
      Регистрация на отдельный курс может быть закончена раньше по решению регистратора. Курс считается отменённым по окончании регистрации, если на него записалось менее 4 студентов. Регистрация на все курсы закрывается регистратором спустя две недели после её начала. По окончании регистрации профессору будет доступен список студентов, записавшихся на его курсы. Кроме этого, профессора должны иметь возможность работать с данными об оценках студентов по их курсам при подведении итогов семестра.
      Регистраторы должны иметь возможность вносить в систему, а также просматривать, изменять, удалять данные о студентах, профессорах, курсах, дисциплинах.


      Глоссарий предметной области составляется на основе описания создаваемой системы, постановки задачи, глоссария деятельности предприятия, созданного в ходе бизнес-моделирования, и концепции. Этот глоссарий предназначен для описания терминологии области, в которой будет работать система. Выделяются термины, им даётся описание, рассчитанное на широкий круг читателей (пользоваться этим описанием будут все лица, заинтересованные в разработке системы). Глоссарий составляется на русском языке. Термины сопровождаются переводом на английский на тот случай, если термин будет использован в модели системы как название класса, пакета и другого элемента модели.

      Глоссарий предметной области:

Дисциплина
(Course)

Учебная дисциплина (некоторый изучаемый предмет), по которой может быть прочитан семестровый курс лекций. Дисциплины различаются названиями, длительностью. Дисциплины могут быть связаны межу собой требованиями на предварительно изученные дисциплины. Например, ТФКП может быть изучена после освоения математического анализа, а завершение изучения ТФКП позволяет осваивать функциональный анализ.

Оценка
(Mark)

Количество баллов (от 2 до 5), полученных студентом при сдаче курса по какой-либо дисциплине, прослушанного в течение какого-то семестра.

Индивидуальный учебный план
(Schedule)

Набор предлагаемых курсов, выбранных студентом для изучения в некотором семестре. Индивидуальный учебный план включает в себя 4 основных и 2 альтернативных предлагаемых курса.

Предлагаемый курс
(Course Offering)

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

Профессор
(Professor)

Пользователь системы регистрации. Лектор произвольного количества предлагаемых курсов в течение семестра. Отмечает в системе читаемые им в семестре предлагаемые курсы, ставит оценки студентам при подведении итогов по курсам. Основные сведения о профессоре -- имя, учёная степень, до двух телефонных номеров.

Расчётная система
(Billing System)

Внешняя программная система, в которую система регистрации передаёт данные об индивидуальных учебных планах для формирования счетов за обучение.

Регистратор
(Registrar)

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

Регистрация на курсы
(Registration)

Процесс привязки студентов и профессоров к предлагаемым в семестре курсам по дисциплинам. Длится 2 недели.

Список курса
(Roster)

Список всех студентов, записавшихся на некоторый предлагаемый курс. В каждом таком списке не более 10 студентов.

Студент
(Student)

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

Табель успеваемости
(Report Card)

Все оценки за все курсы, полученные студентом в некотором семестре.

      Дополнительная спецификация определяет нефункциональные требования к системе: надёжность, удобство использования, производительность, сопровождаемость, а также ряд функциональных требований, являющихся общими для нескольких вариантов использования, -- так называемых бизнес-правил. Назначение дополнительных спецификаций -- определить требования к системе регистрации на курсы, которые не отражены в других документах и моделях. Рассмотрим дополнительную спецификацию:

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

    • Студент может регистрироваться на курс только в том случае, если им выполнены требования к предварительному уровню подготовки.

    • На каждый курс лекций может записаться не более 10 студентов.

    • На регистрацию студентов отводится две недели.

    • Предлагаемый курс считается отменённым по окончании регистрации, если на него записалось менее 4 студентов. И т. п.

  2. Требования по реализации
    Система должна быть реализована на Java.

  3. Надёжность
    Система должна быть в работоспособном состоянии 24 часа в день 7 дней в неделю, время простоя -- не более 10%.

  4. Производительность
    Система должна поддерживать до 2000 одновременно работающих пользователей.

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

  6. Проектные ограничения
    Система должна поддерживать протокол обмена данными с расчётной системой.

      Функциональные требования к системе моделируются и документируются в виде вариантов использования (use case). Вариант использования (use case) -- связный элемент функциональности, предоставляемый системой при взаимодействии с действующими лицами, и соответствующий цели некоторого действующего лица. Действующее лицо (actor) -- роль, обобщённое описание элементов внешнего окружения системы, ведущих себя по отношению к системе одинаковым образом. Такие роли исполняют либо люди-пользователи системы, либо внешние системы, взаимодействующие с системой. Изредка роль действующего лица исполняет устройство или даже некий невычислительный процесс, протекающий во внешней среде: ход времени, изменение температуры воздуха и т. п..

      В контексте процесса описания требований варианты использования трактуются следующим образом:

  • вариант использования фиксирует соглашение между участниками проекта (членами проектной группы, заказчиками и др.) относительно поведения системы;

  • вариант использования описывает поведение системы при различных условиях, когда система отвечает на запрос одного действующего лица, называемого основным действующим лицом;

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

      Модель вариантов использования состоит из диаграммы вариантов использования, текстовых описаний вариантов использования и диаграмм деятельности, моделирующих потоки событий вариантов использования. UML-диаграмма вариантов использования составляется системным аналитиком, который сначала выявляет элементы модели (use case, actor, subject), затем устанавливает связи между ними, после чего структурирует модель, вводя вспомогательные действующие лица и/или варианты использования. Элементами диаграммы вариантов использования являются варианты использования и действующие лица, соединённые разного рода связями. Также элементом диаграммы вариантов использования являются субъект (subject) -- рамки моделируемой системы.

      Из постановки задачи разработки и глоссария системы регистрации на курсы системный аналитик может выделить список действующих лиц и их интересов:

  • Студент -- регистрируется на курсы, смотрит свой табель;

  • Профессор -- выбирает курсы для преподавания, ставит оценки по своим курсам;

  • Регистратор -- управляет ходом регистрации, ведёт (т. е. вводит, изменяет, удаляет) данные о профессорах, студентах, дисциплинах, учебных курсах;

  • Расчётная система -- получает данные об индивидуальных учебных планах студентов, нужные для формирования счетов за обучение.

Упражнение 3.1. Создание начальной версии UML-диаграммы вариантов использования

(общее для всех вариантов)


      1. В Проводнике моделей найдите пакет Use Case View, а внутри него модель Use Case Model. В модели находится диаграмма вариантов использования Main. Откройте её двойным кликом. UML-диаграмма пуста. Заполним её. Если Вы работаете на FullHD-дисплее или с ещё большим разрешением, то желательно установить увеличение 130% или выше (Ctrl+), чтобы Ваши диаграммы были обозримы на обычном дисплее. С таким увеличением все элементы диаграммы и все связи между ними должны помещаться на экране. Для этого старайтесь располагать элементы плотнее друг к другу. В палитре найдите элемент System. Нажмите на него. Затем поместите курсор на диаграмму и кликните. Система (рамки моделируемой системы -- subject) появится на диаграмме. Назовите добавленный элемент "Система регистрации на курсы". С помощью контекстного меню добавьте этому элементу стереотип «subject». В палитре редактора выберите элемент Actor и добавьте действующее лицо на диаграмму. Введите имя действующего лица: Студент. Повторите те же действия и добавьте оставшихся действующих лиц: профессора, регистратора и расчётную систему. Увеличьте размеры рамок моделируемой системы, чтобы в дальнейшем в них поместились варианты использования системы. Получившаяся диаграмма примет вид, показанный на рисунке 3.1.1.



Рис. 3.1.1. Окно Visual Paradigm с заготовкой UML-диаграммы вариантов использования

Рис. 3.1.1. Окно Visual Paradigm с заготовкой UML-диаграммы вариантов использования (для всех вариантов)

      Исходя из потребностей действующих лиц, системный аналитик может предложить следующие варианты использования: Зарегистрироваться на курсы, Просмотреть табель, Выбрать читаемые курсы, Поставить оценки, Открыть регистрацию, Закрыть регистрацию, CRUD данных о профессорах, CRUD данных о студентах, CRUD данных о курсах. Все эти варианты использования относятся к «уровню моря», т. е. соответствуют цели одного из пользователей системы. Такую цель пользователь может достичь в течение одного сеанса работы с системой. CRUD расшифровывается как Create, Read, Update, Delete (или как Create, Retrieve, Update, Destroy). Предполагается, что вариант использования «CRUD данных о профессорах» описывает все функции системы, предоставляемые регистратору для управления сведениями о профессорах.

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

      1. В палитре редактора выберем элемент Use Case и добавим вариант использования на диаграмму (внутрь System). Введём название: «Зарегистрироваться на курсы». Повторим те же действия для добавления оставшихся вариантов использования: Войти в систему, Просмотреть табель, Выбрать читаемые курсы, Поставить оценки, CRUD данных о профессорах, CRUD данных о студентах, CRUD данных о курсах и дисциплинах, Открыть регистрацию, Закрыть регистрацию. Каждый вариант использования пометим стереотипом, указывающим его уровень. Для этого вызываем контекстное меню правым кликом, выбираем пункт Stereotypes и нужный стереотип в списке. Все варианты использования кроме «Войти в систему» следует пометить стереотипом «sea level usecase», а «Войти в систему» -- «fish level usecase». Разместить варианты использования на диаграмму следует примерно так, как показано на рисунке 3.1.2.

      2. В палитре редактора выберем ассоциацию (Association) и проведём её от действующего лица Студент к варианту использования »Зарегистрироваться на курсы». Чтобы было видно направление связи, вызовем контекстное меню у левого конца ассоциации и выберем пункт Navigable. Установим флажок на значении Unspecified. По умолчанию связь была двунаправленная, теперь же она явно указывает, направление от действующего лица к варианту использования (т. е., что Студент -- основное действующее лицо для этого варианта использования).

      3. Повторим те же действия для добавления связей других действующих лиц и вариантов использования. Получившаяся диаграмма изображена на рис. 3.1.2. Направления связей между действующими лицами и вариантами использования показывают, какое лицо является основным, а какое второстепенным. Для варианта использования Закрыть регистрацию основное действующее лицо -- Регистратор (он инициирует запуск варианта использования), а Расчётная система -- второстепенное действующее лицо (в ходе работы в неё передаются данные об учебных планах для формирования счетов за обучение студентов).

Рис. 3.1.2. Начальная версия UML-диаграммы вариантов использования

Рис. 3.1.2. Начальная версия UML-диаграммы вариантов использования (для всех вариантов) (на диаграмме имеется дефект!)

Упражнение 3.2. Создание уточнённой версии UML-диаграммы вариантов использования

(общее для всех вариантов)


      Созданная диаграмма имеет дефект, заключающийся в том, что у варианта использования «Войти в систему» несколько основных действующих лиц (см. ассоциации, выделенные красным цветом, на рисунке 3.1.2). Согласно диаграмме при каждом входе в систему одновременно три пользователя системы -- Студент, Профессор и Регистратор -- взаимодействуют с системой. Полагая, что пользователи входят по одиночке, а не по трое, и что поведение системы одинаково при входе любого пользователя, введём вспомогательное абстрактное действующее лицо Пользователь, подвидами которого будут лица Студент, Профессор, Регистратор. Указать, что действующее лицо является абстрактным, нужно в спецификации (контекстное меню -> Open specification) на вкладке General, поставив флаг в поле Abstract. UML-диаграмма примет вид, изображённый на рисунке 3.2.1. Для добавления связей обобщения используйте связь обобщения (Generalization). Лишние ассоциации удалите из модели, выделяя их в Model Explorer и нажимая Del. Чтобы связи отображались в Model Explorer, осуществите его настройку: вызовите контекстное меню на белом поле Model Explorer и отметьте флажком Show Relationships. Обратите внимание, что лишний элемент (или связь) следует удалить из модели (выделяя их в Model Explorer и нажимая Del). Если необходимо сохранить элемент (или связь) в модели и всего лишь убрать с диаграммы, на которую он случайно попал по какой-то причине, выделите элемент или связь на диаграмме и используйте пункт контекстного меню Delete -> Delete View Only. Следует чётко понимать, удаляете ли Вы текущий элемент из модели или всего лишь убираете с диаграммы, оставляя в модели (маскируете). Удаление вместо маскирования (как и обратное) может быть нежелательным. Случайно удалённый элемент можно попытаться восстановить, нажав Ctrl+z. Маскированный по ошибке элемент можно снова поместить на диаграмму, перетаскивая его из Model Explorer. Работать с моделью следует аккуратно, не оставляя в ней «мусора» -- случайно созданных элементов и/или связей, не видимых на диаграммах.


Рис. 3.2.1. Уточнённая версия UML-диаграммы вариантов использования

Рис. 3.2.1. Уточнённая версия UML-диаграммы вариантов использования (для всех вариантов / дефект начальной версии исправлен!)

      Теперь на нашей диаграмме каждый вариант использования связан ровно с одним действующим лицом, которое для него является основным, и с произвольным количеством второстепенных действующих лиц. Каждое действующее лицо прямо или косвенно связано хотя бы с одним вариантом использования. Никакие два варианта использования между собой не связаны ассоциацией. Связи между вариантами использования допускаются, если они имеют тип, отличный от ассоциации (или если это варианты использования, применённые к рамкам разных систем, но мы такое не моделируем). Между вариантами использования могут быть связи обобщения, включения и расширения. О них рассказывается на лекции, посвящённой моделированию требований к программному обеспечению. Системный аналитик с помощью таких связей производит структурирование модели вариантов использования. Модель с большим количеством вариантов использования может быть разбита им на части -- пакеты.

      На нашей диаграмме никакие действующие лица не связаны между собой ассоциацией (т. к. стандарт UML это запрещает). Между действующими лицами допускаются лишь связи обобщения. Самостоятельно создавая диаграммы вариантов использования, старайтесь, чтобы их элементы и связи удовлетворяли таким же ограничениям. Также рекомендуется действующих лиц-людей размещать в левой части диаграммы, а действующих лиц, не являющихся людьми, -- на правой. Рекомендуется родительские элементы в иерархии наследования/обобщения размещать выше и/или левее их сыновних элементов (наследников).

      Получившаяся диаграмма является примерным оглавлением проекта. Мы видим, какие функции и кому предоставляет система. По диаграмме архитектор проекта может составить примерную оценку трудоёмкости всего проекта, основанную на прогнозируемой трудоёмкости реализации каждого из вариантов использования. Также архитектор может ранжировать варианты использования по приоритету. Отмеченные им более важные варианты использования будут проанализированы, спроектированы и реализованы в первую очередь.

      Для каждого варианта использования составляется описание. Выполняют эту работу use case писатели.

Упражнение 3.3. Составление описаний вариантов использования

(общее для всех вариантов)


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

      Каждый поток событий (или сценарий) задаётся перенумерованным набором шагов. Используются шаги следующих типов: шаг системы (например, «Система запрашивает имя пользователя и пароль»); шаг действующего лица («Пользователь вводит имя и пароль»); шаг подтверждения («Система подтверждает правильность имени и пароля.»); шаг управления («Выполнение переходит на шаг №… основного потока»); шаг обнаружения («Система обнаруживает, что комбинация имени и пароля не верна.»); шаг завершения («Вариант использования завершается неуспешно.»). Структура предложений, описывающих шаги, одинакова: подлежащее, сказуемое и прочее. От неё отходят лишь при описании циклов и ветвлений.

      Цикл задаётся составным описанием, в начале которого указывается условие цикла («Для каждого не зафиксированного курса в учебном плане выполняется») или количество повторений. Далее следует тело цикла -- последовательность вложенных шагов (см. подчинённый поток «8Г. Утвердить учебный план» варианта использования «Зарегистрироваться на курсы»).

      Ветвление в тривиальных случаях, когда альтернативная ветвь пуста, допускается описывать предложением с союзом если («Система помечает курс как закрытый, если в списке студентов содержится 10 записей»). Чаще ветвление описывают с помощью альтернативных потоков. В основном потоке варианта использования «Войти в систему» 4-й шаг -- шаг подтверждения -- указывает основное продолжение потока, а альтернативный поток «4А. Неправильное имя/пароль» содержит второй вариант развития событий и начинается с шага обнаружения. Почти всегда действия по проверке условия ветвления не описывают. Вместо этого указывается шаг на котором система (или действующее лицо) подтверждает, что условие выполнено, в основном потоке, и другой шаг, где система обнаруживает, что условие нарушено, в альтернативном потоке.

      Соберите в единый текстовый файл описания, приведённые ниже. Для этого скопируйте тексты описаний в окно текстового редактора (Word, Writer и т. п.) и сохраните в формате pdf. Обратите внимание, что в описании любого варианта использования должен присутствовать хотя бы один шаг для каждого действующего лица, связанного с ним ассоциацией. Постусловие в описании не может отсутствовать, так как по нему тестировщики составляют тестовые сценарии. Постусловие состоит из двух частей: гарантии успеха и минимальных гарантий. Первая часть описывает, что должно быть истинно при успешном завершении варианта использования. Вторая часть -- это гарантии системы во всех случаях, в том числе в случаях неуспеха. Например, при успешном входе в систему гарантируется доступ пользователя к главному меню, но в любом случае (даже при неуспехе) -- гарантируется, что доступ не будет предоставлен тем, кто не может указать верную комбинацию пароля и логина. Пустое постусловие допускало бы произвольное поведение системы и было бы не пригодно для тестирования. Неполное постусловие без минимальных гарантий (описывающих, что система не должна предоставлять доступ при неудачном входе) также непригодно. Обратите внимание, что следует явно указывать шаг неуспешного завершения варианта использования. Шаг успешного завершения обычно явно не указывают, если он находится в конце основного потока событий.

      Выполняя упражнения, мы создадим полные описания лишь для 3х вариантов использования, а остальные опишем кратко.

      Вариант использования «Войти в систему»:

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

Область действия: система как «чёрный ящик».

Уровень: подфункция («уровень рыбы»).

Основной поток событий:
1. Пользователь запускает приложение.
2. Система запрашивает имя пользователя и пароль.
3. Пользователь вводит имя и пароль.
4. Система подтверждает правильность имени и пароля.
5. Система определяет тип пользователя (студент, профессор или регистратор) и выводит главное меню, дающее доступ к её функциям в соответствии с типом пользователя.

Альтернативные потоки:
4А. Неправильное имя/пароль
1. Система обнаруживает, что комбинация имени и пароля не верна.
2. Система сообщает об ошибке и завершает работу приложения.
3. Вариант использования завершается неуспешно.

Предусловия: Отсутствуют.

Гарантии успеха: Система предоставляет доступ к главному меню пользователю, сообщившему верную комбинацию имени и пароля, в соответствии с типом пользователя.

Минимальные гарантии: Пользователю, не сообщившему верную комбинацию имени и пароля, доступ к меню не будет предоставлен.


      Обратите внимание на номер альтернативного потока. Цифра указывает номер шага основного потока, на котором может произойти переключение на альтернативный поток, буква позволяет различить альтернативные потоки (если их несколько), на которые можно переключиться на одном и том же шаге. Если переход на альтернативный поток может происходить в течение нескольких подряд идущих шагов, указывают их номера через дефис (например, 1-3Б). Если поток вызывается из разных шагов, он может иметь несколько номеров, перечисленных через запятую.

      Вариант использования «Зарегистрироваться на курсы»:

Краткое описание: Описывается регистрация студента на предлагаемые курсы. Студент может создать / обновить / удалить / утвердить свой учебный план, если операция выполняется в установленное время в начале семестра.

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

Основной поток событий:
1. Студент сообщает о желании зарегистрироваться на курсы.
2. Система подтверждает, что регистрация на курсы в текущем семестре открыта.
3. Система выводит перечень доступных действий и предлагает студенту выбрать одно из них.
4. Студент сообщает системе свой выбор.
5. Согласно выбору студента выполняется один из подчинённых потоков 5А-Г.

Подчинённые потоки событий:
5А. Создать учебный план
1. Система подтверждает, что у студента отсутствует учебный план на текущий семестр.
2. Система выводит пустой учебный план.
3. Студент запрашивает список предлагаемых курсов текущего семестра.
4. Система выводит список предлагаемых курсов.
5. Студент выбирает из списка четыре основных курса и два альтернативных курса.
6. Система создаёт учебный план студента и заносит в него выбранные курсы, помечая их как не зафиксированные.
7. Система сообщает, что создание учебного плана завершено.
5Б. Обновить учебный план
1. Система подтверждает наличие у студента учебного плана на текущий семестр и выводит его.
2. Студент запрашивает список предлагаемых курсов текущего семестра.
3. Система выводит список предлагаемых курсов.
4. Студент обновляет свой выбор курсов, удаляя или добавляя конкретные курсы из/в учебный план.
5. Система обновляет учебный план в соответствии с пожеланиями студента. Для каждого зафиксированного курса, удалённого из плана, система удаляет студента из списка студентов, записавшихся на курс. Каждый добавленный курс система помечает как не зафиксированный.
6. Система сообщает, что обновление учебного плана завершено.
5В. Удалить учебный план
1. Система подтверждает наличие у студента учебного плана на текущий семестр и выводит его.
2. Система запрашивает у студента подтверждения удаления учебного плана.
3. Студент подтверждает удаление.
4. Система удаляет учебный план. Для каждого зафиксированного курса из удаляемого учебного плана, система удаляет студента из списка студентов, записавшихся на курс.
5. Система сообщает, что удаление учебного плана завершено.
5Г. Утвердить учебный план
1. Система подтверждает наличие у студента учебного плана на текущий семестр.
2. Для каждого не зафиксированного курса в учебном плане выполняется:
2.1. Система подтверждает выполнение студентом предварительных требований (прохождение необходимых курсов), и подтверждает, что курс открыт для регистрации, и отсутствуют конфликты (в учебном плане не должно быть зафиксированного курса, читаемого в тот же день и на той же паре, что и проверяемый курс).
2.2. Система добавляет студента в список записавшихся на курс.
2.3. Система помечает курс в учебном плане как зафиксированный.
2.4. Система помечает курс как закрытый, если в списке студентов содержится 10 записей.
3. Система сообщает студенту результаты утверждения учебного плана.

Альтернативные потоки
2А, 5А.1А, 5Б.1А, 5В.1А, 5Г.1А. Обнаружена ошибка
1. Система обнаруживает одну из возможных ошибок: регистрация на курсы в текущем семестре закрыта; у студента уже заведён учебный план на текущий семестр, а он желает создать ещё один учебный план; у студента отсутствует учебный план на текущий семестр, а он желает обновить/удалить/утвердить учебный план.
2. Система выдаёт студенту сообщение об ошибке с указанием типа ошибки.
3. Вариант использования завершается неуспешно.
5Г.2.1А. Не выполнены предварительные требования, курс заполнен, или в учебном плане есть конфликты
1. Система обнаруживает, что студент не выполнил необходимые предварительные требования, или выбранный им конкретный курс заполнен, или в учебном плане есть конфликты.
2. Система выдаёт сообщение об ошибке.
3. Система переходит к следующему не зафиксированному курсу и продолжает выполнение потока «Утвердить учебный план» (цикл на шаге 5Г.2).
5В.3А. Удаление отменено
1. Студент отменяет удаление учебного плана.
2. Система сообщает студенту, что учебный план не будет удалён.
3. Вариант использования завершается неуспешно.

Предусловия: Студент должен войти в систему.

Гарантии успеха: Система создаст, обновит, удалит или утвердит учебный план студента в соответствии с выбором пользователя.

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


      Вариант использования «Закрыть регистрацию»:

Краткое описание: Описывается закрытие регистрации регистратором. Конкретные курсы, на которые не записалось достаточного количества студентов (менее четырёх), отменяются. В расчётную систему передаётся информация об индивидуальном учебном плане каждого студента, чтобы студентам были выписаны счета за обучения и они могли бы внести оплату за семестр.

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

Основной поток событий:
1. Регистратор запрашивает закрытие регистрации.
2. Система подтверждает возможность закрыть регистрацию и фиксирует, что регистрация закрыта.
3. Для каждого предлагаемого курса, который открыт для регистрации, выполняется:
3.1. Система подтверждает, что курс взялся провести какой-либо профессор, и что на курс записалось не менее 4х студентов.
3.2. Для каждого учебного плана студента, в котором курс помечен основным и не зафиксированным, выполняется подчинённый поток «Зафиксировать курс в учебном плане».
4. Для каждого учебного плана студента система проверяет наличие в нём 4х зафиксированных курсов; если их недостаточно, система дополняет план альтернативными курсами по схеме, описанной в шаге 3 основного потока.
5. Для каждого открытого предлагаемого курса выполняется:
5.1. Система подтверждает, что в списке не менее 4х студентов.
5.2. Система помечает курс как закрытый.
6. Выполняется подчинённый поток «Передать данные об учебных планах».

Подчинённые потоки::
3.2. Зафиксировать курс в учебном плане
1. Система подтверждает, что курс открыт для регистрации.
2. Система добавляет студента в список записавшихся на курс.
3. Система помечает курс в учебном плане как зафиксированный.
4. Система помечает курс как закрытый, если в списке студентов содержится 10 записей.
6. Передать данные об учебных планах студентов
1. Система запрашивает связь с расчётной системой.
2. Расчётная система подтверждает готовность к приёму данных.
3. Для каждого учебного плана студента выполняется:
3.1. Система передаёт в расчётную систему данные об учебном плане студента.
3.2. Расчётная система принимает данные об учебном плане студента и присылает подтверждение удачного приёма данных.

Альтернативные потоки:
2А. Регистрация не может быть прекращена
1. Система обнаруживает, что процесс регистрации нельзя прекратить немедленно.
2. Система выдаёт сообщение регистратору о невозможности закрытия регистрации.
3. Вариант использования завершается неуспешно.
3.1А. Курс никто не ведёт
1. Система обнаруживает, что ни один профессор не выбрал курс для чтения.
2. Система помечает курс как отменённый.
3. Система исключает данный курс из каждого содержащего его учебного плана и удаляет студентов из списка записавшихся на курс.
3. Система выбирает следующий курс и продолжает выполнение шага 3 основного потока.
3.1Б. На курс записалось мало студентов
1. Система обнаруживает, что на курс записалось менее 4х студентов.
2. Система выбирает следующий курс и продолжает выполнение шага 3 основного потока.
3.2.1А Регистрация на курс закрыта
1. Система обнаруживает, что курс помечен как закрытый. 2. Выполнение подчинённого потока «Зафиксировать курс в учебном плане» завершается.
5.1А. Менее 4х студентов на курсе
1. Пока в списке меньше 4х студентов и есть учебные планы, содержащие этот курс, в которых меньше 4 зафиксированных курсов, выполняется подчинённый поток «Зафиксировать курс в учебном плане»
2. Система подтверждает, что на курсе не менее 4х студентов.
3. Продолжается выполнение основного потока с шага 5.2.
5.1А.2А. Невозможно добавить студентов на курс
1. Система обнаруживает, менее 4х студентов.
2. Система помечает курс как отменённый.
3. Система вычёркивает курс из всех учебных планов и переходит к следующему открытому курсу.
4. Продолжается выполнение основного потока с шага 5.
6.2А. Расчётная система недоступна
1. Система ожидает некоторое установленное время.
2. Выполнение передаётся на шаг 1 подчинённого потока «Передать данные об учебных планах».

Предусловия: Регистратор должен войти в систему.

Гарантии успеха: Регистрация закрыта, данные об учебных планах студентов переданы в расчётную систему.

Минимальные гарантии: При невозможности закрыть регистрацию система выдаст предупреждение об этом.


      Для остальных вариантов использования мы составим только краткие описания. В рамках работ по определению требований в ходе одной итерации допускается составлять полные описания лишь для нескольких приоритетных вариантов использования. Менее приоритетные варианты использования описываются кратко. Их полные описания могут быть составлены на последующих итерациях.

      Вариант использования «Выбрать читаемые курсы»:

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

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

      Вариант использования «Поставить оценки»:

Краткое описание: Описывается ввод профессором оценок студентов по прочитанному им курсу. Профессор запрашивает ввод оценок. Система выводит перечень курсов, которые выбраны профессором для чтения в текущем семестре. Профессор выбирает курс для ввода оценок. Система выводит список студентов, слушающих курс. Профессор вводит оценки. Система подтверждает, что оценки указаны для всех студентов и сохраняет введённые оценки.

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

      Вариант использования «Посмотреть табель»:

Краткое описание: Описывается просмотр студентом своих оценок по курсам, изучаемым в текущем семестре. Студент запрашивает вывод табеля. Система по каждому курсу, изучаемому студентом, выводит оценки, которые ранее ввели профессора.

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

      Вариант использования «Открыть регистрацию»:

Краткое описание: Описывается запуск регистратором процесса регистрации на курсы в текущем семестре. Регистратор запрашивает открытие регистрации. Система подтверждает, что регистрация пока не была открыта, и открывает регистрацию.

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

      Вариант использования «CRUD данных о профессорах»:

Краткое описание: Описывается работа регистратора с данными о профессорах. Регистратор запрашивает работу с данными о профессорах. Система выводит перечень доступных действий и предлагает выбрать одно из них. Регистратор выбирает нужное действие: ввести данные о новом профессоре; обновить данные о профессоре; удалить данные о профессоре; просмотреть данные о профессоре. По выбору регистратора система осуществляет нужное действие с данными о профессоре.

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

      Вариант использования «CRUD данных о студентах»:

Краткое описание: Описывается работа регистратора с данными о студентах. Регистратор запрашивает работу с данными о студентах. Система выводит перечень доступных действий и предлагает выбрать одно из них. Регистратор выбирает нужное действие: ввести данные о новом студенте; обновить данные о студенте; удалить данные о студенте; просмотреть данные о студенте. По выбору регистратора система осуществляет нужное действие с данными о студенте.

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

      Вариант использования «CRUD данных о курсах и дисциплинах»:

Краткое описание: Описывается работа регистратора с данными о курсах и дисциплинах. Регистратор запрашивает работу с данными о курсах и дисциплинах. Система выводит перечень доступных действий и предлагает выбрать одно из них. Регистратор выбирает нужное действие: ввести данные о новой дисциплине; обновить данные о дисциплине; удалить данные о дисциплине; просмотреть данные о дисциплине; просмотреть список курсов в текущем семестре; создать курс по дисциплине в текущем семестре; удалить курс по дисциплине в текущем семестре. По выбору регистратора система осуществляет нужное действие с данными о дисциплине или курсе.

Область действия: система как «чёрный ящик».

Уровень: цель пользователя («уровень моря»).

Упражнение 3.4. Создание UML-диаграмм деятельности

(общее для всех вариантов)


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

      1. В Model Explorer вызываем контекстное меню варианта использования «Войти в систему» и выбираем Sub Diagrams -> New Diagram.... В открывшемся окне указываем тип создаваемой диаграммы: Activity diagram. Как заготовку выбираем пустую диаграмму -- Blank. Даём имя диаграмме -- Войти в систему.

      2. На появившейся в редакторе диаграмме создаём два раздела (Vertical Swimlane) -- Пользователь, Система регистрации на курсы -- каждый из которых обозначает область ответственности. Связываем каждый раздел с элементом модели, который он представляет, в окне спецификации на вкладке General в поле Represents (первый -- с действующим лицом Пользователь, второй с системой). Работы, соответствующие узлам действия, которые будут расположены в области ответственности пользователя, будут выполняться пользователем, остальные -- системой. Заметим, что если бы с вариантом использования были бы связаны два действующих лица, на диаграмме следовало бы создать три раздела (два для действующих лиц и один для системы). Входной узел (Initial Node) помещаем в раздел Пользователь, т. к. это действующее лицо основное для данного варианта использования.

      3. Согласно описаниям потоков событий варианта использования создаём узлы действий (Action): Запустить приложение, Запросить логин и пароль; Ввести логин и пароль; Проверить логин и пароль; Сообщить об ошибке и завершить работу приложения; Вывести меню. Узлы действий размещаем по разделам в соответствии с тем, кто выполняет действия. Не следует вместо узлов действия (Action) создавать деятельности (Activity)! В UML деятельность создаётся как объемлющая рамка всей диаграммы деятельности, включающая все другие её узлы и дуги.

      4. Добавляем узел логического ветвления (Decision Node). Соединяем узлы рёбрами потоков управления (Control Flow). Задать нетривиальные сторожевые условия можно, открыв спецификацию потока, на вкладке General в поле Guard (другой вариант: контекстное меню потока -> Guard...). Не следует указывать сторожевые условия в названиях потоков управления! Не следует вместо узла логического ветвления (Decision Node) создавать узел логического объединения (Merge Node)!

      5. Добавляем два узла завершения деятельности (Activity Final Node) с именами, указывающими на успешное и безуспешное завершение варианта использования. Вид получившейся диаграммы представлен на рис. 3.4.1.


Рис. 3.4.1. UML-диаграмма деятельности для варианта использования «Войти в систему»

Рис. 3.4.1. UML-диаграмма деятельности для варианта использования «Войти в систему» (для всех вариантов)

      Диаграмма деятельности пути передачи управления между узлами. Изначально курсор управления порождается во входном узле. Оттуда он передаётся по ребру на вход узла действия (запустить приложение). Узел действия ждёт, когда курсоры управления придут на все входящие ребра, после чего запускается действие, а по окончании действия курсоры управления подаются на все исходящие из узла действия ребра. Когда курсор попадает в узел логического ветвления, проверяются сторожевые условия на всех исходящих рёбрах этого узла. Исходящих рёбер может быть два и более. По одному из рёбер, на котором сторожевое условие истинно, курсор управления передаётся дальше. Если таких рёбер (с истинными сторожевыми условиями) несколько, то случайным образом выбирается одно. Если все сторожевые условия ложны, то курсор не может быть передан дальше. Поток управления заблокирован, а диаграмма нарушает правила стандарта языка. Во избежание ошибок следует внимательно формулировать сторожевые условия. Рекомендуется делать их взаимоисключающими и покрывающими все возможные случаи. Часто используется условие [else], способствующее выполнению этих требований.

      При попадании курсора управления в узел завершения деятельности (любой, по любому входящему в него потоку) вся деятельность прекращается. Уничтожаются все курсоры управления на всех рёбрах диаграммы. В случаях, когда требуется остановить один поток, оставив другие активными, применяется узел завершения потока (Flow Final Node), изображаемый кружком с крестиком.

      Самостоятельно постройте диаграмму для варианта использования «Зарегистрироваться на курсы». Обратите внимание, что подчинённый поток может быть представлен на диаграмме в виде одного узла (см. узлы «Создать учебный план», «Обновить учебный план», «Удалить учебный план», «Утвердить учебный план»). Тип этих узлов -- узел вызова деятельности (Call Behavior Action). С каждым из них связана деятельность, соответствующая выполнению подчинённого потока варианта использования, которая может быть смоделирована на отдельной диаграмме деятельности. При создании такой диаграммы следует сначала создать внутри варианта использования четыре деятельности (Activity): Создать учебный план, Обновить учебный план, Удалить учебный план, Утвердить учебный план. Затем разместите на диаграмме деятельности четыре узла действия (Action). В окне спецификации каждого созданного узла на вкладке General в поле Type укажите тип узла: Call Behavior Action, после чего нажмите на кнопку с многоточием рядом с появившимся полем Behavior. В открывшемся окне следует выбрать подходящую деятельность. Обратите внимание, что если деятельности созданы в корне проекта, то следует перетащить их внутрь варианта использования «Зарегистрироваться на курсы» в Model Explorer.


      Может оказаться, что какая-то диаграмма создана Вами в корне проекта, а не внутри элемента проекта. Перетащить диаграмму в нужное место Model Explorer не даёт. Тем не менее, переместить диаграмму из корня проекта можно. Откройте спецификацию диаграммы. На закладке General второе сверху поле Parent model: <No parent model>. Нажмите кнопку "..." и укажите нужный элемент проекта как Parent model для диаграммы.

Рис. 3.4.2. UML-диаграмма деятельности варианта использования «Зарегистрироваться на курсы»

Рис. 3.4.2. UML-диаграмма деятельности «Зарегистрироваться на курсы» (для всех вариантов)

      Моделирование требований следовало бы продолжить дальше, описав все варианты использования и построив для них диаграммы деятельности. Однако, не имеет смысла сразу описывать все требования. Работа осуществляется последовательными итерациями, в ходе которых составляются описания отдельных вариантов использования в порядке их важности. Когда описания важных вариантов использования составлены, выполняются работы по анализу и проектированию частей системы, реализующих их. Use case писатели приступают к работе над менее приоритетными вариантами использования во время последующих итераций, или занимаются ими на той же итерации, если они мало загружены во время анализа и проектирования. Следует быть готовыми к пересмотру требований в ходе проекта. Изменчивость требований обусловлена тем, что заказчики и будущие пользователи системы не могут сразу точно указать свои пожелания, и тем, что по ходу проекта разработчики лучше узнают предметную область и контекст системы. Из-за изменения требований переделываются описания вариантом использования, исправляются диаграммы деятельности.

      Перейдём к процессу анализа и проектирования, в ходе которого осуществляется эскизное и проектное моделирование системы.

4. Эскизное моделирование системы


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

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

      Архитектурный анализ выполняется архитектором и включает в себя следующие технологические операции:

  1. Утверждение общих соглашений моделирования и документирования системы.

  2. Формирование набора ключевых абстракций предметной области.

      Соглашения моделирования фиксируются в документе «Руководящие указания по проектированию» (Design Guidelines). Они определяют: перечень используемых диаграмм и элементов модели; правила применения диаграмм; соглашения по именованию элементов модели; организацию модели (пакеты).

      Будем придерживаться следующих соглашений:

  1. В эскизной и проектной модели используются английские имена (поскольку на основе этих моделей могут быть получены заготовки кода, которые при использовании русских имён будут бесполезны).

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

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

  4. Имена атрибутов, полюсов ассоциаций и операций должны начинаться со строчной буквы.

  5. Литералы перечислимых типов и константы записываются заглавными буквами.

  6. Составные имена должны быть сплошными, без подчёркиваний, каждое отдельное слово (кроме, может быть, первого) должно начинаться с заглавной буквы.

  7. Модель анализа (Analysis Model) представляет собой пакет внутри логического архитектурного представления (Logical View). Внутри модели анализа помещается пакет Use Case Realizations, содержащий в себе все эскизные реализации вариантов использования. Также внутри модели создаётся диаграмма классов -- ключевых абстракций -- Key Abstractions.

  8. Для каждого варианта использования должна быть создана кооперация (Collaboration), внутри которой будут размещены элементы модели, относящиеся к реализации варианта использования. Каждая такая кооперация содержит диаграммы взаимодействия, описывающие потоки событий варианта использования (базовый, альтернативные и подчинённые потоки). Также кооперация содержит диаграмму классов VOPC (View Of Participating Classes), на которую помещаются классы, экземпляры которых участвуют в реализации этого варианта использования, и связи между ними.

Упражнение 4.1. Создание структуры логического архитектурного представления в соответствии с соглашениями моделирования

(общее для всех вариантов)


Рис. 4.1.1. Структура модели анализа

Рис. 4.1.1. Структура модели анализа (для всех вариантов)

      1. В модели Analysis Model (модель анализа) создадим пакет Use Case Realizations. Для этого в Model Explorer вызовем контекстное меню меню пакета Analysis Model, Model Element -> Package (или Model Element -> New Model Element -> Model element type: Package.

      2. В пакет Use Case Realizations добавим три кооперации (Collaboration) Login, RegisterForCourses и CloseRegistration (контекстное меню пакета -> Model Element -> New Model Element -> Model element type: Collaboration). Назначим каждой созданной кооперации стереотип «usecase realization». Каждая кооперация описывает сценарии одного из вариантов использования: Login -- Войти в систему, RegisterForCourses -- Зарегистрироваться на курсы, CloseRegistration -- Закрыть регистрацию. В пакете Use Case Realizations создадим диаграмму составной структуры (Composite Structure Diagram), на которой покажем связи между вариантами использования и их реализациями. Перетащим кооперации и варианты использования из Model Explorer на диаграмму. Соединим связями реализации (Realization, этот тип связи можно найти в палитре, если открыть выпадающий список у связи Generalization) кооперации и варианты использования, которые они реализуют. Важно, чтобы стрелки у связей показывали от коопераций в сторону реализуемых вариантов использования. Получившаяся диаграмма примет вид, показанный на рис. 4.1.2.

      3. Внутри каждой кооперации создадим диаграмму последовательности Basic Flow (Login Basic Flow, RegisterForCourses Basic Flow, CloseRegistration Basic Flow) и диаграмму классов VOPC (VOPC Login, VOPC RegisterForCourses, VOPC CloseRegistration). Воспользуемся контекстным меню кооперации -> Sub Diagrams -> New Diagram. Диаграммы последовательности (Sequence diagram) с именами, заканчивающимися на Basic flow, служат для моделирования реализации основных и альтернативных сценариев (для вариантов использования CRUD и других сложных вариантов использования создаются дополнительные диаграммы последовательности, на которых моделируются подчинённые сценарии). VOPC это сокращение View Of Participating Classes. Назначение диаграмм классов (Class diagram) с именами, начинающимися с VOPC -- отображение всех классов, экземпляры которых участвуют в реализации варианта использования, и связей между этими классами.

      4. Если в заготовке проекта нет диаграммы классов Key Abstractions в корне пакета Analysis Model, то создадим её. Контекстное меню пакета Analysis Model -> Sub Diagrams -> New Diagram -> Class Diagram.

      5. Дополнительно в кооперацию RegisterForCourses добавим пять диаграмм последовательности, моделирующих подчинённые потоки: CreateSchedule Subflow, DisplayCourseOfferings Subflow, UpdateSchedule Subflow, DeleteSchedule Subflow, SubmitSchedule Subflow. Контекстное меню пакета Analysis Model -> Sub Diagrams -> New Diagram -> Sequence Diagram. Вариант использования «Зарегистрироваться на курсы» составлен как CRUD. Моделировать все его сценарии на одной диаграмме последовательности неудобно, поэтому отдельно моделируют основной сценарий, отдельно подчинённые потоки.

      Структура модели в Model Explorer должна соответствовать рис. 4.1.1.


Рис. 4.1.2. UML-диаграмма составной структуры Use Case Realizations

Рис. 4.1.2. UML-диаграмма составной структуры Use Case Realizations (для всех вариантов)

      Ключевые абстракции -- основные понятия предметной области -- архитектор выделяет, анализируя требования и пользуясь глоссарием предметной области и моделью бизнес-анализа, если таковая была создана. Каждый термин из глоссария является кандидатом для того, чтобы на его основе был создан класс ключевой абстракции (или в несколько классов, если структура данных, связанная с ним, слишком сложна для представления одним классом). Некоторые термины могут быть источником для атрибутов классов, другие -- для перечислимых типов и их литералов. В системе регистрации можно выделить следующие ключевые абстракции: Student (данные об учащемся), Schedule (учебный план студента, которых у него может быть несколько разных в разных семестрах), CourseOffering (данные о курсе, предлагаемом для изучения в некотором семестре), Professor (данные о лекторе), Course (данные об учебной дисциплине из учебного плана), User (данные об учётной записи пользователя). Ассоциации между классами-ключевыми абстракциями описывают типичные соединения между их экземплярами. Мощности у полюсов ассоциаций указывают ограничения на количество соединений у одного экземпляра. Обратите внимание на рефлексивную ассоциацию (см. рис. 4.1.3) класса Course, используемую для указания на дисциплины, которые следует изучить до начала изучения какой-либо дисциплины. В обратную сторону связь трактуется как список дисциплин, которые можно начать изучать после сдачи курса по какой-либо дисциплине. Полюсам рефлексивных ассоциаций следует давать имена, чтобы различать их и осуществлять навигацию вдоль ассоциации. Также поступают при наличии двух ассоциаций между одной парой классов. К ключевым абстракциям также относят перечислимые типы из предметной области DayOfWeek (день недели), UserType (тип учётной записи пользователя).


Рис. 4.1.3. UML-диаграмма классов Key Abstractions

Рис. 4.1.3. UML-диаграмма классов Key Abstractions (для всех вариантов)

      Предварительно настроим среду для более удобной работы. Меню Tools -> Project Options -> Diagramming (вариант: Window -> Project Options -> Diagramming). На вкладке Association отменим отображение уникальности (Show multiplicity constraints -- Unique). По умолчанию любая пара объектов, связывается не более чем одним соединением, являющимся экземпляром одной ассоциации. Если необходимо допустить повторные соединения, уникальность соединения следует отменить. Там же укажем необходимость явно выводить мощность полюса, равную 1 (снимаем флажок Suppress implied "1" multiplicity). Перейдите к вкладке Class. Выберите вложенную вкладку Presentation. Снимаем флажок отображения классов в виде пиктограмм стереотипов (Display as Robustness Analysis icon). Сохраняем настройки, закрываем окно настроек проекта. Снятие флажка Suppress implied "1" multiplicity может потребоваться дополнительно на каждой диаграмме классов. Вызываем контекстное меню на поле диаграммы классов, нужный флажок спрятан в Presentation Options. Также в Presentation Options диаграммы Key Abstractions найдём и установим флажок Attribute Display Options -> Show Property Modifiers.

      1. Откроем диаграмму Key Abstractions. Выберем в палитре инструмент Class. Добавим классы Course, CourseOffering, Professor, Schedule, Student, User.

      2. Добавим перечислимый тип DayOfWeek, используя Enumeration в выпадающем списке элемента палитры Class. Внутри DayOfWeek расположим значения перечислимого типа (enumeration literal): SU, ..., SA. Аналогично поступим с перечислимым типом UserType.

      3. Выберем в палитре инструмент Association. Проведём ассоциации между классами. Укажем мощности у полюсов -- концов ассоциаций (контекстное меню полюса Multiplicity). Укажем, что связь между классами Student и Schedule -- композиция (контекстное меню полюса, Aggregation kind -> Composited). Дадим имена полюсам (контекстное меню полюса Edit Role Name...). Чтобы имена полюсов отобразились на диаграмме установите флажок через контекстное меню ассоциации -> Presentation Options -> Show From Role Name (и/или Show To Role Name).

      4. Добавим атрибуты (Attribute) классов: классу Student -- address: string, name: string, phones: string[0..2], id: long; классу Schedule -- semester: byte; классу CourseOffering -- number:long, day: DayOfWeek; pair: byte, semester: byte; классу Professor -- name: string, academicDegree, phones: string[0..2]; классу Course -- code:string, description: string, duration:byte; классу User -- login:string, passwordHash:long[2]; type:UserType. У атрибутов Course::code, User::login, Professor::name, Student::id, входящих в состав идентификаторов, надо открыть спецификацию (контекстное меню атрибута Open Specification...) и установить флажок ID на вкладке General.

      5. Проведём зависимость (Dependency) от класса CourseOffering к перечислимому типу DayOfWeek. Эта связь указывает, что изменения в описании перечислимого типа могут отразиться на описании класса CourseOffering, так как один из его атрибутов имеет этот перечислимый тип. Аналогично свяжем User с UserType.

      6. Добавим всем классам-сущностям стереотип «entity». Для этого выделим нужный класс в Model Explorer, вызовем контекстное меню класса, Stereotype -> «entity». Если стереотипа «entity» в списке контекстного меню нет, то выберем Edit Stereotypes..., найдём нужный стереотип в левом списке формы Class Specification, выделим его и добавим классу кнопкой > (Add Selected). В итоге диаграмма Key Abstractions должна соответствовать рисунку 4.1.3.

      Мы не указали типы всех атрибутов, не описали операции, не уточнили направления всех связей, и это нормально. Дело в том, что нет необходимости сразу указывать все детали диаграммы ключевых абстракций. Важно определить начальный набор классов, установить между ними связи, вытекающие из свойств предметной области, указать основные данные, хранимые в объектах. В ходе проекта возможности уточнить набор ключевых абстракций ещё представятся.

      Мы готовы перейти к выполнению анализа вариантов использования, т. е. к составлению эскизных моделей их реализаций. В технологии Unified Process этим занимаются разработчиками, выполняя для каждого выбранного варианта использования следующие технологические операции:

  1. Составление набора классов, экземпляры которых участвуют в реализациях потоков событий варианта использования (так называемых, классов анализа).

  2. Определение обязанностей классов анализа, уточнение их атрибутов и связей.

  3. Унификацию классов анализа, в ходе которой делается попытка упростить модель, исключая лишние классы, объединяя классы с общими обязанностями в один.

      Классы анализа реализуют функциональные требования к системе и определяют типы для объектов, из которых будет состоять эскизная модель системы. Совокупность классов анализа представляет собой начальную концептуальную модель системы. Эта модель проста и позволяет сосредоточиться на реализации функциональных требований, не отвлекаясь на детали реализации, обеспечение эффективности и надёжности. Для решения этих вопросов впоследствии модель анализа будет трансформирована в проектную модель. В ходе анализа вариантов использования для реализации поведения, описанного их сценариями, выявляются классы трёх типов:

  • граничные классы (boundary classes), являющиеся посредниками при взаимодействии системы с действующими лицами и с аппаратной базой;

  • классы-сущности (entity classes), отвечающие за хранение данных;

  • управляющие классы (control classes), реализующие бизнес-логику и обеспечивающие координацию поведения объектов в системе.

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

      Правило выделения классов-сущностей: классы-сущности -- это, обычно, классы ключевых абстракций системы. Если в ходе сценария производятся манипуляции данными, представленными классом ключевой абстракции, если эти данные вводятся / выводятся / изменяются / удаляются и т. п., то класс ключевой абстракции должен быть помещён ан VOPC диаграмму варианта использования, а его экземпляры должны присутствовать на диаграмме последовательности, моделирующей сценарий.

      Правило выделения управляющих классов: обычно для каждого варианта использования создаётся ответственный за его реализацию класс управления. Если моделируется встроенная система (вроде, терминала, турникета, валидатора и т. п.), то в такой системе заводят единый управляющий класс-контроллер, и лишь при необходимости -- вспомогательные контроллеры. Например, главный контроллер ведёт общую работу турникета, а при осуществлении прохода пассажира используется вспомогательный контроллер, который берёт на себя только прохож, а затем передаёт управление главному контроллеру.

      Выполним анализ варианта использования «Войти в систему».

Упражнение 4.2. Анализ варианта использования «Войти в систему»

(общее для всех вариантов)


      Итак, выполним анализ варианта использования «Войти в систему». Сначала решим, экземпляры каких классов будут задействованы в реализации этого варианта использования. Согласно диаграмме вариантов использования имеется одно действующее лицо (Пользователь), связанное с нашим вариантом использования. Создадим граничный класс LoginForm -- экранную форму, отвечающую за взаимодействие с Пользователем при входе в систему. В Model Explorer вызовем контекстное меню пакета Analysis Model, Model Element -> Class. Дадим имя классу -- LoginForm. Тем же образом создадим управляющий класс LoginController, отвечающий за логику входа в систему, а также управляющий класс DataAccess, отвечающий за доступ к данным об устойчивых объектах в базе данных нашей системы. Из описания варианта использования следует, что в потоке событий будет задействован экземпляр класса User -- учётная запись пользователя. Поскольку в конце система может открыть главное меню, то потребуется ещё один класс -- MainMenuForm. Открываем в редакторе диаграмму классов VOPC Login. Перетаскиваем на неё вышеупомянутые классы из Model Explorer.

      Назначим классам стереотипы. Выделим в Model Explorer класс LoginController. С помощью контекстного меню добавим стереотип «control». Также поступим с классом DataAccess. Аналогично добавим стереотип «boundary» граничным классам LoginForm и MainMenuForm. У класса-сущности User должен быть стереотип «entity».

      Классы, пока отсутствующие в модели, лучше не создавать на диаграмме VOPC, а вместо этого работать в Model Explorer с помощью контекстного меню пакета Analysis Model, так чтобы все классы анализа после их создания оказались в корне этого пакета. Если бы мы создали классы на диаграмме VOPC, то нам следовало бы найти их в Model Explorer (внутри кооперации) и переместить (перетащить) в корень пакета Analysis Model. Начальный эскиз диаграммы классов VOPC Login приведён на рисунке 4.2.1. В дальнейшем нам потребуется доработать этот эскиз, добавив ассоциации между классами.


Рис. 4.2.1. Начальный эскиз UML-диаграммы классов VOPC Login

Рис. 4.2.1. Начальный эскиз UML-диаграммы классов VOPC Login (для всех вариантов) (работа над диаграммой не завершена!)

      Продолжим анализ варианта использования «Войти в систему». Распределение поведения, предусматриваемого вариантом использования, между классами анализа реализуется при построении диаграмм взаимодействия. На основе описания варианта использования для потоков событий (основного, альтернативных, подчинённых) строятся диаграммы взаимодействия -- диаграммы последовательности или коммуникативные диаграммы. Перейдём к моделированию потоков событий варианта использования «Войти в систему» с помощью диаграмм последовательности.

      Предварительно настроим среду для более удобной работы. Меню Window -> Project Options -> Diagramming (вариант: Tools -> Project Options -> Diagraming). На вкладке Interaction установите настройку Mark target lifeline stopped ... -- Yes и оставим помеченными пункты: Show sequence number in Communication Diagram; Show message operation signature...; Show stereotype of message... . У остальных пунктов отметку уберём.

      Откроем внутри кооперации Login диаграмму последовательности Login Basic Flow (основной поток варианта использования «Войти в систему»). Добавим на диаграмму 6 линий жизни (Lifeline): линию жизни действующего лица Пользователь; lform -- экземпляр формы LoginForm; menu -- экземпляр формы MainMenuForm; lctrl -- экземпляр контроллера ВИ LoginController; dao -- экземпляр класса DataAccess; curUser -- экземпляр класса User. Проще всего добавлять линии жизни, перенося действующее лицо и классы из Model Explorer на диаграмму. При переносе класса укажем, что добавляется линия жизни. Добавим линиям жизни стереотипы (те же, что у классов, экземплярами которых являются объекты). Заметим, что линию жизни объекта граничного класса следует расположить рядом с линией жизни, представляющей то действующее лицо, за общение с которыми отвечает граничный класс, а линии объектов-контроллеров следует расположить в середине диаграммы. В правой части диаграммы располагают линии объектов-сущностей. Как будет видно дальше, если справа на диаграмме находятся линии жизни второстепенных действующих лиц, то рядом с ними находятся линии жизни экземпляров граничных классов, отвечающих за взаимодействие с этими действующими лицами.

       Выберем на палитре синхронное сообщение (Call Message) и проведём его от линии жизни действующего лица Пользователь к линии жизни lform:LoginForm. Оставим сообщение без имени. Создадим вызываемую операцию (контекстное меню сообщения -> Select Operation -> Create Operation -> "login"). Добавим второе синхронное сообщение от линии жизни lform:LoginForm к линии жизни lctrl:LoginController -- вызов операции login (её тоже надо будет создать), которым форма передаёт введённые в неё данные контроллеру ВИ. Добавим третье синхронное сообщение от линии жизни lctrl:LoginController к линии жизни dao:DataAccess -- вызов операции getUserByLogin, которым контроллер ВИ запрашивает у объекта доступа к БД учётную запись пользователя.

       Каждое сообщение-вызов экземпляру класса должно быть связано с операцией этого класса. Сообщения, получаемые экземплярами действующих лиц, связывать с операциями не следует. Всякий раз, добавляя сообщение, вызывающее новую операцию будем добавлять операцию в модель (в класс). Если вызывается ранее созданная операция, то снова добавлять её в тот же класс не следует. Вместо этого следует выбрать её из списка операций класса (контекстное меню сообщения -> Select Operation -> Select Operation...).

      Итак, далее есть два варианта развития событий. Если логин указан верно, то объект доступа к данным подкачивает учётную запись из БД и создаёт по ней экземпляр класса User. Создадим комбинированный фрагмент взаимодействия (Loop Combined Fragment). Заменим оператор loop на opt в созданном фрагменте (контекстное меню фрагмента, Operator type -> opt). Зададим сторожевое условие операнда комбинированного фрагмента (контекстное меню фрагмента -> Operand -> Manage Operands). Нарисуем в операнде взаимодействия создающее сообщение (Create Message) от dao:DataAccess к curUser:User. При этом начало линии жизни curUser:User сдвинется вниз. Ссылку на объект-учётную запись объект доступа к БД вернёт контроллеру ВИ (нарисуем сообщение-возврат к объекту-контроллеру). Тот в свою очередь поручает учётной записи проверить пароль, после чего при успехе открывает главное меню, порождая экземпляр menu:MainMenuForm. Меню при открытии получает ссылку на текущего пользователя. Оно запрашивает тип пользователя, для того, чтобы выводить разные списки пунктов пользователям разных типов.

      Добавим на диаграмму сообщение-вызов checkPassword() от lctrl:LoginController к curUser:User, сообщение-возврат, а также комбинированный фрагмент взаимодействия (Alt Combined Fragment). Введём нужные сторожевые условия, выделив фрагмент на диаграмме и вызвав контекстное меню -> Operand -> Manage Operands. Нарисуем в первом операнде взаимодействия alt-фрагмента создающее сообщение (Create Message) open(curUser) от lctrl:LoginController к menu:MainMenuForm. Начало этой линии жизни также сдвинется вниз. Добавим сообщение-вызов getType() от menu:MainMenuForm к curUser:User. Добавим во второй операнд alt-фрагмента сообщением displayError(). Ниже alt-фрагмента добавим сообщение close и укажем его тип -- Destroy -- (контекстное меню -> Type -> Destroy). UML-диаграмма примет вид, схожий с рисунком 4.2.2. Не забудьте создать операции LoginForm::login(), LoginForm::displayError(), LoginForm::close(), LoginController::login(), DataAccess::getUserByLogin(l:string):User, User::checkPassword(pswrd:string):boolean, User::getType():UserType и связать их с сообщениями.


Рис. 4.2.2. UML-диаграмма последовательности Login Basic Flow

Рис. 4.2.2. UML-диаграмма последовательности Login Basic Flow (для всех вариантов)

      Продолжим анализ варианта использования «Войти в систему». Откроем диаграмму классов VOPC Login. Добавим ассоциации, необходимые для того, чтобы взаимодействие, описанное диаграммой последовательности Login Basic Flow, было осуществимо. Расставим мощности и имена ролей на полюсах ассоциаций. Укажем направления навигации (на противоположном полюсе с помощью контекстного меню укажите Navigable Unspecified). Итоговый вид UML-диаграммы приведён на рисунке 4.2.3. Заметим, что в реализации участвуют два граничных класса, два класса-контроллера, и класс-сущность, т. е. классы всех трёх разновидностей: и отвечающие за внешнее взаимодействие, и реализующие логику работы, и отвечающие за представление данных. Также заметим, что итоговая диаграмма VOPC Login является связанным графом, иначе бы экземпляры классов не смогли бы работать совместно.


Рис. 4.2.3. Итоговая версия UML-диаграммы классов VOPC Login в Analysis Model

Рис. 4.2.3. Итоговая версия UML-диаграммы классов VOPC Login в Analysis Model (для всех вариантов)

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


Упражнение 4.3. Анализ варианта использования «Зарегистрироваться на курсы»

(содержит часть общую для всех вариантов и специальные части для вариантов 1, 2, 3, 4)


      Определим классы анализа, которые понадобятся для реализации варианта использования. Согласно диаграмме вариантов использования имеется одно действующее лицо (Студент), связанное с нашим вариантом использования. Создадим граничный класс RegistrationForm -- экранную форму, отвечающую за взаимодействие со Студентом в рамках его работы со своим учебным планом. В Model Explorer вызовем контекстное меню пакета Analysis Model, Model Element -> Class. Дадим имя классу -- RegistrationForm. Второй нужный нам граничный класс -- MainMenuForm -- мы создали ранее. Создадим управляющий класс RegistrationController, отвечающий за реализацию бизнес-логики (действия аналогичны). Второй нужный нам управляющий класс -- DataAccess, отвечающий за сохранение данных об устойчивых объектах в базе данных нашей системы, -- уже создан нами. Из описания варианта использования следует, что в потоках событий будут задействованы экземпляры классов Student, CourseOffering, Schedule. Открываем в редакторе диаграмму классов VOPC RegisterForCourses. Перетаскиваем на неё вышеупомянутые классы из Model Explorer. Убедимся, что на диаграмме отобразились ассоциации между классами-сущностями, участвующими в реализации варианта использования. Если ассоциации на диаграмме классов не видны, то их можно отобразить таким способом: контекстное меню класса на диаграмме -> Related Elements -> Visualize Related Model Element....

      Назначим классам стереотипы. Выделим в Model Explorer класс RegistrationController. С помощью контекстного меню добавим стереотип «control». Аналогично добавим стереотип «boundary» граничному классу RegistrationForm. Стереотип «control» классу DataAccess и стереотип «boundary» классу MainMenuForm мы добавили ранее. Проверим, что классам-сущностям Student, CourseOffering, Schedule назначен стереотип «entity».

      Начальный эскиз диаграммы классов VOPC RegisterForCourses приведён на рисунке 4.3.1. В дальнейшем нам потребуется доработать этот эскиз, добавив ассоциации между классами.


Рис. 4.3.1. UML-диаграмма классов VOPC RegisterForCourses

Рис. 4.3.1. UML-диаграмма классов VOPC RegisterForCourses (для всех вариантов) (работа над диаграммой не завершена!)

      Откроем внутри кооперации RegisterForCourses диаграмму последовательности RegisterForCourses Basic Flow (основной поток варианта использования Зарегистрироваться на курсы). Добавим на диаграмму 6 линий жизни (Lifeline): линию жизни действующего лица Студент; menu:MainMenuForm; rform:RegistrationForm; rctrl:RegistrationController; dao:DataAccess; curStud:Student. Проще всего добавлять линии жизни, перенося действующее лицо и классы из Model Explorer на диаграмму. При переносе класса укажем, что добавляется линия жизни. Добавим линиям жизни стереотипы. Заметим, что линию жизни объекта граничного класса следует расположить рядом с линией жизни, представляющей то действующее лицо, за общение с которыми отвечает граничный класс, а линии объектов контроллеров следует расположить в середине диаграммы. В правой части диаграммы располагают линии жизни объектов-сущностей.

      Выберем на палитре синхронное сообщение (Call Message) и проведём его от линии жизни актора Студент к линии жизни menu:MainMenuForm. Оставим сообщение без имени. Создадим вызываемую операцию (контекстное меню сообщения -> Select Operation -> Create Operation -> "registerForCourses"). Добавим второе синхронное сообщение -- вызов операции с тем же именем, которым форма извещает контроллер о выборе студента и заодно пересылает ссылку на экземпляр учётной записи текущего пользователя (параметр операции следует добавить в окне её спецификации на вкладке Parameters). Экземпляр контроллера должен проверить, возможна ли работа студента с индивидуальным учебным планом. Для этого он посылает сам себе рефлексивное сообщение (Self Message) -- вызов собственной операции isRegistrationOpened. Если регистрация открыта, то следует выполнить дополнительные действия. Поместим на диаграмму комбинированный фрагмент (Loop Combined Fragment) и поменяем в нём оператор с loop на opt (контекстное меню фрагмента, Operator type -> opt). Зададим сторожевое условие (контекстное меню -> Operand -> Manage Operands...). Внутри opt-фрагмента контроллер запрашивает через объект доступа к данным сведения о студенте, который является текущим пользователем. Объект доступа к данным создаёт объект curStud:Student и заполняет его данными, подгруженными из БД. Объект-контроллер запрашивает был ли ранее создан учебный план на текущий семестр у этого студента (если был, то создание нового плана будет недоступно, зато будут доступны обновление, удаление, утверждение плана). Добавим в операнде взаимодействия opt-фрагмента сообщение от экземпляра контроллера к объекту доступа к данным, создающее сообщение от dao:DataAccess к curStud:Student, сообщение-вызов операции hasScheduleForSemester от rctrl:RegistrationController к curStud:Student;. Добавим ниже opt-фрагмента сообщение-возврат от rctrl:RegistrationController к menu:MainMenuForm.

      Каждое сообщение экземпляру класса должно быть связано с операцией данного класса. Сообщения, получаемые экземплярами действующих лиц, связывать с операциями не следует. Также не связывают с операциями сообщения-возвраты (Reply Message). Всякий раз, добавляя сообщение, вызывающее новую операцию будем добавлять операцию в модель. Параметры операции буем указывать в окне её спецификации, на вкладке Parameters. Если вызывается ранее созданная операция, то снова добавлять её в тот же класс не следует, достаточно только выбрать её из списка операций (контекстное меню сообщения -> Select Operation -> Select Operation...). Убедимся, что нами созданы операции DataAccess::getStudentByUser(u:User):Student, MainMenuForm::displayError(), Student::hasScheduleForSemester(semester):boolean и связать сообщения-вызовы с ними.

      Далее есть два варианта развития событий. Либо регистрация закрыта, и форма, получив от контроллера возврат, вызывает у себя операцию displayError ради информирования студента об ошибке, либо регистрация открыта и происходит дальнейшее содержательное взаимодействие. Добавим на диаграмму альтернативный комбинированный фрагмент взаимодействия (Alt. Combined Fragment). По умолчанию во фрагменте два операнда с пустыми сторожевыми условиями. Ввести нужные сторожевые условия следует, выделив фрагмент на диаграмме и вызвав контекстное меню -> Operand -> Manage Operands. Добавим в нижнем операнде alt-фрагмента создающее сообщение open от menu:MainMenuForm к rform:RegistrationForm. Расширим нижний операнд комбинированного фрагмента для того, чтобы в нём поместилось продолжение взаимодействия. UML-диаграмма примет вид, схожий с рисунком 4.3.2.


Рис. 4.3.2. Начальный вид UML-диаграммы последовательности RegisterForCourses Basic Flow

Рис. 4.3.2. Начальный вид UML-диаграммы последовательности RegisterForCourses Basic Flow (для всех вариантов) (работа над диаграммой не завершена!)

      Сообщения-возвраты (Reply Message), посылаемые в ответ на сообщения-вызовы не всегда будем явно изображать на диаграмме, она и без того достаточно сложна. Сообщения-возвраты мы будем изображать только при необходимости, когда без них затруднительно понять логику взаимодействия.

      Помещаем на диаграмму вложенный комбинированный фрагмент с оператором alt аналогично предыдущему. Добавим в новый комбинированный фрагмент ещё два операнда взаимодействия, чтобы общее их количество стало равно четырём, (контекстное меню -> Operand -> Add Operand). Добавим операндам сторожевые условия (контекстное меню -> Operand -> Manage Operands...). Внутри каждого их четырёх операндов комбинированного фрагмента будет происходить одно из взаимодействий, соответствующих четырём подчинённым потокам варианта использования. Чтобы не загромождать диаграмму основного потока, для каждого подчинённого потока нами ранее создана отдельная диаграмма. Здесь мы сделаем на них ссылки. Для этого добавим по одному элементу Interaction Use в каждый операнд. Во вкладке General в спецификации каждого Interaction Use заполним поле Refers to ссылкой на диаграмму (в выпадающем списке выберите Select Frame...). UML-диаграмма примет окончательный вид, показанный на рисунке 4.3.3. Если Вы сначала создали Interaction Use, а затем -- диаграмму для него, то диаграмма помещается средой в корне проекта, что затрудняет дальнейшую работу. Переместить диаграмму из корня на подобающее ей место внутри кооперации можно. Найдите диаграмму на закладке Diagram Navigator (или Model Explorer). Откройте её спецификацию. На закладке General второе сверху поле Parent model: <No parent model>. Нажмите "..." и укажите нужную кооперацию как родительскую модель для диаграммы.


Рис. 4.3.3. Окончательный вид UML-диаграммы последовательности RegisterForCourses Basic Flow

Рис. 4.3.3. Окончательный вид UML-диаграммы последовательности RegisterForCourses Basic Flow (для всех вариантов)

Моделирование подчинённых потоков CreateSchedule Subflow и DisplayCourseOfferings Subflow
(только для вариантов 1 и 3)


      Если у Вас нечётный вариант, то составьте диаграмму последовательности CreateSchedule Subflow и диаграмму последовательности DisplayCourseOfferings Subflow. Для остальных вариантов упражнения указаны дальше по тексту. Смоделируем один из подчинённых потоков CreateSchedule Subflow. Вид UML-диаграммы, которая должна получиться, показан на рисунке 4.3.4. На диаграмме использован комбинированный фрагмент с оператором opt, представляющий ветвление с единственной содержательной альтернативой. Добавить его следует как комбинированный фрагмент с оператором loop, а затем исправить оператор взаимодействия на opt (контекстное меню -> Operator Kind -> opt). Обратите внимание, что на рис. 4.3.4 есть сообщение new, которое имеет тип Create Message. Связывать сообщение с вызовом операции не следует. Ещё на диаграмме присутствует множественная линия жизни cOff[i]:CourseOffering, изображающая элемент коллекции экземпляров класса CourseOffering -- списка курсов, предлагаемых для изучения студентами в текущем семестре. Откройте спецификацию этой линии жизни и установите флажок Multi-object на вкладке General.


Рис. 4.3.4. UML-диаграмма последовательности CreateSchedule Subflow

Рис. 4.3.4. UML-диаграмма последовательности CreateSchedule Subflow (для вариантов 1 и 3)

      Фрагмент Interaction Use (с оператором взаимодействия ref) ссылается на диаграмму последовательности DisplayCourseOfferings Subflow. Поскольку вывод списка предлагаемых курсов возникает в нескольких подчинённых потоках, есть смысл смоделировать его однажды, и многажды ставить ссылку на взаимодействие, моделирующее его. На диаграмме присутствует комбинированный фрагмент с оператором loop, описывающий цикл типа for со сторожевым условием. Создавая loop-фрагмент, задайте сторожевое условие (контекстное меню -> Operand -> Manage Operands...).


Рис. 4.3.5. UML-диаграмма последовательности DisplayCourseOfferings Subflow

Рис. 4.3.5. UML-диаграмма последовательности DisplayCourseOfferings Subflow (для вариантов 1 и 3)

      Каждое сообщение на диаграмме последовательности назначает экземплярам классов обязанности по отправке или приёму и обработке сообщения. Для приёма сообщения в классе объекта-приёмника должна быть одноимённая операция. Для отправки сообщения между экземплярами классов должно быть соединение, т. е. между классами, экземпляры которых обмениваются сообщениями, должна быть ассоциация. На диаграмме 4.3.3. RegisterForCourses Basic Flow форма отправляет сообщение registerForCourses контроллеру регистрации. Значит, в классе RegistrationController должна быть одноимённая операция, которая обрабатывает сообщение от формы, а между классом-формой и классом-контроллером должна быть ассоциация. Нарисуем её на диаграмме VOPC RegisterForCourses. Мощности полюсов этой ассоциации 1 к 0..1 (меню может быть связано с другим контроллером, если в системе работает не студент, а профессор или работник учебного отдела). Объект-контроллер посылает сообщения объекту класса DataAccess (см. рис. 4.3.3, 4.3.4) и экземпляру класса Student, следовательно, нужны ещё ассоциации между классами. Добавьте ассоциации, соединяющие классы RegistrationController, DataAccess, Student, CourseOffering. Ассоциации от класса DataAccess мы добавляем, предполагая, что в ответ на полученные запросы он возвращает объекты-студенты и объекты-курсы, загруженные из БД, следовательно между классами должны быть связи. Конкретный тип связей будет выбран позднее. В ходе эскизного моделирования можно считать, что эти связи -- ассоциации. Заметим, что для того, чтобы между экземплярами двух классов было соединение, ассоциация между классами необязательна. При проектном моделировании будет решено, какие эскизные ассоциации следует оставить. При эскизном моделировании создают ассоциации, потому что так проще.

      Проверьте, что для каждого сообщения, принимаемого экземпляром любого класса (не действующего лица), существует связанная операция. Заметьте, что не следует дважды создавать операцию в одном и том же классе, обрабатывающую приём двух одноимённых сообщений. Второе сообщение следует связать с ранее созданной операцией. На диаграмме VOPC RegisterForCourses отобразятся созданные операции. В результате классы должны выглядеть, как показано на рисунке 4.3.6. Если количество операций классов и их сигнатуры на Вашей диаграмме отличаются от рисунка 4.3.6, то в этом нет ошибки. Операции могут быть добавлены, а сигнатуры переписаны при выполнении последующих упражнений.


Уточнение диаграммы классов VOPC RegisterForCourses в соответствии с рисунком 4.3.6
(общее для всех вариантов)


Рис. 4.3.6. Итоговый вид UML-диаграммы классов VOPC RegisterForCourses в Analysis Model

Рис. 4.3.6. Итоговый вид UML-диаграммы классов VOPC RegisterForCourses в Analysis Model (для всех вариантов)

      Уточнение диаграммы классов VOPC RegisterForCourses следует выполнить независимо от номера варианта (если у Вас чётный вариант, то добавьте операции и ассоциации, о которых сказано выше). Добавьте (выполняя любой вариант) новый атрибут классу CourseOffering -- numStudents. Отметьте атрибут CourseOffering::numStudents:byte как выводимый (в окне спецификации атрибута на вкладке General отметьте Derived), поскольку его значение равно количеству учебных планов студентов, связанных с предлагаемым курсом. Так как студенты учатся на дневном и вечернем отделениях добавьте в пакет Analysis Model классы FullTimeStudent (студент очного отделения) и PartTimeStudent (студент вечернего отделения) -- наследники класса Student. Чтобы убедиться, что классы будут созданы в пакете Analysis Model следует создать их с помощью контекстного меню пакета Analysis Model в Model Explorer. Если их создать с помощью палитры на диаграмме, классы будут помещены в пакет Use Case Realizations, являющийся родительским для диаграммы. Если классы созданы в неверном пакете, перетащите их в нужный пакет в Model Explorer. Проведите на диаграмме связи обобщения (Generalization). Выделите обе связи обобщения и создайте из них Generalization Set с помощью контекстного меню. Укажите в окне спецификации набора обобщений его свойства: disjoint, covering. В контекстном меню диаграммы укажите способ вывода наборов обобщений (-> Presentation Options -> Generalization Set Notation -> Dashed Line). У появившейся пунктирной линии вызовите контекстное меню и включите вывод свойств набора обобщений -> Presentation Options -> Show Constraints. Возле пунктирной линии появится надпись {complete, disjoint}. Если рекомендация не срабатывает, то введите нужную надпись в название набора вместе с фигурными скобками и выведите название набора обобщений на диаграмму. Заметим, что в метамодели свойство набора обобщений называется covering, но на диаграмме указывается как ограничение complete.

      Пометьте класс Student абстрактным (контекстное меню класса -> Model Element Properties-> Abstract). Добавьте атрибуты классам наследникам (указываются только собственные атрибуты, унаследованные добавлять не следует). Так как мы моделируем классы анализа, типы атрибутов следует выбирать из набора стандартных типов UML. Создайте атрибуты CourseOffering::semester:byte, Student::id:long. Идентификатором экземпляров класса Student сделайте Student::id вместо Student::name. UML-диаграмма должна выглядеть как на рисунке 4.3.6. Если количество операций классов и их сигнатуры на Вашей диаграмме отличаются от рисунка 4.3.6, то в этом нет ошибки. Операции могут быть добавлены, а сигнатуры переписаны при выполнении последующих упражнений.


Моделирование подчинённого потока DeleteSchedule Subflow
(только для вариантов 2 и 4)


      Вид UML-диаграммы последовательности, моделирующей подчинённый поток DeleteSchedule Subflow, приведён на рисунке 4.3.7.


Рис. 4.3.7. UML-диаграмма последовательности DeleteSchedule Subflow

Рис. 4.3.7. UML-диаграмма последовательности DeleteSchedule Subflow (для вариантов 2 и 4)

      Если у Вас чётный вариант, то Вам следует смоделировать диаграмму последовательности DeleteSchedule Subflow. Перенесём на диаграмму DeleteSchedule Subflow действующее лицо Студент из модели вариантов использования (создавать его заново не следует). Создадим 7 линий жизни объектов (Lifeline) на диаграмме: rform:RegistrationForm, rctrl:RegistrationController, dao:DataAccess, curStud:Student, curSched:Schedule, primary[i]:CourseOffering, alternative[i]:CourseOffering. Назначим линиям жизни стереотипы в соответствии с рисунком 4.3.7. Проведём сообщения вызова между объектами, создадим вызываемые операции и свяжем их с сообщениями. Добавим комбинированные фрагменты с оператором взаимодействия loop. Добавим ссылку на диаграмму взаимодействия, описывающую подчинённый поток (Interaction Use), и укажем диаграмму последовательности DisplayCourseOfferings Subflow (контекстное меню -> Refers to -> More... -> поле Refers to на вкладке General). Пометим линию жизни curSched:Schedule завершённой (чтобы появился крестик на её конце) -- контекстное меню -> Model Element Properties-> Stopped. По окончании работы с диаграммой последовательности убедимся, что на диаграмме классов VOPC RegisterForCourses присутствуют все ассоциации, необходимые для взаимодействия экземпляров классов, а также операции из сообщений-вызовов (см. рисунок 4.3.6).

Упражнение 4.4. Анализ варианта использования «Закрыть регистрацию»

(общее для всех вариантов)


      Выполняя любой вариант, необходимо провести анализ варианта использования «Закрыть регистрацию». Определим классы анализа, которые понадобятся для реализации варианта использования «Закрыть регистрацию». Согласно диаграмме вариантов использования имеются два действующих лица (Студент и Расчётная система), связанных с нашим вариантом использования. Создадим граничный класс RegistrarForm -- экранную форму, отвечающую за взаимодействие с Регистратором и класс BillingSystem, реализующий обмен данными с Расчётной системой. В Model Explorer вызовем контекстное меню пакета Analysis Model, Model Element -> Class. Дадим имена классам -- RegistrarForm, BillingSystem. Третий нужный нам граничный класс -- MainMenuForm -- мы создали ранее. Создадим управляющий класс CloseRegistrationController, отвечающий за реализацию бизнес-логики (действия аналогичны). Второй нужный нам управляющий класс -- DataAccess, отвечающий за сохранение данных об устойчивых объектах в базе данных нашей системы, -- уже создан нами. Из описания варианта использования следует, что в потоках событий будут задействованы экземпляры классов Student, CourseOffering, Schedule. Открываем в редакторе диаграмму классов VOPC CloseRegistration. Перетаскиваем на неё вышеупомянутые классы из Model Explorer. Убедимся, что на диаграмме отобразились ассоциации между классами-сущностями, участвующими в реализации варианта использования. Если ассоциации на диаграмме классов не видны, то их можно отобразить таким способом: контекстное меню класса на диаграмме -> Related Elements -> Visualize Related Model Element....

      Назначим классам стереотипы. Выделим в Model Explorer класс CloseRegistrationController. С помощью контекстного меню добавим стереотип «control». Аналогично добавим стереотип «boundary» граничным классам RegistrarForm и BillingSystem. Стереотип «control» классу DataAccess и стереотип «boundary» классу MainMenuForm мы добавили ранее. Проверим, что классам-сущностям Student, CourseOffering, Schedule назначен стереотип «entity». Необходимо, чтобы все классы анализа оказались в корне пакета Analysis Model. Если Вы создали классы на диаграмме, то найдите их в Model Explorer (внутри кооперации) и переместите (перетащите) в корень пакета Analysis Model. Начальный вариант UML-диаграммы классов VOPC CloseRegistration приведён на рисунке 4.4.1.


Рис. 4.4.1. Начальный вариант UML-диаграммы классов VOPC CloseRegistration

Рис. 4.4.1. Начальный вариант UML-диаграммы классов VOPC CloseRegistration (для всех вариантов) (работа с диаграммой не завершена)

      Мы не будем полностью моделировать все потоки событий этого варианта использования. Смоделируем подчинённый поток «Передать данные об учебных планах студентов». Для этого создадим внутри кооперации CloseRegistration диаграмму последовательности TransferSchedulesData Subflow и откроем её в редакторе. Добавим на диаграмму 7 линий жизни (Lifeline): crctrl:CloseRegistrationController, dao:DataAccess, studlist[i]:Student, cOff[j]:CourseOffering, studlist[i].schedule[s]:Sсhedule, bs:BillingSystem, действующее лицо Расчётная система. Проще всего добавлять линии жизни, перенося действующее лицо и классы из Model Explorer на диаграмму. При переносе класса укажем, что добавляется линия жизни. Добавим линиям жизни стереотипы в соответствии с рисунком 4.4.2. Заметим, что линию жизни объекта граничного класса следует расположить рядом с линией жизни, представляющей то действующее лицо, за общение с которым отвечает граничный класс. Пометим три множественные линии жизни. (Откройте спецификацию каждой такой линии жизни и установите флажок Multi-object на вкладке General.)

      Добавим на диаграмму сообщения и комбинированные фрагменты согласно рисунку 4.4.2. Редактирование осуществим по аналогии с RegisterForCourses Basic Flow. Комбинированный фрагмент с оператором opt следует добавлять как элемент палитры Loop Combined Fragment с последующей заменой в спецификации фрагмента оператора на нужный (контекстное меню -> Operator Kind). Длительные сообщения создадим с помощью элемента палитры Duration Message, а затем укажем их тип (контекстное меню -> Type). Асинхронные сообщения добавляются на диаграмму как обычные. Затем в контекстном меню устанавливается флажок Model Element Properties -> Asynchronous. Границы для количества итераций для комбинированного фрагмента с оператором loop задаются в спецификации вложенного в него операнда взаимодействия (Interaction Operand) на вкладке Guard.


Рис. 4.4.2. UML-диаграмма последовательности TransferSchedulesData Subflow

Рис. 4.4.2. UML-диаграмма последовательности TransferSchedulesData Subflow (для всех вариантов)

      Моделирование реализации варианта использования «Закрыть регистрацию» надо продолжить. Откроем диаграмму классов VOPC CloseRegistration. Добавим ассоциации, необходимые для того, чтобы взаимодействие, описанное диаграммой последовательности TransferSchedulesData Subflow, было осуществимо. Расставим мощности на полюсах ассоциаций. Укажем направления навигации (на противоположном полюсе с помощью контекстного меню укажем Navigable Unspecified). Итоговый вид UML-диаграммы VOPC CloseRegistration приведён на рисунке 4.4.3.


Рис. 4.4.3. Итоговая версия UML-диаграммы классов VOPC CloseRegistration в Analysis Model

Рис. 4.4.3. Итоговая версия UML-диаграммы классов VOPC CloseRegistration в Analysis Model (для всех вариантов)

      Если количество операций классов и их сигнатуры на Вашей диаграмме отличаются от рисунка 4.4.3, то в этом нет ошибки. Операции могут быть добавлены, а сигнатуры переписаны при выполнении последующих упражнений. Некоторое значение имеет список операций класса DataAccess: DataAccess::getCourseOfferingList(semester:byte):CourseOffering[], DataAccess::getStudentByUser(u:User):Student, DataAccess::getStudentList(semester:byte):Student[], DataAccess::updateCourseOfferings(cOffs:CourseOffering[]):boolean, DataAccess::updateStudent(st:Student):boolean; и список операций класса BillingSystem: BillingSystem::finishTransferData{}, sendStudentData(name:string, address:string, cOff: CourseOffering[]). Стоит сделать так, чтобы в модели они были именно таковы.


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


      Созданную модель анализа следует сохранить в резервной копии файла проекта. Если при проектировании модель анализа разрушится, можно будет использовать резервную копию. При сдаче выполненных упражнений полезно иметь с собой два файла проекта: один, сохранённый на момент окончания эскизного моделирования; второй, представляющий модель после выполнения всех упражнений. Закройте проект и сделайте резервную копию файла проекта в workspace.

5. Проектное моделирование системы


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

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

Упражнение 5.1. Проектирование архитектуры системы регистрации

(общее для всех вариантов)


      Система регистрации работает с реляционной базой, в которой между сеансами работы хранит сведения о профессорах, студентах и курсах. Также система регистрации взаимодействует с внешней программной системой -- расчётной системой. Следовательно, при проектировании мы будем использовать механизм обеспечения устойчивости RDBMS (relational database management system) и механизм обмена запросами и/или данными с внешней системой RemoteInterchange. Существуют готовые каркасы, обеспечивающие доступ к реляционным БД. К таким относится JDBC (Java Database Connectivity). Каркас XML-RPC обеспечивает межсистемное взаимодействие. Проектные механизмы уже добавлены в нашу модель (они входят в состав заготовки проекта, с которой мы начали выполнять упражнения). См. пакеты Architectural Mechanisms и Middleware в Logical View внутри Design Model.

      В Design Model создайте ещё два пакета: Application и BusinessServices. На уровень приложения следует поместить элементы пользовательского интерфейса и элементы, реализующие логику приложения. На уровень бизнес-служб -- элементы, относящиеся к предметной области. Уровень промежуточного ПО содержит элементы, обеспечивающие сервисы, независимые от платформы. Назначьте пакетам стереотип «layer» -- архитектурный уровень. В Design Model создайте диаграмму пакетов (Package Diagram) Main. Вытащите на неё все три архитектурных уровня и соедините их зависимостями (Dependency), как указано на рис. 5.1.1. Также из пакета Architectural Mechanisms вытащите на диаграмму пакеты RemoteInterchange и Persistency. Проведите к ним зависимости от пакета BusinessServices, т. к. там будут использованы описания этих механизмов. Настройте отображение имени родительского пакета на диаграмме (контекстное меню пакета -> Presentation Options -> Show Owner -> Show Name Only). Если в заготовке проекта отсутствовали зависимости пакетов RemoteInterchange и Persistency от уровня Middleware, то добавьте их в модель. Создана иерархия архитектурных уровней системы, т. е. её устройство с точки зрения самых крупных блоков.


Рис. 5.1.1. UML-диаграмма пакетов Main

Рис. 5.1.1. UML-диаграмма пакетов Main (для всех вариантов)

      Следующие действия нацелены на трансформацию классов анализа в проектные элементы (классы, интерфейсы и подсистемы) и распределение проектных элементов по уровням системы.

      При эскизном моделировании не были полностью учтены все вопросы, связанные с обеспечением устойчивости данных. В потоке событий система предпринимала некоторые действия, чтобы введённые данные были доступны не только в текущем сеансе работы, но и в последующих. Для этого отправлялись сообщения к объекту доступа к данным, но его действия по обработке этих сообщений не были промоделированы. В этом нет ошибки, во время эскизного моделирования эти вопросы рассматривать рано, надо сосредоточиться на основных функциях системы. Начиная проектное моделирование, следует вернуться к этим вопросам и смоделировать то, что было пропущено ранее. Реализация обязанностей, назначенных классу DataAccess, сложна. Поэтому при отображении в проектные классы следует перевести его в подсистему обеспечения устойчивости DBAccess (сокращённо от DataBase Access). Граничный класс BillingSystem, обеспечивающий взаимодействие с расчётной системой, также отображается в подсистему BSAccess (сокращённо от Billing System Access) для того, чтобы возможные изменения во взаимодействии с расчётной системой мало затрагивали остальные части системы и были локализованы в подсистеме. Остальные классы анализа перейдут в проектные один в один.

      Итак, все классы анализа, кроме DataAccess и BillingSystem, отобразятся в проектные один в один. Чтобы не испортить модель анализа, скопируйте её содержимое внутрь проектной модели. Для этого в Model Explorer выделите пакет Analysis Model, вызовите его контекстное меню и выберите в нём пункт Duplicate Recursively. После этого будет осуществлено дублирование пакета и всех его элементов. Дубль пакета получит имя Analysis Model2. Стереотипы анализа («boundary», «control», «entity») в проектной модели не имеют смысла, поэтому их следует удалить со всех классов пакета Analysis Model2.

      Создайте в пакете Application пакет Registration. В созданный пакет переместите классы RegistrationForm и RegistrationController из корня Analysis Model2. Для этого воспользуйтесь контекстным меню элемента и пунктом Move... . Также создайте в пакете Application пакет Login и переместите в него классы LoginForm, LoginController, MainMenuForm из корня Analysis Model2. Ещё создайте в пакете Application пакет CloseRegistration и переместите в него классы RegistrarForm и CloseRegistrationController из корня Analysis Model2.

      В пакете BusinessServices создайте пакет UniversityArtefacts (т. е. артефакты университета, в нем будут размещены классы-сущности предметной области, а также перечислимые типы DayOfWeek и UserType). Через контекстное меню откройте спецификацию диаграммы классов Key Abstractions2. Введите её новое имя в поле Diagram name: UniversityArtefacts. Укажите новую родительскую модель Parent model: пакет UniversityArtefacts. Примените изменения. В результате этих действий диаграмма вместе со всеми её элементами и связями переместится в пакет UniversityArtefacts. Дополнительно в этот пакет следует переместить классы FullTimeStudent и PartTimeStudent из корня Analysis Model2. Проверьте, что все копии классов-сущностей и перечислимых типов оказались в пакете UniversityArtefacts. Если что-то всё ещё не переместилось, то довершите перемещение.

      В пакете BusinessServices создайте пакет Interfaces (где будут находиться все внутренние интерфейсы системы). В пакет Interfaces перенесите классы DataAccess и BillingSystem из Analysis Model2. Переименуйте DataAccess в IDBAccess и назначьте ему стереотип «Interface». Переименуйте BillingSystem в IBSAccess и назначьте ему стереотип «Interface». Пакет Use Case Realizations из Analysis Model2 перенесите в Design Model и переименуйте в Design Use Case Realizations. Пустой пакет Analysis Model2 удалите из проекта.

      При реализации подсистемы DBAccess будет использован механизм RDBMS-JDBC, смоделированный в одноимённом пакете, расположенным в Design Model::Architectural Mechanisms::Persistency. При реализации подсистемы BSAccess будет использован механизм XMLRPCInterchange, смоделированный одноимённым пакетом, расположенным в Design Model::Architectural Mechanisms::RemoteInterchange. Чтобы не повредить части модели, описывающие механизмы, скопируйте их внутрь Design Model. Для этого продублируйте (Duplicate Recursively) пакеты RDBMS-JDBC и XMLRPCInterchange, а затем переместите полученные дубли на уровень Business Services и переименуйте их в DBAccess и BSAccess. Назначьте пакетам DBAccess и BSAccess стереотип «subsystem». Откройте окно спецификации пакета-подсистемы DBAccess. Выберите вкладку Template Parameters (если она скрыта, то воспользуйтесь чёрным треугольником в правом верхнем углу окна спецификации). Удалите все параметры, так как DBAccess является конкретизацией параметризованного пакета RDBMS-JDBC. Таким же способом удалите параметры у пакета-подсистемы BSAccess -- конкретизации параметризованного пакета XMLRPCInterchange. Структура проектной модели в Model Explorer должна иметь вид похожий на рис. 5.1.2. Убедитесь, что верно распределили элементы модели по пакетам.


Рис. 5.1.2. Структура проектной модели

Рис. 5.1.2. Структура проектной модели (для всех вариантов)

      Переименуйте кооперации и диаграммы внутри пакета Design Model::Design Use Case Realizations, убрав цифру в окончании и добавив приставку Design (см. рисунки 5.1.1 и 5.1.2). UML-диаграмма составной структуры внутри этого пакета примет вид, представленный на рисунке 5.1.3.


Рис. 5.1.3. UML-диаграмма составной структуры Design Use Case Realizations

Рис. 5.1.3. UML-диаграмма составной структуры Design Use Case Realizations (для всех вариантов)

      Создайте диаграмму пакетов Dependencies в пакете Application. Разместите на ней пакеты BusinessServices::Interfaces и BusinessServices::UniversityArtefacts, а также все пакеты, вложенные в Application, которые есть в Вашей модели (CloseRegistration, Login, Registration). Укажите зависимости (Dependency) между ними в соответствии с рисунком 5.1.4. Элементы пакета Registration используют классы-артефакты и интерфейс подсистемы, отсюда его зависимости. Элементы пакета CloseRegistration используют классы-артефакты и интерфейс подсистемы, отсюда его зависимости. Элементы пакета Login используют классы-артефакты и классы из пакетов CloseRegistration, Registration, отсюда его зависимости. Настройте отображение имени родительского пакета на диаграмме для пакетов с уровня BusinessServices (контекстное меню пакета -> Presentation Options -> Show Owner -> Show Name Only). UML-диаграмма пакетов примет вид, схожий с рис. 5.1.4.


Рис. 5.1.4. UML-диаграмма пакетов Dependencies. Связи подпакетов уровня Application

Рис. 5.1.4. UML-диаграмма пакетов Dependencies. Связи подпакетов уровня Application (для всех вариантов)

      Создайте диаграмму пакетов BusinessServices в пакете BusinessServices. Разместите на ней пакеты этого архитектурного уровня, укажите зависимости (Dependency) между ними. Каждая подсистема реализует свой интерфейс, отсюда их зависимости от пакета Interfaces. Для описаний в пакетах Interfaces, BSAccess, DBAccess понадобятся классы-артефакты, отсюда остальные зависимости. UML-диаграмма пакетов примет вид, представленный на рис. 5.1.5. В дальнейшем у пакетов-подсистем возникнут дополнительные зависимости. Они будут добавлены в ходе проектирования подсистем.


Рис. 5.1.5. Структура уровня BusinessServices

Рис. 5.1.5. Структура уровня BusinessServices (для всех вариантов)

      Моделирование структуры потоков управления системы в упражнения не включено. Этот вопрос рассматривается только на лекциях. В системе можно выделить следующие процессы: StudentApplication.exe -- пользовательский процесс рабочего места студента; ProfessorApplication.exe -- пользовательский процесс рабочего места лектора; RegistrarApplication.exe -- пользовательский процесс рабочего места регистратора; RegistrationProcess -- процесс, управляющий ходом регистрации; BSAccessProcess -- процесс, обеспечивающий связь с расчётной системой; DBAccessProcess -- процесс, обеспечивающий доступ к БД системы.

      Промоделируем конфигурацию вычислительной среды. Она состоит из сред выполнения (Execution Environment), на которых могут быть размещены вложенные компоненты-процессы, и устройств (Device). Связи между узлами -- пути коммуникации -- являются подвидами ассоциации. Откроем диаграмму размещения (Deployment Diagram) Main внутри архитектурного представления Deployment View. Создадим на ней узлы и связи между узлами. Компоненты следует создавать, размещая их внутри родительского узла. Окончательный вид UML-диаграммы размещения Main приведён на рис. 5.1.6. По получившейся диаграмме можно судить, что в среде могут быть сервера регистрации, к каждому из которых подключён свой коммутатор и сервер расчётной системы. К каждому коммутатору подключён принтер и компьютеры трёх типов. Коммуникации осуществляются через сеть Wi-Fi кампуса, проводную локальную сеть кампуса, проводную сеть бухгалтерии. Принтер подключён по USB. UML-диаграмма размещения задаёт перечень типов узлов и возможные конфигурации, составленные из узлов разных типов. Если есть необходимость, то рисуют диаграмму с конкретными узлами (не с типами) для того, чтобы, например, пояснить количество серверов регистрации в системе (из диаграммы на рис. 5.1.6, строго говоря, не следует, что в системе такой сервер один). Сведения о количестве экземпляров узлов можно дать в примечании на диаграмме размещения, моделирующей типы узлов.


Рис. 5.1.6. UML-диаграмма размещения Main

Рис. 5.1.6. UML-диаграмма размещения Main (для всех вариантов)

      На этом проектирование архитектуры завершено, переходим к проектированию элементов системы.

Упражнение 5.2. Проектирование элементов системы регистрации

(содержит общую для всех вариантов часть и специальные части для разных вариантов)


      Проектирование элементов системы включает в себя следующие виды работ: уточнение реализаций вариантов использования; проектирование подсистем; проектирование классов и проектирование схемы реляционной базы данных.

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

      Переименуйте диаграммы из Design Model: диаграммы классов VOPC RegisterForCourses2 в Design VOPC RegisterForCourses, VOPC Login2 в Design VOPC Login, VOPC CloseRegistration2 в Design VOPC CloseRegistration; диаграммы последовательности RegisterForCourses Basic Flow2 в Design RegisterForCourses Basic Flow, Login Basic Flow2 в Design Login Basic Flow, CloseRegistration Basic Flow2 в Design CloseRegistration Basic Flow, CreateSchedule Subflow2 в Design CreateSchedule Subflow, DeleteSchedule Subflow2 в Design DeleteSchedule Subflow, UpdateSchedule Subflow2 в Design UpdateSchedule Subflow, SubmitSchedule Subflow2 в Design SubmitSchedule Subflow, DisplayCourseOfferings Subflow2 в Design DisplayCourseOfferings Subflow, TransferSchedulesData Subflow2 в Design TransferSchedulesData Subflow.

      Откройте диаграмму последовательности Design Login Basic Flow из кооперации DesignLogin в пакете Logical View :: Design Model :: Design Use Case Realizations. Уберите с линий жизни стереотипы анализа («boundary», «control», «entity») с помощью контекстного меню -> Stereotypes. Убедитесь, что бывший экземпляр dao:DataAccess стал "экземпляром интерфейса" dao:IDBAccess. Добавьте этой линии жизни стереотип «interface». Таким образом показано, что происходит обращение к экземпляру класса, реализующему интерфейс подсистемы. Какой именно это будет класс -- это для реализации варианта использования неважно.

      Реализация варианта использования не определяет, как подсистема DBAccess должна обрабатывать вызов операции её интерфейса. Эта часть относится к проектированию подсистемы и может варьироваться в зависимости от реализации подсистемы. Внутреннее поведение подсистемы скрыто, чтобы обеспечить возможность лёгкой модификации её реализации. Поэтому удалите сообщение new() от dao:IDBAccess к curUser:User. Надёжнее удалить это сообщение внутри фрейма Design Login Basic Flow в Model Explorer. Сигнатуры всех операций, вызываемых на диаграмме можете сразу пополнить их параметрами и типами возвращаемых значений. Чтобы это сделать, найдите соответствующую операцию внутри соответствующего класса в Model Explorer, вызовите её контекстное меню -> Open Specification, поле Return Type на вкладке General содержит возвращаемый тип. Вкладка Parameters содержит параметры.


Рис. 5.2.1. Уточнённая UML-диаграмма последовательности Design Login Basic Flow

Рис. 5.2.1. Уточнённая UML-диаграмма последовательности Design Login Basic Flow (для всех вариантов)



      Откройте диаграмму последовательности Design RegisterForCourses Basic Flow из кооперации DesignRegisterForCourses в пакете Logical View :: Design Model :: Design Use Case Realizations. Уберите с линий жизни стереотипы анализа («boundary», «control», «entity») с помощью контекстного меню -> Stereotypes. Убедитесь, что самая правая линия жизни -- бывший экземпляр dao:DataAccess представляет "экземпляр интерфейса" dao:IDBAccess. Добавьте ей стереотип «interface». Реализация варианта использования не должна определять, как подсистема DBAccess будет обрабатывать вызов операции её интерфейса. Эта часть относится к проектированию подсистемы и может варьироваться в зависимости от реализации подсистемы. Внутреннее поведение подсистемы должно быть скрыто, чтобы обеспечить возможность лёгкой модификации её реализации. Поэтому удалите сообщение new() от dao:IDBAccess к curStud:Student. Надёжнее удалить это сообщение внутри фрейма Design RegisterForCourses Basic Flow в Model Explorer. Сигнатуры всех операций, вызываемых на диаграмме можете сразу пополнить их параметрами и типами возвращаемых значений. Чтобы это сделать, найдите соответствующую операцию внутри соответствующего класса в Model Explorer, вызовите её контекстное меню -> Open Specification, поле Return Type на вкладке General содержит возвращаемый тип. Вкладка Parameters содержит параметры.


Рис. 5.2.2. Уточнённая UML-диаграмма последовательности Design RegisterForCourses Basic Flow

Рис. 5.2.2. Уточнённая UML-диаграмма последовательности Design RegisterForCourses Basic Flow (для всех вариантов)



      Откройте диаграмму последовательности Design TransferSchedulesData Subflow из кооперации DesignCloseRegistration в пакете Logical View :: Design Model :: Design Use Case Realizations. Уберите с линий жизни стереотипы анализа («boundary», «control», «entity») с помощью контекстного меню -> Stereotypes. Убедитесь, что вторая слева линия жизни -- бывший экземпляр dao:DataAccess представляет "экземпляр интерфейса" dao:IDBAccess. Добавьте ей стереотип «interface». Убедитесь, что вторая справа линия жизни -- бывший экземпляр bs:BillingSystem представляет "экземпляр интерфейса" bs:IBSAccess. Добавьте ей стереотип «interface». Реализация варианта использования не должна определять, как подсистемы DBAccess и BSAccess будут обрабатывать вызовы операций их интерфейсов. Эта часть относится к проектированию подсистем и может варьироваться в зависимости от реализаций подсистем. Внутреннее поведение подсистем должно быть скрыто, чтобы обеспечить возможность лёгкой модификации их реализаций. Поэтому удалите сообщения, исходящие от dao:IDBAccess и от bs:IBSAccess. Надёжнее удалить эти сообщения внутри фрейма Design TransferSchedulesData Subflow в Model Explorer. Линии жизни, которые на диаграмме не участвуют во взаимодействии (cOff[j]:CourseOffering и Расчётная система), удалите с диаграммы. Они будут участниками взаимодействий внутри реализаций интерфейсов. Эти взаимодействия будут промоделированы в ходе проектирования подсистем. Сигнатуры всех операций, вызываемых на диаграмме можете сразу пополнить их параметрами и типами возвращаемых значений. Чтобы это сделать, найдите соответствующую операцию внутри соответствующего класса в Model Explorer, вызовите её контекстное меню -> Open Specification, поле Return Type на вкладке General содержит возвращаемый тип. Вкладка Parameters содержит параметры.


Рис. 5.2.3. Уточнённая UML-диаграмма последовательности Design TransferSchedulesData Subflow

Рис. 5.2.3. Уточнённая UML-диаграмма последовательности Design TransferSchedulesData Subflow (для всех вариантов)



       В зависимости от Вашего варианта на диаграммах Design CreateSchedule Subflow (нечётный вариант), Design DisplayCourseOfferings Subflow (нечётный вариант), Design DeleteSchedule Subflow (чётный вариант) уберите с линий жизни стереотипы анализа («boundary», «control», «entity»), добавьте стереотип «interface» линиям жизни, представляющим объекты классов, реализующих интерфейсы подсистем (dao:IDBAccess и bs:IBSAccess). Если от линий жизни, представляющих экземпляры классов, реализующих интерфейсы подсистем, исходят сообщения, вызывающие операции других объектов, но не возвраты, то уберите эти сообщения с диаграмм, т. к. внутреннее поведение подсистем моделируется отдельно и не смешивается с внешним (относительно подсистемы) поведением.

      Сообщения, принимаемые объектом dao:IDBAccess, должны быть связаны с операциями интерфейса (IDBAccess::getCourseOfferingList() и др.). Сообщения, принимаемые объектом bs:IBSAccessIBSAccess, должны быть связаны с операциями интерфейса (IBSAccess::startTransferData() и др.). Если в Вашей модели эти операции отсутствуют, добавьте их в интерфейсы (независимо от Вашего варианта). Дополнительно создайте в интерфейсе IDBAccess операции init() и close(), управляющие соединением системы с СУБД. Проектные версии диаграмм Design CreateSchedule Subflow, Design DisplayCourseOfferings Subflow, Design DeleteSchedule Subflow примут вид, представленный на рисунках 5.2.4, 5.2.5, 5.2.6. При уточнении реализаций вариантов использования можно детализировать сигнатуры операций, т. е. добавить их параметры и типы результатов (в Model Explorer раскройте класс, выберите операцию, откройте её спецификацию и введите сведения на вкладках General и Parameters). Но это необязательно, т. к. можно составить полные сигнатуры операций позже -- при проектировании классов. Если Вы будете выполнять уточнения сигнатур операций, убедитесь, что работаете с проектными классами, т. е. элементами Design Model.


Рис. 5.2.4. Уточнённая UML-диаграмма последовательности Design CreateSchedule Subflow

Рис. 5.2.4. Уточнённая UML-диаграмма последовательности Design CreateSchedule Subflow (для вариантов 1 и 3)




Рис. 5.2.5. Уточнённая UML-диаграмма последовательности Design DisplayCourseOfferings Subflow

Рис. 5.2.5. Уточнённая UML-диаграмма последовательности Design DisplayCourseOfferings Subflow (для вариантов 1 и 3)


Рис. 5.2.6. Уточнённая UML-диаграмма последовательности DeleteSchedule Subflow

Рис. 5.2.6. Уточнённая UML-диаграмма последовательности DeleteSchedule Subflow (для вариантов 2 и 4)


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


Вводные замечания по проектированию подсистем
(общее для всех вариантов)


      Следующей технологической операцией является проектирование подсистем. В рассматриваемой модели в ходе этой операции для 1го и 2го вариантов следует на основе механизма JDBC спроектировать подсистему DBAccess, а для 3го и 4го вариантов следует на основе механизма XMLRPCInterchange спроектировать подсистему BSAccess. При этом механизм выполняет роль шаблона, описывающего с точки зрения структуры и поведения либо типовую организацию доступа к устойчивым данным, либо типовую организацию обмена данными с внешней системой. В параметризованном пакете Design Model::Architectural Mechanisms::Persistency::RDBMS-JDBC параметрами являются классы PersistentObject, PersistentObjectList и DBClass, а в шаблоне Design Model::Architectural Mechanisms::RemoteInterchange::XMLRPCInterchange -- классы ObjectToSend, ObjectToReceive, CustomTypeFactory, CustomParser, CustomSerializer и XMLRPCConnector. Проектирование подсистемы, в основном, сводится к конкретизации шаблона, в ходе которой класс-параметр (например, PersistentObject в вариантах 1 и 2) заменяется на конкретный класс из модели (например, на класс CourseOffering, сведения об экземплярах которого хранятся в БД, и другие подобные классы из пакета UniversityArtefacts). Класс-параметр PersistentObjectList (в вариантах 1 и 2) заменяется на соответствующие классы-контейнеры (например, CourseOfferingList). Класс-параметр DBClass заменяется на прокси-класс подсистемы DBAccess (в вариантах 1 и 2). Класс-параметр XMLRPCConnector (в вариантах 3 и 4) заменяется на прокси-класс подсистемы BSAccess. Классы-параметры ObjectToSend и ObjectToReceive (в вариантах 3 и 4) заменяется на класс CourseOffering, сведения об экземплярах которого будут пересылаться во внешнюю систему. Классы-параметры CustomTypeFactory, CustomParser, CustomSerializer (в вариантах 3 и 4) заменяются на классы подсистемы BSAccess, обеспечивающие передачу экземпляров класса CourseOffering во внешнюю систему.


Проектирование подсистемы DBAccess на основе механизма JDBC
(только для вариантов 1 и 2)


      Выполняя упражнения 1го или 2го варианта, переименуйте класс DBClass внутри пакета DBAccess в класс DBAccess и назначьте ему стереотип «subsystem proxy» -- тем самым будет указано, что экземпляр этого класса будет принимать все сообщения, идущие внутрь подсистемы DBAccess. Класс PersistentObjectList переместите в пакет UniversityArtefacts, переименуем его в CourseOfferingList. Откройте спецификацию класса CourseOfferingList через его контекстное меню. Найдите вкладку Relations. Если её не видно, воспользуйтесь чёрным треугольником в правом верхнем углу окна спецификации класса и сделайте вкладку видимой. Измените имя у связи привязки шаблона (Binding) на < E->CourseOffering >. Тем самым Вы укажете, что элементами этого списка будут экземпляры класса CourseOffering. Класс PersistentObject переименуйте в класс CourseOffering и с помощью контекстного меню объедините класс CourseOffering из подсистемы DBAccess с классом CourseOffering из пакета UniversityArtefacts (Merge to Model Element...) так, чтобы целью объединения был класс UniversityArtefacts::CourseOffering. Если результат объединения оказался не в том пакете, то перенесите его в пакет UniversityArtefacts. В подсистеме DBAccess переименуйте кооперацию JDBC2 в IDBAccessRealization. Добавьте ей стереотип «interface realization» и удалите стереотип «mechanism». В подсистеме DBAccess переименуйте одноимённые диаграммы пакетов и классов RDBMS-JDBC2 в DBAccess.

      Выполняя упражнения 1го или 2го варианта, откройте диаграмму классов DBAccess в одноимённой подсистеме. На диаграмме указано, что при реализации доступа к БД используются элементы, описанные в пакетах java::lang, java::util и java::sql. Поэтому следует убедиться, что на диаграмме пакетов DBAccess из одноимённой подсистеме присутствуют пакеты lang и sql с уровня Middleware из пакета java, и что проведены зависимости (Import или Dependency) от подсистемы DBAccess к пакетам java::lang, java::util и java::sql. Если этих связей нет, то добавьте их на диаграмму пакетов. При этом не забудьте, что зависимости проводятся так, чтобы направления стрелок указывали от зависящего пакета к пакетам, от которых он зависит. Пакет-подсистема DBAccess является конкретизацией параметризованного пакета RDBMS-JDBC. Следует добавить пакет RDBMS-JDBC на диаграмму и провести к нему связь привязки шаблона (зависимость, помеченную стереотипом «bind»). Откройте спецификацию этой зависимости и в поле Name на вкладке General введите: <DBClass -> DBAccess, PersistentObject -> CourseOffering, User, Student, PersistentObjectList -> CourseOfferingList> (переводы строк при работе под Windows можно вставить как Alt+Enter). В результате, диаграмма пакетов подсистемы DBAccess должны быть похожа на рисунок 5.2.7.


Рис. 5.2.7. UML-диаграмма пакетов в подсистеме DBAccess

Рис. 5.2.7. UML-диаграмма пакетов в подсистеме DBAccess (для вариантов 1 и 2)


      Продолжая работу над упражнениями 1го или 2го варианта, внутри кооперации IDBAccessRealization переименуйте диаграмму последовательности initialize2 в init, read2 -- в getCourseOfferingList, disconnect2 -- в close, update2 -- в updateStudent. Диаграмму составной структуры внутри внутри кооперации IDBAccessRealization переименуйте в Main. Лишние диаграммы -- delete2, create2 -- удалите. Теперь откройте находящуюся внутри подсистемы DBAccess диаграмму классов DBAccess. Поместите на неё классы Student, User и проведите к ним зависимости от класса DBAccess. Добавьте на диаграмму интерфейс IDBAccess. Для его отображения в виде "леденца" используйте контекстное меню -> Presentation Option -> Interface Ball. Проведите связь реализации от класса DBAccess к интерфейсу IDBAccess. Измените операции интерфейса IDBAccess, так, чтобы они совпадали с сигнатурами операций класса DBAccess, как они представлены на диаграмме 5.2.8. В частности тип CourseOffering[] следует заменить в сигнатурах на CourseOfferingList. Удалите из класса DBAccess в Model Explorer все операции. Затем продублируйте все операции интерфейса IDBAccess (контекстное меню -> Duplicate), перенесите созданные дубли в класс DBAccess, уберите лишние "2" из их имён. Удалите ассоциации между IDBAccess и классами User, Student. Проведите недостающие зависимости IDBAccess от классов User, Student, CourseOfferingList. Удалите лишнюю зависимость DBAccess от CourseOffering. В результате, диаграмма классов и структура подсистемы DBAccess должны быть похожи на изображённые на рисунках 5.2.8 и 5.2.9. Благодаря использованию механизма было затрачено меньше сил на обдумывание и моделирование, чем если бы подсистема проектировалась с чистого листа. Переходите к моделированию внутреннего поведения подсистемы DBAccess.


Рис. 5.2.8. UML-диаграмма классов подсистемы DBAccess

Рис. 5.2.8. UML-диаграмма классов подсистемы DBAccess (для вариантов 1 и 2)


Рис. 5.2.9. Структура подсистемы DBAccess в Model Explorer

Рис. 5.2.9. Структура подсистемы DBAccess в Model Explorer (для вариантов 1 и 2)

      Продолжая работу над упражнениями 1го или 2го варианта, продолжите проектирование подсистемы DBAccess. Внутри кооперации IDBAccessRealization находятся диаграммы последовательности, среди которых нам интересны: init (бывшая initialize), close (бывшая disconnect), getCourseOfferingList, updateStudent. Каждое взаимодействие будет описывать, что делают объекты подсистемы при вызове соответствующей операции. Реализацию операций, не перечисленных выше, мы моделировать не будем, а указанные четыре промоделируем.

      На диаграмме последовательности init левая линия жизни должна представлять объект db:DBAccess, входящее сообщение, принимаемое им, должно быть связано с операцией init. Добавьте нижнее потерянное сообщение (Lost Message) и укажите его тип -- возврат (контекстное меню -> Type(Reply)). В спецификации сообщения в поле Name укажите, что возвращается. UML-диаграмма примет вид, изображённый на рисунке 5.2.10. Взаимодействие описывает установление соединения с БД.


Рис. 5.2.10. UML-диаграмма последовательности, описывающая реализацию операции init() в подсистеме DBAccess

Рис. 5.2.10. UML-диаграмма последовательности, описывающая реализацию операции init() в подсистеме DBAccess (для вариантов 1 и 2)

            На диаграмме последовательности close левая линия жизни должна представлять объект db:DBAccess, входящее сообщение, принимаемое им, должно быть связано с операцией close. UML-диаграмма close должна иметь вид, изображённый на рисунке 5.2.11.


Рис. 5.2.11. UML-диаграмма последовательности, описывающая реализацию операции close() в подсистеме DBAccess

Рис. 5.2.11. UML-диаграмма последовательности, описывающая реализацию операции close() в подсистеме DBAccess (для вариантов 1 и 2)

      Выполняя упражнения 1го варианта, смоделируйте реализацию операции getCourseOfferingList. На диаграмме последовательности getCourseOfferingList левая линия жизни должна представлять объект db:DBAccess, а самая правая -- obj:CouseOffering. Вторая справа линия жизни -- объект list:CourseOfferingList. Свяжите найденное сообщение, принимаемое экземпляром DBAccess, с операцией getCourseOfferingList. Добавьте классу CourseOffering новые операции-сеттеры setDay(day:DayOfWeek):void, setPair(p:byte):void, setNumber(n:long):void, setSemester(s:byte):void. Проще всего это сделать, открыв диаграмму классов UniversityArtefacts, выбрав атрибут класса CourseOffering, вызвав его контекстное меню и указав Create Getter and Setter. Удалите примечание с диаграммы последовательности. Добавьте соответствующие сообщения-вызовы от объекта db:DBAccess к obj:CourseOffering и от db:DBAccess к rs:ResultSet на диаграмму последовательности. UML-диаграмма примет вид, изображённый на рисунке 5.2.12.


Рис. 5.2.12. UML-диаграмма последовательности, описывающая реализацию операции getCourseOfferingList() в подсистеме DBAccess

Рис. 5.2.12. UML-диаграмма последовательности, описывающая реализацию операции getCourseOfferingList() в подсистеме DBAccess (для варианта 1)

      Выполняя упражнения 2го варианта, смоделируйте реализацию операции updateStudent. На диаграмме последовательности updateStudent левая линия жизни должна представлять экземпляр db:DBAccess, остальные -- cOff[i]:CourseOffering, obj:Student, c:Connection и s:Statement. Ненужную линию жизни следует удалить, недостающие линии жизни следует создать. Свяжите найденное сообщение с операцией updateStudent. Добавьте недостающие операции-геттеры классу Student. Проще это сделать, открыв диаграмму классов UniversityArtefacts, выбрав атрибут класса Student, вызвав его контекстное меню и указав Create Getter and Setter. Свяжите третье сверху сообщение с вызовом операции getId():long, добавьте остальные недостающие сообщения и комбинированные фрагменты. Удалите примечание, ставшее ненужным. UML-диаграмма должна иметь вид, изображённый на рисунке 5.2.13.


Рис. 5.2.13. UML-диаграмма последовательности, описывающая реализацию операции updateStudent(st:Student) в подсистеме DBAccess

Рис. 5.2.13. UML-диаграмма последовательности, описывающая реализацию операции updateStudent(st:Student) в подсистеме DBAccess (для варианта 2)

      Проектирование подсистемы DBAccess завершено. Переходите к проектированию классов


Проектирование подсистемы BSAccess на основе механизма XMLRPCInterchange
(только для вариантов 3 и 4)


      Выполняя упражнения 3го или 4го варианта, осуществите проектирование подсистемы BSAccess. Переименуйте класс XMLRPCConnector внутри пакета BSAccess в класс BSAccess и назначьте ему стереотип «subsystem proxy» -- тем самым будет указано, что экземпляр этого класса будет принимать все сообщения, идущие внутрь подсистемы BSAccess. Классы ObjectToSend и ObjectToRecieve с помощью контекстного меню объедините c классом CourseOffering из пакета UniversityArtefacts (Merge to Model Element...) так, чтобы целью объединения был класс UniversityArtefacts::CourseOffering. Если результат объединения оказался не в том пакете, то перенесите его в пакет UniversityArtefacts. В подсистеме BSAccess переименуйте кооперацию XMLRPCInterchange2 в IBSAccessRealization, диаграмму классов XMLRPCInterchange2 -- в BSAccess, диаграмму пакетов XMLRPCInterchange2 в BSAccess. Добавьте кооперации IBSAccessRealization стереотип «interface realization» и удалите стереотип «mechanism».

      Продолжая выполнять упражнения 3го или 4го варианта, откройте диаграмму классов в пакете XMLRPCInterchange внутри архитектурного механизма RemoteInterchange. На диаграмме указано, что при реализации обмена данными с внешней системой используются элементы, описанные в пакетах java::net и org::apache::xmlrpc. Поэтому откройте диаграмму пакетов BSAccess из подсистемы, и убедитесь, что проведены зависимости (Import или Dependency) от подсистемы BSAccess к пакетам java::net и org::apache::xmlrpc. Если зависимостей нет, то добавьте их на диаграмму пакетов. При этом не забудьте, что стрелки зависимостей должны указывать в направлении от зависящего пакета к пакетам, от которых он зависит. Пакет-подсистема BSAccess является конкретизацией параметризованного пакета XMLRPCInterchange. Следует добавить пакет XMLRPCInterchange на диаграмму и провести к нему связь привязки шаблона (зависимость, помеченную стереотипом «bind»). Откройте спецификацию этой зависимости и в поле Name на вкладке General введите: <XMLRPCConnector -> BSAccess, ObjectToSend -> CourseOffering, ObjectToReceive -> CourseOffering, CustomTypeFactory -> CourseOfferingFactory, CustomSerializer -> CourseOfferingSerializer, CustomParser -> CourseOfferingParser> (переводы строк при работе под Windows можно вставить как Alt+Enter). В результате, диаграмма пакетов подсистемы BSAccess должны быть похожа на рисунок 5.2.14.


Рис. 5.2.14. UML-диаграмма пакетов подсистемы BSAccess

Рис. 5.2.14. UML-диаграмма пакетов подсистемы BSAccess (для вариантов 3 и 4)


      Продолжая выполнять упражнения 3го или 4го варианта, переименуйте внутри кооперации IBSAccessRealization диаграмму последовательности init2 в init, sendRequest2 -- в sendStudentData. Теперь откройте находящуюся внутри подсистемы BSAccess диаграмму классов BSAccess. Уберите с диаграммы дубль класса CourseOffering (не следует удалять класс из модели, нужно лишь скрыть лишнее его появление на диаграмме). Переименуйте классы: CustomTypeFactory в CourseOfferingFactory, CustomParser в CourseOfferingParser, CustomSerializer в CourseOfferingSerializer. Убедитесь, что отображены зависимости CourseOfferingParser и CourseOfferingSerializer от CourseOffering. Если это не так, то через контекстное меню класса, зависимость которого не видна, -> Related Elements -> Visualize Related Model Element... покажите зависимость на диаграмме. Повторно создавать зависимость не следует. Дважды один и тот же класс зависеть от другого не может. Добавьте на диаграмму интерфейс IBSAccess. Для его отображения в виде "леденца" используйте контекстное меню -> Presentation Option -> Interface Ball. Проведите связь реализации от класса BSAccess к интерфейсу IBSAccess. Удалите ассоциацию между IBSAccess и классом CourseOffering. Проведите недостающую зависимость IBSAccess от класса CourseOffering. Измените сигнатуры операций интерфейса IBSAccess в соответствии сигнатурами класса BSAccess, изображёнными на диаграмме 5.4.15 (недостающие операции добавьте, лишние удалите). Удалите из класса BSAccess все операции. Продублируйте операции интерфейса IBSAccess (контекстное меню -> Duplicate). Получившиеся дубли операций переместите в класс BSAccess. Удалите "2" в названиях перемещённых операций. Исправьте сигнатуру операции createCourseOffering в классе CourseOfferingParser. В результате, диаграмма классов и структура подсистемы должны стать похожи на изображённые на рисунках 5.2.15 и 5.2.16. Благодаря использованию механизма было затрачено меньше сил на обдумывание и моделирование, чем если бы подсистема проектировалась с чистого листа. Переходите к моделированию внутреннего поведения подсистемы BSAccess.


Рис. 5.2.15. UML-диаграмма классов подсистемы BSAccess

Рис. 5.2.15. UML-диаграмма классов подсистемы BSAccess (для вариантов 3 и 4)


Рис. 5.2.16. Структура подсистемы BSAccess в Model Explorer

Рис. 5.2.16. Структура подсистемы BSAccess в Model Explorer (для вариантов 3 и 4)

      Продолжая выполнять упражнения 3го или 4го варианта, допроектируйте подсистему BSAccess. Внутри кооперации IBSAccessRealization переименуйте диаграмму составной структуры XMLRPCInterchange Main2 в Main; диаграмму последовательности sendRequest2 -- в sendStudentData. Каждое взаимодействие будет описывать, что делают объекты подсистемы при вызове соответствующей операции. Вообще говоря, диаграмма последовательности должна быть создана для каждой операции интерфейса подсистемы. Мы можем создать пустые диаграммы для операций startTransferData, finishTransferData. Их реализацию мы моделировать не будем, а первые две промоделируем (в рамках 3го или 4го варианта).

      На диаграмме последовательности init левая линия жизни должна представлять объект cn:BSAccess, с назначенным стереотипом «subsystem proxy», входящее сообщение, принимаемое им, должно быть связано с операцией init. UML-диаграмма примет вид, изображённый на рисунке 5.2.17. Взаимодействие описывает инициализацию подсистемы перед первым обменом данными с внешней системой.


Рис. 5.2.17. UML-диаграмма последовательности, описывающая реализацию операции init() в подсистеме BSAccess

Рис. 5.2.17. UML-диаграмма последовательности, описывающая реализацию операции init() в подсистеме BSAccess (для вариантов 3 и 4)

      На диаграмме последовательности sendStudentDataAndSchedule левая линия жизни должна представлять cn:BSAccess, а самая правая -- действующее лицо Расчётная система. Шаблонная диаграмма описывает сложное взаимодействие, при котором не только пересылается объект данных во внешнюю систему, но и в ответ получается объект-результат. Моделируемая операция не предусматривает получение объекта извне, а значит, лишние линии жизни следует удалить из модели (из фрейма sendStudentData): result:CourseOffering, cp:CourseOfferingParser. Переименуйте линию жизни param:CourseOffering в cOff[i]:CourseOffering. Замените линию жизни XMLRPCServer на Расчётную систему. Свяжите найденное сообщение, принимаемое экземпляром cn:BSAccess, с операцией sendStudentData. Добавьте классу CourseOffering новые операции-геттеры getNumber():long, getPair():byte, getDay():DayOfWeek, getSemester():byte. Проще это сделать, открыв диаграмму классов UniversityArtefacts, выбрав атрибут класса CourseOffering, вызвав его контекстное меню и указав Create Getter and Setter. Удалите примечания с диаграммы последовательности. Добавьте комбинированный фрагмент loop и соответствующие сообщения (вызовы геттеров) от объекта cs:CourseOfferingSerializer к cOff[i]:CourseOffering на диаграмму последовательности. Добавьте нижнее потерянное сообщение (Lost Message) и укажите его тип -- возврат (контекстное меню -> Type(Reply)). В спецификации сообщения в поле Name укажите, что возвращается. UML-диаграмма примет вид, изображённый на рисунке 5.2.18.


Рис. 5.2.18. UML-диаграмма последовательности, описывающая реализацию операции sendStudentDataAndSchedule() в подсистеме BSAccess

Рис. 5.2.18. UML-диаграмма последовательности, описывающая реализацию операции sendStudentDataAndSchedule() в подсистеме BSAccess (для вариантов 3 и 4)

      Проектирование подсистемы BSAccess будем считать завершённым. Моделировать взаимодействие внутри подсистемы при вызовах операций startTransferData, finishTransferData мы не будем. Так как в ходе обработки этих вызовов не пересылаются сложные объекты, то эти взаимодействия будут ещё более упрощёнными версиями только что рассмотренной диаграммы. Объекты классов CourseOfferingFactory, CourseOfferingSerializer и CourseOffering не понадобятся. Просто будет передан запрос во внешнюю систему при посредничестве экземпляра XmlRpcClient, и также просто будет получен ответ.


Проектирование классов системы
(общее для всех вариантов)


      Проектирование классов включает следующие действия: детализацию проектных классов; уточнение операций и атрибутов; моделирование состояний для экземпляров классов; уточнение связей между классами. При детализации проектный класс может быть разбит на несколько классов из соображений, связанных с его реализацией в коде. Класс может быть удалён из модели, если его экземпляры являются лишь посредниками, не несущими содержательных обязанностей. Обязанности классов, определённые в при эскизном моделировании и документированные в виде операций анализа, преобразуются в операции, которые будут реализованы в коде. При этом каждой операции даётся имя, характеризующее её, определяется полная сигнатура операции, создаётся краткое описание операции, передающее смысл всех её параметров, определяется видимость операции, определяется область действия операции (операция экземпляра или операция класса, т. е. статическая). Если метод, реализующий операцию, реализует нетривиальный алгоритм, то он моделируется на диаграмме деятельности. Уточнение атрибутов классов заключается в следующем: задаются типы атрибутов, их множественность и значения по умолчанию (необязательно); задаётся видимость атрибутов; при необходимости определяются выводимые (вычисляемые на основе других данных) атрибуты, статические атрибуты, атрибут может быть разбит на несколько или наоборот, несколько атрибутов могут быть объединены в один.

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

      Затем производится уточнение связей между классами. Ассоциации, созданные при эскизном моделировании, которые соответствуют временным соединениям между объектами, заменяются на зависимости. У оставшихся ассоциаций проверяется, равноправны ли классы, участвующие в них. Ассоциации вида «часть-целое» явно моделируются как агрегации или композиции. Указываются мощности на полюсах, направления связей, типы множественных связей (set = unordered + unique, ordered set = ordered + unique, bag = unordered + nonunique, sequence = ordered + nonunique), квалификаторы. Классы ассоциаций преобразуются в обычные с помощью материализации связей. Аналогично, n-арные ассоциации могут быть трансформированы во вспомогательный класс связи с набором бинарных ассоциаций. Некоторые связи обобщения могут быть преобразованы путём метаморфозы подтипов.

      Осуществите проектирование классов системы регистрации. Создайте в пакете UniversityArtefacts диаграмму классов Student. Поместите класс Student на неё, перетащив из Model Explorer. С помощью контекстного меню -> Related Element -> Visualize Related Model Elements... отобразите на диаграмме классы FullTimeStudent и PartTimeStudent и связи обобщения между ними (заново проводить обобщения не следует!). Добавьте и уточните атрибуты и операции классов, чтобы придать диаграмме вид, схожий с рисунком 5.2.19. Геттеры и сеттеры удобно создавать, выделив атрибут и вызвав контекстное меню. Статические (подчёркнутые) атрибуты и операции задаются указанием области действия classifier (контекстное меню -> Model Element Properties -> Scope -> classifier). Типы long, int, boolean и string используются из набора стандартных типов UML, Date -- из пакета java::util.


Рис. 5.2.19. UML-диаграмма классов Student

Рис. 5.2.19. UML-диаграмма классов Student (для всех вариантов)

      Построим модель состояний экземпляров класса CourseOffering в соответствии с рисунком 5.2.20.

      Экземпляры класса CourseOffering должны по-разному обрабатывать вызовы операции addSchedule() в зависимости от того, отменен курс или нет, и в зависимости от количества уже зарегистрировавшихся студентов. Это признак сложного поведения и причина для создания диаграммы состояний. Добавьте классу CourseOffering диаграмму состояний LifeCycle (контекстное меню, Sub diagram -> New diagram -> State Machine Diagram). Создайте начальное псевдосостояние (Initial), финальное состояние (FinalState), композитное состояние Active, вложенное в него начальное псевдосостояние, подсостояния Open, Closed, Canceled и два псевдосостояния выбора (Choice). Чтобы внутри состояния можно было разместить подсостояния и/или внутренние переходы, в него следует добавить регион (контекстное меню -> Add Horizontal Region). Соедините состояния внешними переходами, как указано на рисунке 5.2.20. Переходы внутри Active следует пометить как локальные (вкладка General спецификации перехода, поле Kind).

      Переходу может быть добавлено событие (триггер), указываемое до слэша, действие, указываемое после слэша, сторожевое условие, записываемое между триггером и действием в прямоугольных скобках. События addSchedule, removeSchedule, destroy, close, cancel, getNumber и setNumber добавляйте на вкладку Triggers спецификаций переходов. Типы всех событий -- события вызова (Call Trigger). Их следует привязать к одноимённым операциям класса CourseOffering. Действия при переходах укажите в поле Effect, текст действия укажите в имени создаваемой деятельности. Сторожевые условия на переходах укажите в поле Guard на вкладке General спецификации перехода. Чтобы добавить действие по входу в состояние, откройте спецификацию состояния, перейдите на вкладку General и создайте действие в поле Entry. Внутренние переходы (не путать с локальными!) создаются на вкладке Internal Transitions спецификации региона, созданного внутри состояния. Вложенный регион следует создать не только в Active, но и в Open. Недостающие операции класса CourseOffering следует добавить в него. То же касается недостающих атрибутов: CourseOffering::isClosed:boolean, CourseOffering::isCanceled:boolean


Рис. 5.2.20. UML-диаграмма состояний Lifecycle класса CourseOffering

Рис. 5.2.20. UML-диаграмма состояний Lifecycle класса CourseOffering (для всех вариантов)

      К проектированию классов также относится моделирование нетривиальных реализаций операций (т. е. методов). Например, тривиальными являются операции-геттеры. Нетривиальная операция содержит в своём методе ветвления и/или циклы. В нашу модель внутрь проектного класса RegistrationForm можно добавить диаграмму деятельности (Activity Diagram) createSchedule (см. рис. 5.2.22), а также внутрь проектного класса DBAccess -- диаграмму деятельности updateStudent (см. рис. 5.2.21). В вариантах 1 и 4 следует построить диаграмму деятельности для моделирования операции DBAccess::updateStudent. В вариантах 2 и 3 следует построить диаграмму деятельности для моделирования операции RegistrationForm::createSchedule. При построении следует использовать структурированные узлы Conditional Node with Regions и Loop Node with Regions. Псевдокод внутрь узла действия можно ввести, если выделить его и переименовать (F2). Переводы строк в псевдокоде можно ввести с помощью Alt+Enter. Выравнивание псевдокода осуществляется с помощью контекстного меню Presentation Options -> Caption Placement.

Рис. 5.2.21. UML-диаграмма деятельности для операции DBAccess::updateStudent

Рис. 5.2.21. UML-диаграмма деятельности для операции DBAccess::updateStudent (для вариантов 1 и 4)

Рис. 5.2.22. UML-диаграмма деятельности для операции RegistrationForm::createSchedule

Рис. 5.2.22. UML-диаграмма деятельности для операции RegistrationForm::createSchedule (для вариантов 2 и 3)

      Уточните связи между классами на диаграмме Design VOPC RegisterForCourses проектной реализации варианта использования «Зарегистрироваться на курсы». Добавьте на диаграмму отсутствующие элементы и связи. Уточните ассоциации, указав, где нужно, что они являются агрегациями или композициями. Укажите направления ассоциаций. Обратите внимание на двунаправленные ассоциации (со стрелкам на обоих концах). Чтобы они так отображались, следует сделать настройку (контекстное меню -> Presentation Options -> Show Arrows -> Show All Arrows and Crosses). В учебном плане студента хранятся ссылки на курсы, включённые в него, и каждый курс хранит массив ссылок на учебные планы, в которые он включён. Добавьте квалификатор на композицию между Student и Schedule (контекстное меню полюса ассоциации -> Qualifier...). Добавление квалификатора меняет мощность на противоположном полюсе ассоциации. Внесите исправление мощности. Укажите начальные значения атрибутам numStudents, isClosed, isCanceled класса CourseOffering. Уточните обобщения (осуществите метаморфозу подтипов). При эскизном моделировании мы определили, что бывают студенты дневного отделения и студенты вечернего отделения, и создали иерархию наследования. Хороша ли такая модель, в случае перевода студента с одного отделения на другое? При переводе требуется создать студента нового типа, скопировать в него данные (значения слотов атрибутов класса Student), а затем исходный объект удалить. Эффективнее было бы общую для дневных и вечерних студентов часть не трогать, а менять только то, что зависит от отделения. Выделите эту меняющуюся часть в абстрактный класс Classification, проведите обобщения к его классам-наследникам FullTimeClassification и PartTimeClassification -- переименованным бывшим классам FulltimeStudent и PartTimeStudent. Класс Student сделайте конкретным. Убедитесь, что в модели не осталось прежних обобщений, связывающих Student c FullTimeClassification и PartTimeClassification (если они остались, то удалите их из Model Explorer). Результат на уточнённой диаграмме классов Design VOPC RegisterForCourses (рис. 5.2.23).


Рис. 5.2.23. Уточнённая диаграмма классов Design VOPC RegisterForCourses

Рис. 5.2.23. Уточнённая диаграмма классов Design VOPC RegisterForCourses (для всех вариантов)

      Упражнения по проектированию элементов системы на этом завершены. Мы рассмотрели на примерах как осуществляется каждая технологическая операция в рамках него. Переходите к завершающему упражнению по моделированию схемы реляционной базы данных.


Упражнение 5.3. Создание UML-диаграммы классов, моделирующей схему реляционной базы данных

(общее для всех вариантов)


      Если среди проектных классов есть устойчивые, чьи экземпляры должны сохраняться в периодах между запусками системы, следует обеспечить сохранение их в базе данных (например, реализовав подсистему обеспечения устойчивости на базе JDBC) и создать схему реляционной базы данных. Фактически, следует отобразить объектную модель в реляционную. Одна из стратегий при этом состоит в том, что для каждого устойчивого класса создаётся собственная таблица. Атрибуты класса переводятся в столбцы таблицы. Атрибут-идентификатор становится первичным ключом (если в составе идентификатора несколько атрибутов, то первичный ключ будет составным). При объектно-реляционном отображении ассоциации между классами переводятся в связи между таблицами, накладывающие ограничения целостности на записи таблиц. Связи между таблицами могут быть идентифицирующими и не идентифицирующими. Идентифицирующая связь указывает, что внешний ключ включает в себя часть первичного ключа, то есть ключ родительской записи является частью ключа дочерних записей. В некоторых случаях для ассоциации (например, * к *) требуется создавать дополнительную таблицу, хранящую соединения между объектами. Пример такой служебной таблицы -- TablePrimaryCourse. Исходные классы Schedule и CourseOffering связаны ассоциацией (* к 0..4). Значит, чтобы хранить сведения о соответствующих связях записей из таблиц TableSchedule и TableCourseOffering, следует завести связанную с ними таблицу TablePrimaryCourse. Для отображения обобщений используются разные способы. Один из них -- "отдельная таблица для каждого класса" из иерархии наследования. В этом случае у всех получившихся таблиц будет один и тот же первичный ключ, который в таблицах подклассов будет также внешним ключом. Другой способ -- "одна таблица для всей иерархии наследования". В этом случае создаётся таблица, хранящая записи об экземплярах всех конкретных (не абстрактных) классов, входящих в иерархию. Такая таблица получается "разрежённой", так как в записях некоторые поля остаются не заполненными (так как они относятся к экземплярам других подклассов). Примером такой единой таблицы является TableStudent (в её записях хранятся сведения о студентах и их классификациях: "дневных" и "вечерних").

      Для изображения схем реляционных баз данных в виде диаграмм есть специальные нотации. Но мы можем использовать UML, а конкретно, диаграмму классов, чтобы изобразить схему базы данных графически. Таблицы на диаграмме классов изображаются классами со стереотипом «table». Связи между таблицами (по которым устанавливается соответствие значений первичного ключа записей одной таблицы значениям внешнего ключа другой таблицы) моделируются с помощью ассоциаций. Заметим, что эти ассоциации двунаправленные, так как по записям любой из связанных таблиц можно найти соответствующие записи другой таблицы. Связь между таблицами отображается как композиция, если требуется указать на зависимость по существованию (каскадированное удаление). Так, при удалении родительской записи (например, из таблицы TableStudent) должны быть удалены дочерние записи (из таблицы TableSchedule).

      Осуществите проектирование схемы реляционной базы данных. Продублируйте рекурсивно пакет UniversityArtefacts. Полученный дубль переименуйте в Database Schema и переместите в корень Design Model. Удалите из пакета Database Schema всё лишнее (все операции всех классов, диаграмму состояний, связи зависимости, обобщения, перечислимые типы). Должны остаться только классы (с атрибутами) и ассоциации. Назначьте пакету стереотип «schema». Диаграмму классов Student2, находящуюся в пакете, удалите. Диаграмму классов UniversityArtefacts2 переименуйте в DataBase Schema. Убедитесь, что на этой диаграмме находятся классы Student, Schedule, CourseOffering, Course, Professor, User. Добавьте классам, находящимся на диаграмме, стереотип «table» и уберите любые другие стереотипы, если они остались. Переименуйте классы, добавив к именам приставку Table. Добавьте класс (таблицу) TableStaticValues для хранения значений статических атрибутов. Добавьте классы (таблицы) TablePrimaryCourse и TableCourseRequisites для хранения соединений * к *. Добавьте недостающие атрибуты и их стереотипы. Уберите квалификатор и исправьте мощность на ассоциации между TableStudent и TableSchedule (полюс рядом с TableSchedule). Новое значение мощности -- *. См. рисунок 5.3.1.

      Эту схему можно использовать для хранения сведений о студентах, учебных планах, читаемых курсах, дисциплинах, профессорах, пользователях. Столбцы для хранения выводимых атрибутов можно не заводить. Перечислимые типы заменяются на подходящие целочисленные (из-за того, что нет уверенности в том, будет ли поддерживать пользовательские перечислимые типы СУБД). При отображении обобщения в реляционную модель нами применена стратегия "Одна таблица для всей иерархии наследования". Согласно ей для трёх классов Classification, FullTimeClassification и PartTimeClassification заводится одна таблица. Одновременно производится слияние этой единой таблицы с таблицей TableStudent. Получается, что данные обоих типов студентов хранятся в одной таблице, просто некоторые поля в каждой записи не заполнены в зависимости от типа студента. Использованные стратегии упрощают схему, позволяют обойтись сравнительно малым количеством таблиц и связей. Композиции на нашей схеме имеют следующий смысл -- связанная запись из подчинённой таблицы должна быть удалена при удалении записи из основной таблицы. Агрегации не используются на диаграммах классов, моделирующих схемы реляционных баз данных.


Рис. 5.3.1. UML-диаграмма классов DataBase Schema

Рис. 5.3.1. Диаграмма классов DataBase Schema (для всех вариантов)

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


Предупреждение


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

  

© Кафедра системного программирования ВМК МГУ.

Обновлено: 12.XI.2020