Диаграмма состояния UML. Диаграмма сост_и_перех (1). Диаграмма состояний (statechart diagram)
Скачать 418.47 Kb.
|
Переход осуществляется при наступлении некоторого события: окончания выполнения деятельности (do activity), получении объектом сообщения или приемом сигнала. На переходе указывается имя события. Кроме того, на переходе могут указываться действия, производимые объектом в ответ на внешние события при переходе из одного состояния в другое. Срабатывание перехода может зависеть не только от наступления некоторого события, но и от выполнения определенного условия, называемого сторожевым условием. Объект перейдет из одного состояния в другое в том случае, если произошло указанное событие и сторожевое условие приняло значение «истина». Примечание 53 На диаграмме состояний переход изображается сплошной линией со стрелкой, которая направлена в целевое состояние (например, «выход из строя» на рис. 6.1). Каждый переход может помечен строкой текста, которая имеет следующий общий формат: <сигнатура события>'['<сторожевое условие>']' <выражение действия>. При этом сигнатура события описывает некоторое событие с необходимыми аргументами: <имя события>'('<список параметров, разделенных запятыми>')'. Событие Термин событие (event) требует отдельного пояснения, поскольку является самостоятельным элементом языка UML. Формально, событие представляет собой спецификацию некоторого факта, имеющего место в пространстве и во времени. Про события говорят, что они «происходят», при этом отдельные события должны быть упорядочены во времени. После наступления некоторого события нельзя уже вернуться к предыдущим событиям, если такая возможность не предусмотрена явно в модели. Семантика понятия события фиксирует внимание на внешних проявлениях качественных изменений, происходящих при переходе моделируемого объекта из состояния в состояние. Например, при включении электрического переключателя происходит некоторое событие, в результате которого комната становится освещенной. После успешного ремонта компьютера также происходит немаловажное событие – восстановление его работоспособности. Если поднять трубку обычного телефона, то, в случае его исправности, мы ожидаем услышать тоновый сигнал. И этот факт тоже является событием. В языке UML события играют роль стимулов, которые инициируют переходы из одних состояний в другие. В качестве событий можно рассматривать сигналы, вызовы, окончание фиксированных промежутков времени или моменты окончания выполнения определенных действий. Имя события идентифицирует каждый отдельный переход на диаграмме состояний и может содержать строку текста, начинающуюся со строчной буквы. В этом случае принято считать переход триггерным, т. е. таким, который специфицирует событие-триггер. Например, переходы на рис. 6.1 являются триггерными, поскольку с каждым из них связано некоторое событие-триггер, происходящее асинхронно в момент выхода из строя технического устройства или в момент окончания его ремонта. Если рядом со стрелкой перехода не указана никакая строка текста, то соответствующий переход является нетриггерным, и в этом случае из контекста диаграммы состояний должно быть ясно, после окончания какой деятельности он срабатывает. После имени события могут следовать круглые скобки для явного задания параметров соответствующего события-триггера. Если таких параметров нет, то список параметров со скобками может отсутствовать. Сторожевое условие Сторожевое условие (guard condition), если оно есть, всегда записывается в прямых скобках после события-триггера и представляет собой некоторое булевское выражение. Напомним, что булевское выражение должно принимать одно их двух взаимно исключающих значений: «истина» или «ложь». Из контекста диаграммы состояний должна явно следовать семантика этого выражения, а для записи выражения может использоваться синтаксис языка объектных ограничений, основы которого изложены в приложении. Введение для перехода сторожевого условия позволяет явно специфицировать семантику его срабатывания. Если сторожевое условие принимает значение «истина», то соответствующий переход может сработать, в результате чего объект перейдет в целевое состояние. Если же сторожевое условие принимает значение «ложь», то переход не может сработать, и при отсутствии других переходов объект не может перейти в целевое состояние по этому переходу. Однако вычисление истинности сторожевого условия происходит только после возникновения ассоциированного с ним события-триггера, инициирующего соответствующий переход. В общем случае из одного состояния может быть несколько переходов с одним и тем же событием-триггером. При этом никакие два сторожевых условия не должны одновременно принимать значение «истина». Каждое из сторожевых условий необходимо вычислять всякий раз при наступлении соответствующего события-триггера. Примером события-триггера может служить разрыв телефонного соединения с провайдером Интернет-услуг после окончания загрузки электронной почты клиентской почтовой программой (при удаленном доступе к Интернету). В этом случае сторожевое условие есть не что иное, как ответ на вопрос: «Пуст ли почтовый ящик клиента на сервере провайдера?». В случае положительного ответа «истина», следует отключить соединение с провайдером, что и делает автоматически почтовая программа-клиент. В случае отрицательного ответа «ложь», следует оставаться в состоянии загрузки почты и не разрывать телефонное соединение. Графически фрагмент логики моделирования почтовой программы может быть представлен в виде следующей диаграммы состояний (рис. 6.5). Как можно заключить из контекста, в начальном состоянии программа не выполняется, хотя и имеется на компьютере пользователя. В момент ее включения происходит ее активизация. В этом состоянии программа может находиться неопределенно долго, пока пользователь ее не закроет, т. е. не выгрузит из оперативной памяти компьютера. После окончания активизации программа переходит в конечное состояние. В активном состоянии программы пользователь может читать сообщения электронной почты, создавать собственные послания и выполнять другие действия, не указанные явно на диаграмме. Однако при необходимости получить новую почту, пользователь должен установить телефонное соединение с провайдером, что и показано явно на диаграмме верхним переходом. Другими словами, пользователь инициирует событие-триггер «установить телефонное соединение». В качестве параметра этого события выступает конкретный телефонный номер модемного пула провайдера. Далее следует проверка сторожевого условия «телефонное соединение установлено», которое следует понимать как вопрос. Только в случае положительного ответа «да», т. е. «истина», происходит переход почтовой программы-клиента из состояния «активизация почтовой программы» в состояние «загрузка почты с сервера провайдера». В противном случае (линия занята, неверный ввод пароля, отключенный логин) никакой загрузки почты не произойдет, и программа останется в прежнем своем состоянии. Рис. 6.5. Диаграмма состояний для моделирования почтовой программы-клиента Второй триггерный переход на диаграмме инициирует автоматический разрыв телефонного соединения с провайдером после окончания загрузки почты на компьютер пользователя. В' этом случае событие-триггер «закончить загрузку почты» происходит после проверки сторожевого условия «почтовый ящик на сервере пуст», которое также следует понимать в форме вопроса. При положительном ответе на этот вопрос (вся почта загружена или ее просто нет в ящике) почтовая программа прекращает загрузку почты и переходит в состояние активизации. В случае же отрицательного ответа загрузка почты будет продолжена. Примечание 54 Речь идет о том, что в отдельных случаях может произойти редкое, но весьма неприятное событие, получившее название «залипание модема». Это характерно для ситуации, когда вся почта загружена, а автоматический разрыв соединения не происходит. Тем не менее и этот случай можно предусмотреть в нашей модели, дополнив диаграмму еще одним переходом с аналогичным событием-триггером «закончить загрузку почты» и с новым сторожевым условием. Это сторожевое условие должно проверять максимально допустимое время соединения для загрузки почты (например, 600 секунд) и может быть сформулировано в виде «время загрузки почты превышает 600 секунд». Модифицировать диаграмму состояний для этого случая предлагается самостоятельно в качестве упражнения. Выражение действия Выражение действия (action expression) выполняется в том и только в том случае, когда переход срабатывает. Представляет собой атомарную операцию (достаточно простое вычисление), выполняемую сразу после срабатывания соответствующего перехода до начала каких бы то ни было действий в целевом состоянии. Атомарность действия означает, что оно не может быть прервано никаким другим действием до тех пор, пока не закончится его выполнение. Данное действие может оказывать влияние как на сам объект, так и на его окружение, если это с очевидностью следует из контекста модели. Выражение записывается после знака "/" в строке текста, присоединенной к соответствующему переходу. В общем случае, выражение действия может содержать целый список отдельных действий, разделенных символом ";". Обязательное требование – все действия из списка должны четко различаться между собой и следовать в порядке их записи. На синтаксис записи выражений действия не накладывается никаких ограничений. Главное – их запись должна быть понятна разработчикам модели и программистам. Поэтому чаще всего выражения записывают на одном из языков программирования, который предполагается использовать для реализации модели. В качестве примера выражения действия (см. рис. 6.5) может служить "разорвать телефонное соединение (телефонный номер), которое должно быть выполнено сразу после установления истинности («истина») сторожевого условия «почтовый ящик на сервере пуст». Другим примером может служить очевидная ситуация с выделением графических объектов на экране монитора при однократном нажатии левой кнопки мыши. Имеется в виду обработка сигналов от пользователя при выделении тех или иных графических примитивов (пиктограмм). В этом случае соответствующий переход может иметь следующую строку текста: "нажата и отпущена левая кнопка мыши (координаты) [координаты в области графического объекта] / выделить объект (цвет). Результатом этого триггерного перехода может быть, например, активизация некоторых свойств объекта (размер файла в строке состояния) или последующее его удаление в корзину. 6.4. Составное состояние и подсостояние Составное состояние (composite state) – такое сложное состояние, которое состоит из других вложенных в него состояний. Последние будут выступать по отношению к первому как подсостояния (substate). Хотя между ними имеет место отношение композиции, графически все вершины диаграммы, которые соответствуют вложенным состояниям, изображаются внутри символа составного состояния (рис. 6.6). В этом случае размеры графического символа составного состояния увеличиваются, так чтобы вместить в себя все подсостояния. Рис. 6.6. Графическое представление составного состояния с двумя вложенными в него последовательными подсостояниями Составное состояние может содержать два или более параллельных подавтомата или несколько последовательных подсостояний. Каждое сложное состояние может уточняться только одним из указанных способов. При этом любое из подсостояний, в свою очередь, может являться составным состоянием и содержать внутри себя другие вложенные подсостояния. Количество уровней вложенности составных состояний не фиксировано в языке UML. Последовательные подсостояния Последовательные подсостояния (sequential substates) используются для моделирования такого поведения объекта, во время которого в каждый момент времени объект может находиться в одном и только одном подсостояний. Поведение объекта в этом случае представляет собой последовательную смену подсостояний, начиная от начального и заканчивая конечным подсостояниями. Хотя объект продолжает находиться в составном состоянии, введение в рассмотрение последовательных подсостояний позволяет учесть более тонкие логические аспекты его внутреннего поведения. Для примера рассмотрим в качестве моделируемого объекта обычный телефонный аппарат. Он может находиться в различных состояниях, одним из которых является состояние дозвона до абонента. Очевидно, для того чтобы позвонить, необходимо снять телефонную трубку, услышать тоновый сигнал, после чего набрать нужный телефонный номер. Таким образом, состояние дозвона до абонента является составным и состоит из двух последовательных подсостояний: «поднять телефонную трубку» и «набрать телефонный номер». Фрагмент диаграммы состояний для этого примера содержит одно составное состояние и два последовательных подсостояний (рис. 6.7). Рис. 6.7. Пример составного состояния с двумя вложенными последовательными подсостояниями Некоторых пояснений могут потребовать переходы. Два из них специфицируют событие-триггер набор цифры, которое имеет имя «цифра» с параметром "n". В качестве параметра, как нетрудно предположить, выступает отдельная цифра на диске телефонного аппарата. Переход из начального под-состояния нетриггерный, поскольку он не содержит никакой строки текста. Последний переход в конечное подсостояние не имеет события- триггера, но имеет сторожевое условие, проверяющее правильность набранного номера абонента. Только в случае истинности этого условия телефонный аппарат может перейти в конечное подсостояние, которое характеризует суперсостояние «дозвон до абонента» в целом. Составное состояние может содержать в качестве вложенных подсостояний начальное и конечное состояния. При этом начальное подсостояние является исходным, когда происходит переход объекта в данное составное состояние. Если составное состояние содержит внутри себя конечное подсостояние, то переход в это вложенное конечное состояние означает завершение нахождения объекта в данном вложенном состоянии. Важно помнить, что для последовательных подсостояний начальное и конечное состояния должны быть единственными в каждом составном состоянии. Это можно объяснить следующим образом. Каждая совокупность вложенных последовательных подсостояний представляет собой подавтомат того автомата, которому принадлежит рассматриваемое составное состояние. Поскольку каждый автомат может иметь по определению единственное начальное и единственное конечное состояния, то для подавтомата это условие также должно выполняться (рис. 6.7). Параллельные подсостояния Параллельные подсостояния (concurrent substates) позволяют специфицировать два и более подавтомата, которые могут выполняться параллельно внутри составного события. Каждый из подавтоматов занимает некоторую область (регион) внутри составного состояния, которая отделяется от остальных горизонтальной пунктирной линией. Если на диаграмме состояний имеется составное состояние с вложенными параллельными подсостояниями, то объект может одновременно находиться в каждом из этих подсостояний. Однако отдельные параллельные подсостояния могут, в свою очередь, состоять из нескольких последовательных подсостояний (подавтоматы 1 и 2 на рис. 6.8). В этом случае по определению объект может находиться только в одном из последовательных подсостояний подавтомата. Таким образом, для абстрактного примера (рис. 6.8) допустимо одновременное нахождение объекта в подсостояниях (1, 3, 4), (2, 3, 4), (1, 3, 5), (2, 3, 5). Недопустимо нахождение объекта одновременно в подсостояниях (1, 2,3) или (3, 4, 5). Рис. 6.8. Графическое изображение составного состояния с вложенными параллельными подсостояниями Поскольку каждый регион вложенного состояния специфицирует некоторый подавтомат, то для каждого из вложенных подавтоматов могут быть определены собственные начальное и конечные подсостояния (рис. 6.8). При переходе в данное составное состояние каждый из подавтоматов оказывается в своем начальном подсостояний. Далее происходит параллельное выполнение каждого из этих подавтоматов, причем выход из составного состояния будет возможен лишь в том случае, когда все подавтоматы будут находиться в своих конечных подсостояниях. Если какой-либо из подавтоматов пришел в свое конечное состояние раньше других, то он должен ожидать, пока и другие подавтоматы не придут в свои конечные состояния. В некоторых случаях бывает желательно скрыть внутреннюю структуру составного состояния. Например, отдельный подавтомат, специфицирующий составное состояние, может быть настолько большим по масштабу, что его визуализация затруднит общее представление диаграммы состояний. В подобной ситуации допускается не раскрывать на исходной диаграмме состояний данное составное состояние, а указать в правом нижнем углу специальный символ-пиктограмму (рис. 6.9). В последующем диаграмма состояний для соответствующего подавтомата может быть изображена отдельно от основной с необходимыми комментариями. Рис. 6.9. Составное состояние со скрытой внутренней структурой и специальной пиктограммой 6.5. Историческое состояние Как было отмечено выше, формализм обычного автомата не позволяет учитывать предысторию в процессе моделирования поведения объектов. Однако функционирование целого ряда систем основано на возможности выхода из отдельных состояний с последующим возвращением в это же состояние. При этом может оказаться необходимым учесть ту часть деятельности, которая была выполнена на момент выхода из этого состоянии, чтобы не начинать ее выполнение сначала. Для этой цели в языке UML существует историческое состояние. Историческое состояние (history state) применяется в контексте составного состояния. Оно используется для запоминания того из последовательных подсостояний, которое было текущим в момент выхода из составного состояния. При этом существует две разновидности исторического состояния: недавнее и давнее (рис. 6.10). Рис. 6.10. Графическое изображение недавнего (а) и давнего (б) исторического состояния Недавнее историческое состояние (shallow history state) обозначается в форме небольшой окружности, в которую помещена латинская буква "Н" (рис. 6.10, а). Это состояние обладает следующей семантикой. Во-первых, оно является первым подсостоянием в составном состоянии, и переход извне в это составное состояние должен вести непосредственно в это историческое состояние. Во-вторых, при первом попадании в недавнее историческое состояние оно не хранит никакой истории (история пуста). |