UML2 и унифицированный процесс. Джим арлоуайла нейштадтпрактический объектно ориентированныйанализ и проектированиеu
![]()
|
• Переход из DialingISP инициируется событием cancel, наследуемым всеми подсостояниями подавтомата DialingISP. Это очень удобно, по скольку означает, что всегда при получении события cancel будет осуществляться переход из любого подсостояния в состояние Not Connected (не соединен). Такое использование суперсостояний и под состояний может существенно упростить автомат. • У подавтомата DialingISP одно входное псевдосостояние dial (набор номера) и два выходных псевдосостояния, notConnected и connected. Входное псевдосостояние изображается в виде кружка, который обычно размещается на рамке составного состояния (хотя также может находиться внутри нее), и обозначает точку входа в подавто мат. Аналогично выходное псевдосостояние, которое изображается в виде кружка с перекрестьем, обозначает выход из подавтомата. do/ dialISP DialingISP entry/ offHook WaitingForDialtone Dialing WaitingForCarrier [dialtone] входное псевдосостояние notConnected dial connected выходное псевдосостояние NotConnected Connected entry/ onHook exit/ onHook do/ useConnection cancel ISPDialer after(20 seconds)/ noDialtone after(20 seconds)/ noCarrier [carrier] Рис. 22.5. Конечный автомат классаISPDialer 494 Глава 22. Дополнительные аспекты конечных автоматов Входные и выходные псевдосостояния очень полезны, поскольку по зволяют определять разные пути входа и выхода из составных состоя ний. Они обеспечивают точки подключения, к которым подключают ся переходы в/из других состояний. Вот полный пошаговый анализ автомата класса ISPDialer. 1. Вход в суперсостояние DialingISP осуществляется через входное псев досостояние dial, и сразу же выполняется входное действие offHook (поднятие трубки) – модем «поднимает трубку». 2. Осуществляется вход в единственную область и состояние Waiting ForDialtone (ожидание тонального сигнала готовности). 3. Ожидание в состоянии WaitingForDialtone длится максимум 20 секунд. 4. Если тональный сигнал готовности не поступает в течение 20 се кунд: 4.1. осуществляется действие noDialtone (нет тонального сигнала го товности) и переход через выходное псевдосостояние notCon nected в состояние NotConnected; 4.2. при входе в NotConnected телефон возвращается на рычаг (дей ствие onHook); 4.3. осуществляется переход в состояние stop (остановка). 5. Если тональный сигнал готовности получен (т. е. сторожевое усло вие [dialtone] принимает значение true) в течение 20 секунд: 5.1. переходим в состояние Dialing (набор), в котором осуществляет ся деятельность dialISP; 5.2. по завершении деятельности dialISP происходит автоматиче ский переход в состояние WaitingForCarrier (ожидание несущей); 5.3. ожидание в состоянии WaitingForCarrier длится максимум 20 се кунд. 5.4. Если в течение 20 секунд несущая не получена: 5.4.1. осуществляется действие noCarrier (нет несущей) и пере ход через выходное псевдосостояние notConnected в со стояние NotConnected; 5.4.2. при входе в состояние NotConnected телефон возвращает ся на рычаг; 5.4.3. осуществляется переход в состояние stop. 5.5. Если в течение 20 секунд несущая получена: 5.5.1. происходит автоматический переход из суперсостояния DialingISP через выходное псевдосостояние connected в со стояние Connected; 5.5.2. осуществляется действие useConnection (использование соединения) до его завершения; 5.5.3. при выходе из Connected телефон возвращается на рычаг; 22.2. Составные состояния 495 5.5.4. осуществляется переход в состояние stop. 6. Если в любой момент нахождения в суперсостоянии DialingISP по ступает событие cancel: 6.1. немедленно осуществляется переход в состояние NotConnected; 6.2. при входе в состояние NotConnected телефон возвращается на ры чаг; 6.3. осуществляется переход в состояние stop. 22.2.2. Ортогональные составные состояния Ортогональные составные состояния содержат два или более вложен ных подавтоматов, выполняющихся параллельно. Ортогональные составные состояния содержат два или более выпол няющихся параллельно подавтоматов. При входе в составное состояние начинается одновременное выполне ние всех его подавтоматов – это неявное ветвление. Существует два способа выхода из составного состояния. 1. Оба подавтомата завершаются – неявное объединение. 2. Один из подавтоматов переходит в состояние, находящееся вне су персостояния, обычно через выходное псевдосостояние. Это не при водит к объединению – не происходит синхронизации подавтома тов, и остальные подавтоматы просто прерывают выполнение. Для исследования параллельных составных состояний нужна систе ма, предоставляющая некоторую степень параллелизма. Мы модели руем простую систему сигнализации, которая состоит из блока управ ления, датчика безопасности, пожарного датчика и блока сигнализа ции. Автомат всей системы представлен на рис. 22.6. Этот автомат отражает две основные характеристики системы сигна лизации. 1. Если срабатывает датчик вторжения, блок сигнализации воспроиз водит тревогу вторжения в течение 15 минут, после чего система возвращается в исходное состояние Monitoring. Это регулируется ме стным законодательством. 2. Если в ходе воспроизведения тревоги вторжения возникает пожар, происходит немедленный переход из состояния SoundingIntruderAlarm в состояние SoundingFireAlarm и начинает звучать сигнал пожарной тревоги. Это означает, что пожарная тревога всегда имеет более вы сокий приоритет, чем тревога вторжения. Initializing и Monitoring – составные состояния. Развернутый вид состав ного состояния Initializing представлен на рис. 22.7. 496 Глава 22. Дополнительные аспекты конечных автоматов При входе в это состояние происходит ветвление и начинается парал лельное выполнение двух подавтоматов. В верхнем подавтомате со стояние InitializingFireSensors выполняет процесс инициализации по жарных датчиков. В нижнем подавтомате состояние InitializingSecuri tySensors делает то же самое для датчиков безопасности. В нормальных условиях по завершении обоих подавтоматов происходит автоматический выход из суперсостояния Initializing. Это объединение: подавтоматы синхронизируются таким образом, что дальнейшая работа невозможна, пока не будут инициализированы и пожарные датчики, и датчики безопасности. Конечно, продолжительность инициализации do/ initializeSecuritySensor Initializing InitializingFireSensors do/ initializeFireSensor InitializingSecuritySensors Детали составного состояния Initializing Рис. 22.7. Развернутый вид составного состояния Initializing SystemActive SoundingFireAlarm after(15 mins) SoundingIntruderAlarm Initializing Monitoring fire fire intruder sensorError HandlingError SystemInactive deactivate activate off off BurglarAlarmSystem error Рис. 22.6. Автомат системы сигнализации 22.2. Составные состояния 497 зависит от используемых типов датчиков, но в простейшем случае это может быть просто короткая задержка на «разогрев» приборов. Из состояния Initializing также есть переход sensorError (ошибка датчи ка) (рис. 22.6), наследуемый обоими подсостояниями. Он позволяет немедленно выйти из Initializing при возникновении ошибки датчика. Также составное состояние Initializing и все его подсостояния наследу ют переход off от своего суперсостояния SystemActive (система активна). Он обеспечивает возможность немедленного выхода из Initializing (и всех подсостояний SystemActive) при получении события off. Иногда требуется запустить параллельные потоки управления, кото рые не надо синхронизировать с помощью объединения по их заверше нии. Этот вариант представлен составным состоянием Monitoring, пока занным на диаграмме состояний на рис. 22.8. У этого состояния есть некоторые интересные свойства. • Два подавтомата не синхронизируются: • При возникновении события fire осуществляется явный переход от MonitoringFireSensors в выходное псевдосостояние fire, при этом происходит выход из состояния Monitoring. Подавтомат Monitoring FireSensors завершается, но подавтомат MonitoringSecuritySensors продолжает выполнение. • Аналогично при возникновении события intruder осуществляется явный переход от MonitoringSecuritySensors в выходное псевдосо стояние intruder, при этом происходит выход из суперсостояния Monitoring. Подавтомат MonitoringSecuritySensors завершается, но подавтомат MonitoringFireSensors продолжает выполнение. • Составное состояние Monitoring и все его подсостояния (рис. 22.8) на следуют переход off от своего суперсостояния SystemActive, представ ленного на рис. 22.6. Это обеспечивает системе возможность немед ленно завершить работу в ответ на событие off независимо от того, какое из подсостояний является активным. do/ monitorSecuritySensor Monitoring MonitoringFireSensors do/ monitorFireSensor MonitoringSecuritySensors Детали составного состояния Monitoring fire intruder Рис. 22.8. Составное состояние Monitoring 498 Глава 22. Дополнительные аспекты конечных автоматов Этот пример показывает, как использование параллельных составных состояний, с синхронизацией или без нее, позволяет очень эффектив но моделировать параллелизм. 22.3. Состояния подавтоматов Состояние подавтомата ссылается на другой автомат. Состояние подавтомата – это особое состояние, ссылающееся на конеч ный автомат, представленный на отдельной диаграмме. Это немного похоже на вызов конечным автоматом подпрограммы другого конеч ного автомата. Состояния подавтоматов семантически эквивалентны составным состояниям. Состояния подавтоматов могут использоваться для упрощения слож ных автоматов. Конечные автоматы разделяются на отдельные диа граммы, и затем основная диаграмма ссылается на них с помощью со стояний подавтоматов. Состояния подавтоматов могут предоставить способ повторного ис пользования поведения. Поведение описывается на одной диаграмме, и затем при необходимости просто делается ссылка на эту диаграмму. Например, пусть две очень похожие системы охранной сигнализации имеют некоторое сходное поведение. Это поведение можно описать на отдельной диаграмме, а затем в автоматах каждой системы ссылаться на эту диаграмму с помощью состояний подавтоматов. Состояния подавтоматов именуются следующим образом: имя состояния : имя используемой диаграммы состояний На рис. 22.9 представлена диаграмма состояний, описывающая пове дение, которое используется в другой диаграмме. Обратите внимание, что входное и выходное псевдосостояния можно показать на рамке. LoggingIn GettingDetails do/ getUsername do/ getPassword Verifying do/ getUsername do/ getPassword cancel [badUsername] [badPassword] VerifyingUser verified cancelled badUsername badPassword getDetails verifyDetails Рис. 22.9. Диаграмма состояний автомата VerifyingUser 22.4. Взаимодействие подавтоматов 499 Их также можно поместить внутрь рамки, но нам кажется, что разме щение на рамке более четко отображает их суть как точек входа и вы хода конечного автомата. Сослаться на автомат VerifyingUser (верификация пользователя) можно с помощью состояния подавтомата, как показано на рис. 22.10. Со стояние подавтомата названо verifyingCustomer (верификация клиента). Читая эту диаграмму, состояние подавтомата необходимо мысленно заменять содержимым диаграммы VerifyingUser. 22.4. Взаимодействие подавтоматов На рис. 22.7 было показано, как можно использовать ветвления и объ единения для создания и последующей синхронизации параллельных подавтоматов. Это вид синхронного взаимодействия подавтоматов – параллельные подавтоматы ожидают завершения друг друга, пока все они не закончат выполнение. Однако очень часто необходимо обеспечить взаимодействие подавто матов, но без синхронизации автоматов. Это называют асинхронным взаимодействием. В UML асинхронное взаимодействие может быть обеспечено с помо щью «сообщений», или «флагов», оставляемых одним подавтоматом во время выполнения. Другие подавтоматы могут подбирать эти фла ги, когда будут готовы. verifyingCustomer : VerifyingUser verificationFailed CheckingOut verified cancelled badUsername badPassword getDetails verifyDetails CancellingCheckout AcceptingPayment DisplayingError AssessCustomer [noDetails] [details] succeeded cancelled checkOut состояние подавтомата paymentFailed [ok] [!ok] Рис. 22.10. Ссылка на автомат VerifyingUser с помощью состояния подавтомата 500 Глава 22. Дополнительные аспекты конечных автоматов Для асинхронного взаимодействия параллельных подавтоматов могут использоваться значения атрибутов. Такие флаги создаются с помощью значений атрибутов контекстного объекта автомата. Основная стратегия состоит в том, что один подавто мат задает значения атрибутов, а другие подавтоматы используют их в сторожевых условиях своих переходов. В состоянии OrderProcessing, показанном на рис. 22.11, нельзя предска зать, что произойдет раньше: комплектация заказа или его оплата. Для комплектации некоторых заказов, возможно, понадобится ждать поступления новых деталей, а некоторые могут быть взяты прямо со склада. Аналогично некоторые платежи могут быть более или менее срочными (по кредитной карте, например), а для прохождения других может потребоваться несколько рабочих дней (по чеку, например). Од нако здесь действует бизнес правило, выстраивающее логическую за висимость между двумя подавтоматами: заказ не может быть достав лен, пока не будет укомплектован и оплачен. В верхнем подавтомате на рис. 22.11 по завершении состояния Accept ingPayment осуществляется переход в состояние PaidFor, где атрибуту p aidFor присваивается значение true. В нижнем подавтомате, когда за вершается AssemblingOrder, можно осуществить переход к DeliveringOrder, но только когда атрибут paidFor принимает значение true. Мы добились асинхронного взаимодействия двух подавтоматов с помощью атрибу та, выступающего в роли флага, значение которого задается одним под автоматом, а запрашивается другим. Это простой и широко используе мый механизм. И наконец, оба подавтомата завершаются и синхрони зируются, и мы покидаем состояние OrderProcessing. 22.5. Предыстория При использовании автоматов в моделировании часто сталкиваешься со следующей ситуацией. • Вы находитесь в подсостоянии A составного состояния. AcceptingPayment do/ acceptPayment OrderProcessing AssemblingOrder do/ assembleOrder PaidFor entry/ paidFor = true DeliveringOrder [paidFor] Рис. 22.11. Параллельное выполнение подавтоматов 22.5. Предыстория 501 • Переходите из составного состояния (и, следовательно, из подсосто яния A). • Проходите через одно или более внешних состояний. • Возвращаетесь в составное состояние, но хотели бы продолжить вы полнение в подсостоянии A с того момента, на котором останови лись в прошлый раз. Как можно добиться этого? Понятно, что составному состоянию необ ходим какой то способ для запоминания подсостояния, в котором вы находились при выходе из него. Это требование возвращения к тому, на чем остановились, настолько распространено, что специально для его реализации в UML было включено псевдосостояние предыстории. Предыстория позволяет суперсостоянию при возвращении после пре рывания «начинать с того, на чем остановился». С помощью предыстории суперсостояния запоминают последнее ак тивное подсостояние. Существует два типа псевдосостояний предысто рии – неглубокая и глубокая предыстории. Рассмотрим их по очереди. 22.5.1. Неглубокая предыстория На рис. 22.12 показан конечный автомат прецедента BrowseCatalog сис темы электронной коммерции. В данном примере из суперсостояния Browsing можно выйти по трем со бытиям: • exit – завершает автомат и возвращается на то место, где осуществ лялось выполнение до него (нет необходимости рассматривать этот случай более подробно); • goToBasket – осуществляет переход в составное состояние Displaying Basket, в котором отображается текущее содержимое корзины для покупок; • goToCheckout – осуществляет переход в составное состояние Check ingOut, в котором покупателю представляется заказ с перечислени ем всех покупок. При возвращении в состояние Browsing из DisplayingBasket или CheckingOut было бы неплохо, чтобы пользователи попадали именно туда, где оста новились. Только такое поведение имеет смысл. Неглубокая предыстория запоминает последнее подсостояние того же уровня, что и псевдосостояние неглубокой предыстории. Псевдосостояние неглубокой предыстории может иметь множество вхо дящих переходов, но только один исходящий. Псевдосостояние неглу бокой предыстории запоминает, в каком подсостоянии вы находились при выходе из суперсостояния. Если затем происходит возвращение из 502 Глава 22. Дополнительные аспекты конечных автоматов внешнего состояния в состояние предыстории, индикатор автоматиче ски перенаправляет переход в последнее подсостояние, которое было за помнено (в данном случае DisplayingIndex или DisplayingItem). Если вход в суперсостояние осуществляется впервые, такого подсостояния нет. Поэтому срабатывает единственный исходящий переход индикатора состояния предыстории, и вы переходите в состояние DisplayingIndex. Благодаря предыстории суперсостояния запоминают последнее под состояние, которое было активно при выходе из суперсостояния. Не глубокая предыстория обеспечивает запоминание подсостояния, нахо дящегося на том же уровне, что и сам индикатор состояния предысто рии. Однако на рис. 22.12 можно увидеть, что DisplayingIndex само явля ется составным состоянием. Неглубокая предыстория не обеспечивает запоминание подсостояний этого состояния. Для этого необходима глу бокая предыстория. |