Создание диаграммы состояний для классов и диаграммы компонентов
Рекомендуемое содержание пункта «Создание диаграммы состояний для классов и диаграммы компонентов». В этом пункте приводится и описывается последовательность действий по созданию диаграммы состояний для классов и диаграммы компонентов для выбранного прецедента информационной подсистемы (см. соответствующие лабораторные занятия).
Диаграммы состояний определяют все возможные состояния, в которых может находиться конкретный объект, а также процесс смены состояний объекта в результате наступления некоторых событий. Существует много форм диаграмм состояний, незначительно отличающихся друг от друга семантикой.
На рисунке 2.17 приводится пример диаграммы состояний для банковского счета (account). Можно также наблюдать процесс перехода счета из одного состояния в другое. Например, если клиент требует закрыть счет, он переходит в состояние «закрыт». Требование клиента называется событием (event), именно такие события и вызывают переход из одного состояния в другое.
Рисунок 2.17 – Диаграмма состояний для класса Account
Если клиент снимает деньги со счета, он может перейти в состояние «Превышение кредита». Это происходит только в том случае, если баланс по счету меньше нуля, что отражено условием [отрицательный баланс] на нашей диаграмме. Заключенное в квадратных скобках условие (guardcondition) определяет, когда может произойти переход из одного состояния в другое.
На диаграмме имеются два специальных состояния - начальное (start) и конечное (stop). Начальное состояние выделено черной точкой, оно соответствует состоянию объекта, когда он только что был создан. Конечное состояние обозначается черной точкой в белом кружке, оно соответствует состоянию объекта непосредственно перед его уничтожением.
На диаграмме состояний может быть одно и только одно начальное состояние. В то же время может быть столько конечных состояний, сколько вам нужно, или их может не быть вообще. Когда, объект находится в каком-то конкретном состоянии, могут выполняться различные процессы. В нашем примере при превышении кредита клиенту посылается соответствующее сообщение. Процессы, происходящие в тот момент, когда объект находится в определенном состоянии, называются действиями (actions).
С состоянием можно связывать следующие данные: деятельность, входное действие, выходное действие и событие. Рассмотрим каждый из них в контексте диаграммы состояний для класса Account банковской системы.
Деятельность(activity) – это поведение, реализуемое объектом, пока он находится в данном состоянии. Например, когда счет находится в состоянии «Закрыт», происходит возврат кредитной карточки пользователю. Деятельность - это прерываемое поведение. Оно может выполняться до своего завершения, пока объект находится в данном состоянии, или может быть прервано переходом объекта в другое состояние. Деятельность изображают внутри самого состояния; ее обозначению должно предшествовать слово do (делать) и слэш.
Входное действие(entryaction) – это поведение, которое выполняется, когда объект переходит в данное состояние. Как только счет в банке переходит в состояние «Превышен счет» (см.рисунок2.17), выполняется действие «Временно заморозить счет» независимо от того, откуда объект перешел в это состояние. Таким образом, данное действие осуществляется не после того, как объект перешел в это состояние, а скорее как часть этого перехода. В отличие от деятельности входное действие рассматривается как непрерываемое.
Входное действие также показывают внутри состояния, его обозначению предшествуют слово entry (вход) и косая черта.
Выходное действие(exitaction) подобно входному действию. Однако оно осуществляется как составная часть процесса выхода из данного состояния. В нашем примере при выходе объекта account из состояния «Превышен счет» выполняется действие «Разморозить счет». Оно является частью процесса такого перехода. Как и входное, выходное действие является непрерываемым.
Выходное действие изображают внутри состояния, его описанию предшествуют слово exit (выход) и косая черта.
Поведение объекта во время деятельности, при входных и выходных действиях, может включать отправку события другому объекту. Например, объект account (счет) может посылать событие объекту cardreader (устройство чтения карты). В этом случае описанию деятельности, входного или выходного действия предшествует знак «^». Соответствующая строка на диаграмме выглядит как
Do: ^Цель. Событие (Аргументы)
Здесь Цель – это объект, получающий событие, Событие – это посылаемое сообщение, а Аргументы являются параметрами посылаемого сообщения.
Деятельность может также выполняться в результате получения объектом некоторого события. Например, объект Account может быть в состоянии «Открыто». При получении некоторого события выполняется определенная деятельность.
Переходом(transition) называется перемещение объекта из одного состояния в другое. На диаграмме все переходы изображают в виде стрелки, начинающейся на первоначальном состоянии и заканчивающейся последующим.
Переходы могут быть рефлексивными. Объект может перейти в то же состояние, в котором он внастоящий момент находится. Рефлексивные переходы изображают в виде стрелки, начинающейся и завершающейся на одном и том же состоянии.
У перехода существует несколько спецификаций. Они включают события, аргументы, ограждающие условия, действия и посылаемые события. Рассмотрим каждое из них в контексте примера банковской системы.
Событие(event) - это то, что вызывает переход из одного состояния в другое. В нашем примере событие «Клиент требует закрыть» вызывает переход счета из открытого в закрытое состояние. Событие размещают на диаграмме вдоль линии перехода.
На диаграмме для отображения события можно использовать как имя операции, так и обычную фразу. В нашем примере события описаны обычными фразами. Если нужно использовать операции, то событие «Клиент требует закрыть» можно было бы назвать RequestClosure ( ).
У событий могут быть аргументы. Так, событие «Сделать вклад», вызывающее переход счета из состояния «Превышен счет» в состояние «Открыто», может иметь аргумент Amount (Количество), описывающий сумму депозита.
Большинство переходов должны иметь события, так как именно они, прежде всего, заставляют переход осуществиться. Тем не менее, бывают и автоматические переходы, не имеющие событий. При этом объект сам перемещается из одного состояния в другое со скоростью, позволяющей осуществиться входным действиям, деятельности и выходным действиям.
Ограждающие условия (guardconditions) определяют, когда переход может или не может осуществиться. В нашем примере событие «Сделать вклад» переведет счет из состояния «Превышение счета» в состояние «Открыто», но только при условии, если баланс будет больше нуля. В противном случае переход не осуществится.
Ограждающие условия изображают на диаграмме вдоль линии перехода после имени события, заключая их в квадратные скобки.
Ограждающие условия задавать необязательно. Однако если существует несколько автоматических переходов из состояния, необходимо определить для них взаимно исключающие ограждающие условия. Это поможет читателю диаграммы понять, какой путь перехода будет автоматически выбран.
Действие (action), как уже говорилось, является непрерываемым поведением, осуществляющимся как часть перехода. Входные и выходные действия показывают внутри состояний, поскольку они определяют, что происходит, когда объект входит или выходит из состояния. Большую часть действий, однако, изображают вдоль линии перехода, так как они не должны осуществляться при входе или выходе из состояния.
Например, при переходе счета из открытого в закрытое состояние выполняется действие «Сохранить дату закрытия счета». Это непрерываемое поведение осуществляется только во время перехода из состояния «Открыто» в состояние «Закрыто».
Действие рисуют вдоль линии перехода после имени события, его изображению предшествует косая черта.
Событие или действие может быть поведением внутри объекта, а может представлять собой сообщение, посылаемое другому объекту. Если событие или действие посылается другому объекту, перед ним на диаграмме помещают знак «^».
Диаграммы состояний не надо создавать для каждого класса, они применяются только в сложных случаях. Если объект класса может существовать в нескольких состояниях и в каждом из них ведет себя по-разному, для него может потребоваться диаграмма состояний.
Диаграммы компонентов показывают, как выглядит модель на физическом уровне. На них изображены компоненты программного обеспечения и связи между ними. При этом на такой диаграмме выделяют два типа компонентов: исполняемые компоненты и библиотеки кода.
Каждый класс модели (или подсистема) преобразуется в компонент исходного кода. После создания они сразу добавляются к диаграмме компонентов. Между отдельными компонентами изображают зависимости, соответствующие зависимостям на этапе компиляции или выполнения программы.
На рисунке 2.18 изображена одна из диаграмм компонентов для банковской системы.
Рисунок 2.18 –Диаграмма компонентов для клиентской части системы
На этой диаграмме показаны компоненты для клиентской части системы. В данном случае система разрабатывается на языке C++. У каждого класса имеется свой собственный заголовочный файл и файл с расширением .СРР, так что каждый класс преобразуется в свои собственные компоненты на диаграмме. Например, класс ATMScreen преобразуется в компонент ATMScreen диаграммы. Он преобразуется также и во второй компонент ATMScreen. Вместе эти два компонента представляют тело и заголовок класса ATMScreen. Выделенный (залитый) компонент называется спецификацией пакета (packagespecification) и соответствует файлу тела класса ATMScreen на языке C++ (файл с расширением *.cpp). Невыделенный компонент (не залитый) также называется спецификацией пакета, но соответствует заголовочному файлу класса языка C++ (файл с расширением *.h).
Компонент АТМ.ехе является спецификацией задачи и представляет поток обработки информации (threadofprocessing). В данном случае поток обработки является исполняемой программой.
Компоненты соединены штриховой линией, что соответствует зависимостям между ними. Например, класс CardReader зависит от класса ATMScreen. Это означает, что для того, чтобы класс CardReader мог быть скомпилирован, класс ATMScreen должен уже существовать. После компиляции всех классов может быть создан исполняемый файл ATMClient.exe.
Пример банковской системы содержит два потока обработки, и таким образом получаются два исполняемых файла. Один из них - это клиентская часть системы, она содержит компоненты CashDispenser, CardReader и ATMScreen. Второй файл - это сервер, включающий в себя компонент Account. Диаграмма компонентов для сервера показана на рисунке 2.19.
Рисунок 2.19 – Диаграмма компонентов для сервера
Как видно из примера, у системы может быть несколько диаграмм компонентов в зависимости от числа подсистем или исполняемых файлов. Каждая подсистема является пакетом компонентов. В общем случае пакеты - это совокупности компонентов. Пример банковской системы содержит два пакета: клиентская часть и сервер.
Диаграммы компонентов применяются теми участниками проекта, кто отвечает за компиляцию системы. Из нее видно, в каком порядке надо компилировать компоненты, а также какие исполняемые компоненты будут созданы системой. На такой диаграмме показано соответствие классов реализованным компонентам. Она нужна там, где начинается генерация кода.