Когда объект посылает сообщение другому объекту (фактически делегируя ему некоторое действие), получатель может, в свою очередь, отправить сообщение третьему объекту, тот - четвертому и т.д. Такой поток сообщений формирует последовательность (Sequence). Она всегда должна иметь начало в некотором процессе или вычислительной нити (см. главу 22); последовательность может продолжаться, пока существует владеющий ею процесс или нить. Постоянно работающая система (см. главу 31), например встроенная в некоторое устройство реального времени, продолжает выполняться, пока не остановлен содержащий ее узел.
Каждый процесс и нить в системе определяет отдельный поток управления, и в каждом таком потоке сообщения упорядочены по времени. Чтобы удачно визуализировать последовательность сообщений, можно явно смоделировать их порядок относительно начала последовательности, предпослав каждому сообщению его порядковый номер, отделенный двоеточием.
Процедурные и вложенные потоки управления обычно изображают в виде линий с закрашенными стрелками, как показано на рис. 15.4. В данном случае сообщение findAt является первым из тех, которые вложены во второе сообщение последовательности (2.1).
|
|
Рис. 15.4 Процедурная последовательность
Менее распространенный, но вполне приемлемый способ показан на рис. 15.5. Здесь линия с незакрашенной стрелкой представляет простой (неструктурированный) поток управления, который моделирует непроцедурную передачу управления от одного шага к другому. В данном случае сообщение assertCall является вторым в последовательности.
Рис. 15.5 Одноуровневая (простая) последовательность
Примечание: Различие между простой и процедурной последовательностью довольно тонкое и принадлежит к числу сложных вопросов моделирования. Обычно простые последовательности применяют только при моделировании взаимодействий в контексте прецедентов, относящихся к системе в целом, включая актеры вне системы. Такие последовательности зачастую оказываются простыми, поскольку управление передается от шага к шагу без учета вложенных потоков управления. Почти во всех остальных случаях применяют процедурные последовательности, поскольку с их помощью представляются вложенные вызовы операций, примеры которых можно найти в большинстве языков программирования.
Моделируя взаимодействия, в которых участвует несколько потоков управления, особенно важно идентифицировать процесс или нить (см. главу 22), пославшие сообщение. Для того чтобы различать потоки управления, в UML перед порядковым номером сообщения можно указать имя процесса или нити, являющихся источником данной последовательности сообщений. Например, выражение
|
|
показывает, что операция ejectHatch (c фактическим параметром 3) выполняется в результате получения пятого сообщения в последовательности, начатой процессом или потоком D. Асинхронный поток управления изображается с помощью "полустрелки" (см. главу 22).
Можно показывать не только фактические аргументы, посланные вместе с операцией или сигналом в контексте взаимодействия, но и возвращаемые значения функции. Например, из выражения ниже явствует, что операция find c фактическим параметром "Rachel1е" возвращает значение p. Это вложенная последовательность: операция выполняется в результате второго сообщения, вложенного в третье, которое, в свою очередь, вложено в первое сообщение последовательности. На той же самой диаграмме p можно использовать в качестве фактического параметра других сообщений.
1.3.2: p:= find("Rachel1е")Примечание: UML позволяет моделировать и более сложные виды последовательностей: итерации, ветвления и охраняемые сообщения (см. главу 18). Кроме того, для моделирования временных ограничений, встречающихся в системах реального времени, с последовательностью можно связать отметки времени (см. главу 23). Более экзотические виды передачи сообщений (например, тайм-ауты) допустимо моделировать, определяя подходящий стереотип (см. главу 6).