Для наглядного представления работы (поведения, реакции на действия пользователей) системы рекомендуется разработать и согласовать с заказчиком прототипы экранов и окон пользовательского интерфейса. В целях иллюстрации на рис. 12.17 приведена копия экрана ИСКРА-ПУТЬ, служащая хорошим дополнением к диаграмме декомпозиции на рис. 12.16.
Рис. 12.17. Меню программы ИСКРА-ПУТЬ и диалоговое окно «Нормативы»
Вопросы для самопроверки
1. Перечислите элементы диаграммы состояний.
2. Чем отличается состояние от перехода?
3. Назовите разновидности состояний и переходов.
4. В чем отличие триггерного перехода от нетриггерного?
5. Назовите основные правила и рекомендации по разработке диаграмм состояний.
Лекция № 13. ДИАГРАММЫ ВЗАИМОДЕЙСТВИЯ 13.1. Общие сведения 13.2. Назначение и состав диаграммы кооперации 13.3. Назначение и состав диаграммы последовательности 13.4. Рекомендации по разработке диаграмм взаимодействия 13.5. Примеры построения диаграмм взаимодействия 13.6. Пакеты 13.1. Общие сведения Реализация отдельного варианта использования требует участия и взаимодействия определенных экземпляров актеров и классов. Наиболее подходящий инструмент для описания такого взаимодействия – это диаграммы кооперации и последовательности, которые, по сути, отображают одну и ту же информацию. В связи с этим большинство Case-средств позволяет после построения одной из диаграмм автоматически получить другую, а также выполнять синхронизацию этих диаграмм между собой.
13.2. Назначение и состав диаграммы кооперации Диаграмма кооперации прежде всего отображает структуру взаимодействия и содержит следующие элементы [23–26]:
экземпляры актеров и классов, участвующих в реализации варианта использования;
ассоциации между экземплярами актеров и классов;
сообщения, передаваемые между экземплярами актеров и классов.
На диаграмме эти элементы отображаются стандартно (экземпляр актера – человечком, экземпляр класса (объект) – прямоугольником или графическим стереотипом класса анализа). В то же время следует помнить, что экземпляр – это конкретная реализация соответствующей сущности (актера, класса, узла и т. д.). Чтобы учесть этот нюанс на диаграммах, имя экземпляра подчеркивается и может отображаться в следующих вариантах:
Имя объекта : Имя класса (например, Вася : Программист);
: Имя класса (например, : Программист) – анонимный объект;
Имя объекта (например, Вася) – предполагается, что имя класса известно;
Имя объекта : (например, Вася :) – объект-сирота. Считается, что имя класса неизвестно.
Для объектов, кроме имени, могут указываться также некоторые важные для данной кооперации атрибуты и их значения.
Взаимодействие между экземплярами актеров и объектами моделируется посредством сообщений, отображаемых над ассоциациями. Сообщение (англ. message) – это спецификация факта передачи информации между сущностями с ожиданием выполнения определенных действий со стороны принимающей сущности. Сущность, отправляющую сообщение, называют клиентом, а принимающую – сервером. Таким образом, сообщения не только передают некоторую информацию, но и требуют или предполагают выполнения сервером определенных действий или передачу (возврат) клиенту необходимой информации. Если принимающей сообщение сущностью является объект, то оно представляет собой операцию (метод) объекта-сервера. Прием сообщения обычно трактуется, как возникновение события на сервере.
Сообщения изображаются стрелкой с обязательным указанием направления (остриё стрелки указывает на сервер) и его спецификации.
Сообщения могут быть следующих видов:
– синхронное сообщение (передача управления). Клиент посылает сообщение серверу и ждет, пока тот примет и обработает сообщение. Как правило, в кооперации один объект передает синхронное сообщение второму, второй – третьему и т. д., образуя вложенный поток сообщений. В любом случае клиент, инициирующий поток сообщений, должен дождаться завершения вложенного потока, т. е. возврата управления. Это самый распространенный тип сообщений;
– асинхронное сообщение. Клиент посылает сообщение серверу и, не дожидаясь ответа, продолжает выполнять свою работу дальше;
– возвращающее сообщение (возврат управления), обозначающее возврат значения или управления от сервера обратно клиенту. Стрелки этого вида зачастую отсутствуют на диаграммах кооперации, поскольку неявно предполагается их существование после окончания процесса выполнения операции.
В отдельных случаях объект может посылать сообщения самому себе (вызывать собственные методы и действия), инициируя так называемые рефлексивные сообщения.
Спецификация сообщения может указываться в двух форматах:
предшествующие сообщения / [сторожевое условие] номер сообщения : стереотип;
предшествующие сообщения / [сторожевое условие] номер сообщения : переменная := имя сообщения (список аргументов)
Предшествующие сообщения (их номера или идентификаторы) записываются через запятые и указывают, что данное сообщение не может быть передано, пока не будут посланы все предшествующие сообщения своим адресатам.
Сторожевое условие – обычное булевское выражение, означающее возможность посылки сообщения. Используется для ветвления потока сообщений.
Порядковый номер указывает на последовательность посылки сообщений. Например, {1, 2, 3, 3.1, 3.2, 3.3, 4, 5}. Сообщения с номерами {1, 2, 3, 4, 5} посылаются объектом, инициализирующим взаимодействие, а сообщения {3.1, 3.2, 3.3} – другим объектом, после получения им сообщения с номером 3.
В UML предусмотрены некоторые стандартные действия, выполняемые в ответ на получение соответствующего сообщения. Они могут быть явно указаны на диаграмме в виде стереотипа рядом с сообщением, к которому они относятся. Стандартными стереотипами, определенными в UML, являются следующие:
«call» (англ. – вызвать) – синхронное сообщение, требующее выполнения операции принимающего объекта;
«create» (англ. – создать) – синхронное сообщение, требующее создания объекта;
«destroy» (англ. – уничтожить) – синхронное сообщение с требованием уничтожить соответствующий объект;
«send» (англ. – послать) – асинхронное сообщение, обозначающее посылку сигнала серверу;
«return» (англ. – возвратить) – возвращающее сообщение.
Переменная (атрибут), которая будет содержать значение, возвращаемое в результате обработки сообщения.
Имя сообщения (обязательный параметр) – имя вызываемой операции объекта-получателя.
Список аргументов – список аргументов, разделенных запятыми и передаваемых для выполнения операции.
Порядковый номер, а также стереотип или имя сообщения, являются обязательными параметрами спецификации.
Примеры сообщений:
1, 2, 3.2 / 5 : звук(частота) – сообщение с номером 5 должно посылаться при условии предшествующей посылки сообщений с номерами 1, 2, 3.2 и требует подачи звукового сигнала с заданной частотой;
[x = 0] 5 : ошибка(‘деление на ноль’) – сообщение с номером 5 должно посылаться при условии x = 0 и требует обработки соответствующей ошибки;
5 : «create» – сообщение, предписывающее создание объекта;
5 : properties := getProperties() – вызов метода, возвращающего системные параметры компьютера в переменную properties.
13.3. Назначение и состав диаграммы последовательности Диаграмма последовательности вместо структуры взаимодействия более наглядно показывает его временной аспект. Она имеет два измерения. Одно измерение – слева направо в виде вертикальных линий, каждая из которых представляет линию жизни отдельного экземпляра актера или объекта, участвующего во взаимодействии. Крайним слева на диаграмме изображается экземпляр актера или объект, который является инициатором взаимодействия. Правее изображается другой объект, который непосредственно взаимодействует с первым и т. д. Таким образом, все сущности на диаграмме образуют некоторый порядок, определяемый временной активностью экземпляров актеров и объектов при взаимодействии друг с другом.
Второе измерение – вертикальная временная ось, направленная сверху вниз. Начальному моменту времени соответствует самая верхняя часть диаграммы. При этом масштаб на оси времени не указывается, поскольку диаграмма последовательности моделирует лишь временную упорядоченность взаимодействий типа «раньше-позже».
На диаграмме последовательности отображаются те же элементы, что и на диаграмме кооперации (экземпляры актеров, объекты и сообщения), а также ряд специфичных элементов, перечисленных ниже [23–26].
Линия жизни (англ. lifeline) отображается пунктирной вертикальной линией, ассоциированной с соответствующим объектом. Линия жизни служит для обозначения периода времени, в течение которого объект может потенциально участвовать во взаимодействии. Если он существует в течение всего взаимодействия, то и его линия жизни должна продолжаться от самой верхней части диаграммы до самой нижней.
Не обязательно создавать все объекты в начальный момент времени. Отдельные объекты в системе могут создаваться по мере необходимости, существенно экономя ресурсы системы и повышая ее производительность. В этом случае объект изображается не в верхней части диаграммы, а в том месте, где он создается. Для обозначения факта уничтожения объекта в UML используется специальный символ X (рис. 13.1).
Рис. 13.1. Пример обозначения линии жизни и символа уничтожения объекта
В процессе взаимодействия одни объекты могут находиться в активном состоянии, непосредственно выполняя определенные действия, или в состоянии пассивного ожидания сообщений от других объектов. Чтобы явно выделить подобную активность объектов, на диаграмме можно использовать элемент фокус управления (англ. focus of control). Он изображается в форме вытянутого узкого прямоугольника, верхняя сторона которого обозначает начало получения фокуса управления объекта (начало активности), а нижняя сторона – окончание фокуса управления (окончание активности). Условные операторы, циклы, рекурсия и вызов собственных методов (отправка рефлексивных сообщений) инициируют вложенные потоки управления у одного и того же объекта, что можно отобразить на диаграмме с помощью вложенных фокусов управления (рис. 13.2).
Рис. 13.2. Способы отображения фокуса управления
На диаграмме последовательности более наглядно, чем на диаграмме кооперации, можно показать ветвление потока управления (рис. 13.3).
Рис. 13.3. Пример ветвления потока управления
13.4. Рекомендации по разработке диаграмм взаимодействия При разработке диаграмм следует придерживаться следующих правил и рекомендаций [23–26].
1. Для выбранного варианта использования необходимо перенести с диаграммы классов анализа все участвующие в нем классы, а с диаграммы вариантов использования – актеров.
2. На диаграмме кооперации между классами следует отобразить ассоциации, перенесенные с диаграммы классов анализа, а также добавить ассоциации, связывающие актеров с граничными классами.
3. Основной и альтернативные потоки событий следует показывать соответствующими сообщениями с использованием сторожевых условий.
4. На стадии анализа имена сообщениям можно давать произвольно (например, «Записать данные о клиенте») или в виде стереотипов. В дальнейшем (на стадии проектирования) имена сообщений должны соответствовать методам классов.
5. Имена сущностей на диаграммах (экземпляры актеров и объекты) должны быть подчеркнуты и обозначены соответствующим образом.
6. На диаграммах последовательности символ уничтожения объектов следует задавать только для тех объектов, которые во время взаимодействия действительно уничтожаются. Экземпляры актеров и объекты классов сущностей (долгоживущая информация), как правило, существуют до начала и после окончания взаимодействия. Для них символ уничтожения не показывается. Объекты граничных и управляющих классов, напротив, в большинстве случаев создаются на момент взаимодействия и по его окончанию уничтожаются. В связи с этим для них требуется отображать символ уничтожения.
Проектировщикам диаграмма кооперации может дать богатый материал о распределении обязанностей между объектами. Так, например, если диаграмма напоминает форму звезды, то можно сделать вывод, что система сильно зависит от центрального объекта. В этом случае стоит подумать о более равномерном распределении обязанностей между участниками взаимодействия. Или, наоборот, если в системе хранится и обрабатывается секретная информация, то большинство сообщений должно проходить через ядро безопасности – классы, отвечающие за идентификацию, аутентификацию и, возможно, шифрование / расшифрование сообщений.
Диаграмма последовательности четко отображает временной аспект взаимодействия. В связи с этим она представляется удобным инструментом для отслеживания порядка посылки и обработки сообщений.
13.5. Примеры построения диаграмм взаимодействия На рис. 13.4 показана упрощенная диаграмма кооперации, а на рис. 13.5 – диаграмма последовательности, показывающие процесс загрузки данных из таблицы с сервера БД (кэширование).
Рис. 13.4. Пример диаграммы кооперации
Рис. 13.5. Пример диаграммы последовательности
Табличные данные после загрузки заносятся в атрибут data объекта propertyTable, представляющий собой двумерный массив объектов Object[][].
Во взаимодействии участвуют следующие объекты:
Object – инициирует загрузку данных;
propertyTable – хранит описание таблицы и ее полей, а также загруженные данные в атрибуте data;
connectDB – отвечает за установку, поддержку и закрытие соединения с БД;
statement – выполняет и возвращает результаты запросов к БД.
Инициировать загрузку могут объекты разных классов, поэтому объект Object не сопоставлен с каким-либо классом. Остальные объекты относятся к конкретным классам. После двоеточия у этих объектов показана вложенность по пакетам, а после последней точки – имя класса, экземпляром которого они являются.
Во взаимодействии следующая последовательность сообщений (вызова методов):
Object инициирует загрузку данных getData();
создается соединение с БД в виде объекта connectDB посредством вызова конструктора класса ConnectDB. Созданный объект запоминается в переменной connect;
создается объект statement для выполнения запросов к БД и запоминается в переменной statement;
посредством вызова метода checkChangeData() проверяется признак изменения данных на сервере. Если данные изменились, то;
o из атрибута data объекта propertyTable удаляются старые данные clear();
o выполняется запрос к БД executeQuere() и запрошенные данные запоминаются в переменной rs;
o в цикле while() записи из переменной rs переносятся в атрибут data с помощью метода add();
удаляется объект statement – на диаграмме указано стереотипное сообщение «destroy»;
закрывается соединение с БД closeConnect().
В качестве иллюстрации правил построения диаграммы последовательности на ней показаны:
два варианта создания объекта – с помощью конструктора () для объекта connectDB и с помощью стереотипного сообщения «create» для объекта statement;
два варианта уничтожения объекта – с помощью вызова деструктора closeConnect() для объекта connectDB и с помощью стереотипного сообщения «destroy» для объекта statement;
два варианта вызова методов, возвращающих значения – вызов конструктора объекта connectDB с занесением результата (созданного объекта) в переменную connect с помощью двух сообщений и выполнением запроса к БД executeQuere() с занесением результата в переменную rs с помощью одного сообщения.
13.6. Пакеты В результате разработки диаграмм классов анализа, кооперации и последовательности определяется набор основных классов, определяющих внутреннюю архитектуру системы. На стадии анализа выявляются основные характеристики классов (атрибуты) и их поведение (методы). Выявленные классы должны быть распределены по пакетам (англ. package) – сущностям, используемым для семантической группировки других сущностей. Отображение пакета в UML см. на рис. 13.6.
Рис. 13.6. Пакет
Допускается (как правило, имеет место) вложенность пакетов, т. е. пакет может состоять из подпакетов, подпакеты – из подподпакетов и т. д. Содержимое пакета может отображаться двумя способами (рис. 13.7).
Рис. 13.7. Способы отображения содержимого пакетов
Между пакетами могут указываться отношения наследования и зависимости (рис. 13.8).
Рис. 13.8. Примеры отношений между пакетами
Отношение наследования означает, что дочерний пакет (WindowsGUI или MacGUI) включает в себя все элементы родительского (GUI) и допускает определение новых (дополнительных) элементов и/или переопределение существующих. Зависимость между пакетами означает, что класс, входящий в зависимый пакет (table), связан отношением с классом, определенным в независимом пакете (db). Отношение зависимости часто помечают стереотипом «import».
При группировке классов по пакетам можно использовать следующие подходы [29]:
группировать классы по стереотипу. В одном пакете будут находиться классы сущностей, в другом – граничные, в третьем – управляющие;
группировать по семантической однородности. Например, пакет «Безопасность» будет содержать все классы, отвечающие за безопасность системы;
группировать по подсистемам (по функциональности). Например, при разработке большой и сложной системы, состоящей из нескольких взаимодействующих подсистем;
комбинировать три подхода, описанных выше. Пример комбинации подходов с возможными способами указания вложенности элементов и связей между ними показан на рис. 13.9.
Рис. 13.9. Фрагмент диаграммы пакетов
На рис. 13.9 на верхнем уровне используется группировка по функциональности. Так, пакет ru состоит из трех подсистем1 (iskraPUT – подсистема расчета и ведения допускаемых скоростей, iskraPTR – подсистема тягово-экономических расчетов и iskraSMI – подсистема расчета станционных и межпоездных интервалов) и пакета library, содержащего подпакеты и классы общего назначения. В подпакетах db, table, field, window, panel и obrData классы сгруппированы по семантической однородности.
Связи между классами, входящими в разные пакеты, на диаграмме могут обозначаться в общем виде (на уровне пакетов с использованием зависимостей) или непосредственно между классами (например, на рис. 13.9 между классами WindowNormat и InternalWindowDB).
В пределах одного уровня вложенности имена элементов (подпакетов и классов) должны быть уникальными. Допускается в разных пакетах определять подпакеты и классы с одинаковыми именами (например, подпакет window в пакетах iskraPUT и library). В дальнейшем (на других диаграммах и при непосредственном программировании), чтобы избежать разночтений, у одноименных подпакетов и классов указывается полная спецификация имен, включая все пакеты верхнего уровня. В имени вложенность обозначается с использованием «.» или «::» (например, ru.iskraPUT.window.WindowNormat или ru::library::window::InternalWindowDB).
Ввиду отсутствия в UML спецификации диаграмм пакетов, но очевидной их необходимости, разработчики Case-средств предлагает различные варианты их отображения.
Распределение классов по пакетам позволяет:
добиться лучшей структурной организации модели (сильнее формализовать модель);
более четко и продуманно распределить обязанности между отдельными разработчиками или их командами;
упростить повторное использование отдельных пакетов в других проектах, так как связи между пакетами, как правило, минимальны.
1В UML система, подсистема и модель являются разновидностями пакета.