Параллельное и распределенное программирование на С++

Хьюз Камерон

Хьюз Трейси

Визуализация проектов параллельных и распределенных систем

 

 

Модель системы представляет собой своего рода информационное тело, «собранное» с целью изучения системы и лучшего ее понимания разработчиками и специалистами, которые должны ее поддерживать. При моделировании системы должны быть идентифицированы отдельные ее части, атрибуты, атакже действия, выполняемые системой. Моделирование — важный инструмент впроцессе проектирования любой системы, поэтому очень важно добиться того, чтобы разработчики до конца понимали систему, которую разрабатывают. Моделирование помогает выявить заложенный в систему параллелизм и понять, как именно следует реализовать ее распределение.

Унифицированный язык моделирования (Uniflted Modeling Language — UML) содержит графические средства, используемые для проектирования, визуализации, моделирования и документирования артефактов системы программного обеспечения. Язык UML представляет собой фактический стандарт для моделирования объект-нсюриентированных систем. Этот язык использует символы и условные знаки для обозначения артефактов системы ПО, отображаемых с различных точек зрения и при различной фокусировке. Язык UML вобрал в себя методы объектно-ориентирован-ного анализа и проектирования, предложенные Гради Бучем (GradyBooch), Джеймсом Рамбау Qames Rumbaugh) и Айваром Джекобсоном (Ivar Jacobson) в 1980-х и 1990-х годах. Он был принят рабочей группой по развитию стандартов объектного программирования (Object Management Group — OMG), международной организацией, состоящей из разработчиков ПО и производителей информационных систем и насчитывающей более 800 членов. Принятие UML дало разработчикам ПО не просто единый язык, а инструмент для анализа объектов, их описания, визуализации и документирования.

В этой главе мы покажем, как можно визуализировать и смоделировать параллельную и распределенную систему с помощью UML. Помимо помощи в разработке системы, моделирование позволяет идентифицировать области параллелизма (где именно?), понять необходимость применения синхронизации и взаимодействия подсистем (когда именно?), а также продумать степень распределения объектов (как именно?). Мы рассматриваем диаграммные методы визуализации и моделирования параллельных систем со структурной и поведенческой точек зрения. Однако следует отметить, что классы, объекты и системы, используемые в этой главе как примеры, служат целям демонстрации и необязательно отражают реальные классы, объекты или структуры, используемые в действительно существующей системе.

 

Визуализация структур

 

При рассмотрении системы со структурной точки зрения акцент ставится на ее статических частях, т.е. нас интересует, как построены элементы системы. В этом случае изучаются атрибуты, свойства и операции, выполняемые системой, а также ее организация, устройство (состав компонентов) и взаимоотношение элементов в системе. В этом разделе рассматриваются диаграммные методы, используемые для моделирования:

• классов, объектов, шаблонов, процессов и потоков;

• организации объектов, работающих «в одной команде».

Изображаемые при моделировании системы элементы могут быть концептуальными или физическими.

 

Классы и объекты

 

Класс — это м о д ель некоторой конструкции, характеризую щ ейся опре д еленными атрибута м и и пове д ение м. Это — описание м ножества понятий или объектов, которые обладают об щ и м и атрибута м и. Класс — это базовый ко м понент любо й объектно-ориентированно й систе м ы. Классы м ожно и спользовать д ля пре д ставления реальных, концептуальных, аппаратных и про г ра мм ных конструкци й. Для пре д ставления классов, объектов и взаи м оотношений, которые су щ ествуют между ни м и в параллельной и/или распределенной систе м е, используется диаграмма класса (class diagram). Диа г ра м ма класса позволяет отобразить атрибуты и услу г и, предоставляе м ые классом, а также о г раничения, нала г ае м ые на способ связи этих классов/объектов.

Язык UML содержит средства для графического представления класса. Для простейшего изображения класса достаточно начертить прямоугольник и написать на нем имя класса. При использовании только одного имени говорят, что это простое гшя. С помощью диаграммы класса можно также отобразить атрибуты и услуги. предоставляемые пользователю этого класса (или операции, выполняемые этим классом). Чтобы включить в диаграмму атрибуты и операции, прямоугольник отображается с тремя горизонтальными отделениями. В верхнем отделении записывается простое имя класса, в среднем — атрибуты, а в нижнем — операции. Разделы атрибутов и операций можно пометить словами «атрибуты» и «операции» соответственно. Имя класса должно быть указано в любом случае, а раздел атрибутов или операций — по необходимости. Это значит, что если нужно указать один из разделов (атрибутов или операций), то другой отображается пустым. Различные способы представления класса показаны на рис. 10.1.

#img_52.png Рис. 10.1. Различные способы представления класса

На рис. 10.1 представ л ен к л асс student_schedule. На рис. 10.1, а) показано его простейшее представление, рис. 10.1, б) содержит полную информацию о классе: его имя, атрибуты и операции, а рис. 10.1, в) представляет имя класса и его операции (раздел, который должен содержать атрибуты, пуст). Если раздел атрибутов оставлен пустым, это означает, что данный класс имеет атрибуты, но их показывать в данном конкретном случае не нужно.

Ино г да используетс я дополнительный раздел, который служит для описания обязанностей класса. Он раз м е щ ается под раздело м операций и может быть опущен. Под обязанностями класса подразумевают то, что ему надлежит выполнить. Обязанности класса отображаются как «договорные» предложения, которые трансформируются в операции и атрибуты. Атрибуты трансформируются в типы данных и структуры данных, а операции — в методы (функции). Этот дополнительный раздел можно пометить словом «обязанности». Обязанности класса student_schedule можно изложить следующим образом: «возвращает расписание для студента на любой день недели при заданном номере студента, годе и периоде расписания». Обязанности класса отображаются в виде текста, причем каждая обязанность представляется в соответствующем разделе как короткое предложение или абзац.

С помощью диаграммы класса можно отобразить объект, или экземпляр класса. Как и при использовании класса, простейшее представление объекта состоит в изображении прямоугольника, который содержит подчеркнутое имя объекта. Тем самым указывается именованный экземпляр класса. Именованный экземпляр класса можно сопровождать именем класса или обойтись без него.

mySchedule   именованный экземпляр

mySchedule: student_schedule  именованный экземпляр с именем класса

Поскольку реальное имя объекта может быть известно только для программы, которая его объявляет, то в системной документации, возможно, имеет смысл указывать анонимные экземпляры классов. Анонимный объект класса можно представить следующим образом.

:student_schedule

Такой тип обозначения м ожет оказаться удобны м в случае, когда в систе м е существует несколько экзе м пляров класса. Несколько экзе м пляров класса можно представить двумя способами: в виде объектов и в виде классов.

Количество экземпляров, которое может иметь класс, называется множественностью. Количество экземпляров класса (от нуля до бесконечности) можно указать на диаграм м е класса. Класс с нулевым количеством экземпляров является чистым абстрактным классом. Он не может иметь ни одного объекта, явно объявленного с использованием этого типа. Количество экземпляров может иметь нижнюю и верхнюю границы, которые также могут быть указаны на диаграмме класса. На рис. 10.2 показаны возможные варианты обозначения нескольких экземпляров класса на диаграмме класса (с помощью графических средств или значения множественности).

На рис. 10.2 множественность класса student_schedule указана как диапазон 1..7 , а это означает, что наименьшее количество расписаний в нашей системе равно 1, а наибольшее — 7. Приведем еще несколько примеров обозначения множественности класса.

1 Один экземпляр

1..n От одного до заданного числа n.

1.. * От одно г о до бесконечности

0..1 От нуля до единицы

0 * От нуля до бесконечности

* Бесконечное количество экземпляров

Безусловно, бесконечное количество экземпляров будет ограничено объемом внутренней или внешней памяти.

#img_53.png Рис. 10.2. Обозначение нескольких экземпляров класса с помощью графических средств и значения множественности

 

Отображение информации об атрибутах и операциях класса

Диаграмма класса может содержать более подробную информацию об атрибутах иоперациях класса. В разделе атрибутов можно указать тип данных и/или значение по умолчанию (если оно предусмотрено) для класса и значения атрибутов для объектов. Например, типы данных, содержащиеся в разделе атрибутов класса student_schedule, могут иметь следующий вид.

StudentNumber : string;

Term : string

StudentSchedule : map >

ScheduleIterator : map >::iterator

Для oбъeктa mySchedule эти атрибуты могут принимать такие значения.

StudentNumber : string = «102933»

Term:string = «Spring»

Методы могут быть отображены с параметрами и с указанием типов возвращаемых ими значений.

studentSchedule(&X : map >) : void

StudentNumber () : string

Фу н кция studentSchedule () принимает значение course для заданного студента (course — это класс, который моделирует один курс обучения). Курсы для каждого дня недели хранятся в векторе. Контейнер map устанавливает соответствие строки (дня недели) и вектора курсов (для заданного дня недели). Функция studentSchedule() возвращает void -значение, а функция studentNumber () — значение типа string.

На диаграмме класса можно также отобразить свойства атрибутов и операций (методов). Свойства атрибутов помогают описать характер использования того или иного атрибута, что дает возможность судить о том, можно ли его изменять или нет. Так, для описания атрибутов используются три свойства: changeable, addOnly и frozen. Краткое описание этих свойств приведено в табл. 10.1. Для определения методов используются четыре свойства: isQuery, sequential, guarded и concurrent. Они также описаны в табл.10.1. Свойства sequential, guarded и concurrent имеют отношение к параллельности выполнения методов. Свойство sequential описывает операцию, ответственность за синхронизацию которой лежит на инициаторе ее вызова. Такие операции не гарантируют целостности объекта. Свойство guarded описывает параллельно выполняемую операцию с уже встроенной синхронизацией. При этом guarded -операции означают, что в каждый момент времени возможен только один ее вызов. Свойство concurrent описывает операцию, которая позволяет ее одновременное использование. Операции, описываемые с помощью свойств guarded и concurrent, гарантируют целостность объекта. Гарантия целостности объекта применима к операциям, которые изменяют состояние объекта.

Таблица 10.1. Свойс т ва а т рибу т ов и ме т одов

Свойства атрибутов  

{changeable}  На значения этого типа атрибута никакие ограничения не налагаются

{addOnly}  Для атрибутов, y которых значение множественности >1, можно добавлять дополнительные значения. Созданное значение невозможно удалить или изменить

{frozen}  После инициализации объекта значение атрибута изменить нельзя

Свойства методов

{isQuery}  При выполнении метода этого типа состояние объекта остается неизменным. Этот метод возвращает значения

{sequential}  Пользователи этого метода для обеспечения гарантии последовательного доступа к нему должны использовать синхронизацию. При множественном параллельном доступе к этому метолу целостность объекта подвергается опасности

{guarded}  Синхронизированный последовательный доступ к этому методу встроен в объект; целостность объекта гарантируется

{concurrent}  К этому метолу разрешен множественный параллельный доступ: целостность объекта при этом гарантируется

Свойства guarded и concurrent можно использовать для отражения модели PRAM (Parallel Random-Access Machine — параллельнал машина с произвольным доступом). Если метод считывает и/или записывает данные в память, доступную для другого метода, который также считывает и/или записывает данные в гу же память, этот метод может быть описан как PRAM-алгоритм. При этом можно использовать соответствующие свойства, например, такие.

PRAM-алгоритмы Свойства
CR (Concurrent Read — параллельное чтение) concurrent
CW (Concurrent Write — параллельная запись) concurrent
CRCW (Concurrent Read Concurrent Write — параллельное чтение, параллельная запись) concurrent
EW (Exclusive Write — монопольнал запись) guarded
ER (Exclusive Read — монопольное чтение) guarded
EREW (Exclusive Read Exclusive Write — монопольное чтение, монопольная запись) guarded

Описание класса student_schedule можно сделать еще более подробным, указав с помощью свойств, как использовать его (класса) атрибуты и операции.

Атрибуты:

StudentNumber : string {frozen}

Term : string {changeable}

StudentSchedule : map > {changeable}

Операции:

scheduleDayOfWeek(&X : vector, Day : string) :void {guarded}

studentNumber() : string {isQuery, concurrent}

Атрибут StudentNumber представляет собой константу типа string. После присвоения значение константы изменить нельзя. Если объект student_schedule используется для того же студента, но для различных периодов времени, то атрибуты Term и StudentSchedule должны быть модифицируемыми. Метод scheduleDayOfWeek () принимает вектор курсов (vector) для конкретного дня недели, хранимого в строке Day. Это — защищенная (guarded) операция. Она помещает расписание студента, соответствующее конкретному дню недели, в map- объект StudentSchedule, изменяя тем самым его состояние. Синхронизация, встраиваемая в этот объект, обеспечивается за счет использования мьютексов. Метод studentNumber() имеет два свойства: isQuery и concurrent. Этот метод возвращает константу StudentNumber и безопасен для одновременного доступа. Его вызов не изменяет состояния объекта, поэтому здесь и использовано свойство isQuery.

На диаграмме класса можно отобразить е щ е одно важное свойство атрибутов и операций — их видимость. Свойство видимости описывает, кто может получить доступ к атрибуту или вызвать операцию. Для представления этого свойства (уровня видимости) используется соответствующий символ. Уровни видимости соответствуют спецификаторам доступа, определенным в С++.

Симво л видимости предваряет имя атрибута и л и операции (метода).

Спецификаторы доступа Символы видимости
public (+) Об щ ий доступ
protected (#) Доступ имеет сам к л асс и его потомки
private (-) Доступ имеет то л ько сам к л асс

 

Организация атрибутов и операций

От того, как будут организованы атрибуты и операции в соответствующих отделениях диаграммы класса, зависит степень успешности использования этого класса. Атрибуты и операции можно упорядочить по алфавиту, уровню доступа или категориям. Как оказалось, алфавитный порядок вряд ли поможет узнать, как могут называться те или иные атрибуты или операции (если документация находится в руках пользователя системы), или какие из них еще не определены (если документация используется в процессе разработки). Упорядочение по уровню доступа зарекомендовало себя гораздо лучше. В этом случае пользователь четко видит, какие атрибуты и операции являются, например, общедоступными (public) или закрытыми (private). Знание перечня защищенных (protected) членов поможет расширить возможности класса или специализировать ero, используя механизм наследования. Такое упорядочение просто реализовать с помощью символов видимости (+, - и #) или C++-спецификаторов доступа (public, private и protected,).

Существует несколько способов разбиения атрибутов и операций по кате г ориям. Минимальный стандартный интерфейс определяет категории для операций, которые в свою очередь определяют атрибуты, поддерживающие эти операции. Составители минимального стандартного интерфейса руководствовались тем, что все классы должны определять такие операции и функции, которые делают его полезным. Вот список этих операций:

• конструктор по умолчанию;

• деструктор;

• конструктор копии;

• операции присваивания;

• операции сопоставления на равенство;

• операции ввода-вывода;

• операции хеширования;

• операции запросов.

Этот список можно использовать в качестве основного перечня категорий для классификации операций, определяемых в классе. В этот перечень можно внести категории, которые позволяют указать дополнительные характеристики для атрибутов и операций.

Атрибуты:

• static

• const

Операции:

• virtual

• pure virtual

• friend

При выборе категорий следует исходить из того, какал из них лучше всего описывает услуги, предоставляемые классом. Имя категории справа и слева заключается вдвойные угловые скобки («. . .»). На рис. 10.3 показано два возможных способа организации атрибутов и операций для класса student_schedule, использующих: символы видимости и спецификаторы доступа (рис. 10.3, а) и категории минимально-гостандартного интерфейса (рис. 10.3, б).

#img_54.png Рис. 10.3. Два способа организации атрибутов и операций в диаграмме класса

 

Шаблонные классы

Шаблонный класс представляет собой механизм, который позволяет в качестве параметра в определении класса использовать тип. Шаблон определяет действия, которые выполняются над переданным ему типом. В С++ параметризованный класс создается с помощью ключевого слова template.

template classname { . . . } ;

Параметр Туре представляет любой тип, передаваемый шаблону. Это может быть встроенный С++-тип или определенный пользователем класс. При объявлении параметра Туре шаблон связывается с эле м енто м, переданным ему в качестве параметризованного типа. Например, класс student_schedule включает контейнер map, который содержит векторы объектов типа course для каждого дня недели. Как класс map, так и класс vector являются шаблонными, map > StudentSchedule;

Контейнер map использует для ключа тип string, а для значения — тип vector. Контейнер vector содержит объекты определенно г о пользователе м типа course. Контейнер map может отобразить соответствие между значениями двух любых типов данных, а контейнер vector содержать значения любого типа данных.

map > Соответствие м ежду число м и векторо м строк

map >  Соответствие м ежлучисло м истрокой

vector  Вектор объектов класса student_schedule

vector > Вектор отображений, которые устанавливают соответствие между числом и строкой

Шаблонные классы также представляются как прямоугольники. Параметризованный тип представляется как прямоугольник (меньшего размера), начертанный штриховой линией и расположенный в правом верхнем углу прямоугольника класса. Шаблонный класс может быть связанным или несвязанным. При представлении несвязанного шаблонного класса в штриховом прямоугольнике отображается прописнал буква T, означающал несвязанный параметризованный тип. Для представления связанного шаблонного класса существует два способа. Один из них состоит в использовании символа класса, содержащего синтаксис С++ для объявления и связывания шаблонного класса, напри м ер: vector

Этот вариант называется неявным связыванием. В дру г о м способе используется стереотип зависи м ости bind (связать). Этот стереотип задает источник, который реализует шаблонный класс посредство м использования реально г о пара м етризованно г о ти па. Этот вариант называется явным связыванием. Шаблонный объект является реализацией шаблонно г о класса. Он обладает отношение м зависи м ости с шаблонным классом. С помощью стереотипа связать указывается и м я параметра-типа. В штриховом прямоугольнике отображаются соответствующие типы данных. Шаблонный объект можно также рассматривать как детализацию шаблонно г о класса. Детализаци я — это общий термин, означающий более высокий уровень представления информации о том, что уже существует. Стереотипный индикатор «связать» детализирует шаблонный класс посредством реализации параметризованного типа. Способы представления шаблонного класса для контейнера map представлены на рис. 10.4.

#img_55.png Рис. 10.4. Способы представления связанного и несвязанного шаблонного класса

 

Отношения между классами и объектами

 

Язык UML определяет три типа отношений между классами:

• зависимости;

• обобщения;

• ассоциации.

Зависимость определяет отношение между дву м я класса м и. Если один класс зависит от другого, это означает, что из м енение, внесенное в независимый класс, может повлиять на зависимый от него класс. Обобщение— это отношение между некоторой общей конструкцией и бо л ее конкретны м типо м этой конструкции. Под об щ ей конструкцией подразумевается родительский класс (или суперкласс), а под более конкретны м ее типо м— сыновний класс (или подкласс). Пото м ок наслелует свойства, атрибуты и операции родителя и м ожет при это м определять собственные атрибуты и операции. Сыновний класс выводится из родительского, и его м ожно использовать в качестве заменителя родительского класса. Класс, не и м ею щ ий родителей (предков), называется корневым, или базовым классом. Ассоциация — это структурное отношение, которое означает, что объекты одного типа связаны с объекта м и другого типа. Ассоциации между объектами двунаправлены. Например, если объект 1 связан с объектом 2, то объект 2 связан с объектом 1 Ассоциация между двумя элементами (например, класса м и) называется бинарной связью, а между nэ л е м ента м и — n-арной.

Зависимость, обобщение и ассоциацию можно рассматривать как различные классификации отношений, поскольку существует множество типов зависимостей, обобщений и ассоциаций, которые можно определить. Каждал классификация отношений имеет собственный символ представления. Таким символом является отрезок прямой (начертанный сплошной или пунктирной линией) между элементами, который может увенчиваться стрелкой некоторого типа. Для более детального определения отношений отрезки прямых могут дополняться стереотипами и специальными обозначениями («украшениями»). Стереотип — это метка, используемая для более подробного описания UML-элемента. Он представляется в виде имени, заключенного в угловые скобки, и размещаемого над элементом или рядом с ним. Например, на рис. 10.4 для описания шаблонного объекта стереотип

<> (<<связать>>)

размещен рядом со стрелкой, которая отображает зависимость используемых объектов. Под «украшениями» понимаются текстовые или графические элементы, добавляемые к базовой интерпретации элемента и используемые для документирования сведений о спецификации элемента. Например, ассоциация отображается в виде отрезка сплошной линии между элементами. Агрегирование — это тип ассоциации, который выражает отношение «целое-часть». Для отображения агрегирования используется отрезок сплошной линии, у которого один конец (прилегающий к «целому» элементу) венчается полым ромбом.

Зависимость обозначается пунктирной направленной линией (со стрелкой), которая указывает на зависимую конструкцию. Отношение зависимости следует применять в случае, когда одна конструкция использует другую. Обобщение обозначается сплошной направленной линией со стрелкой, указывающей на родительский класс (суперкласс). Отношение обобщения следует применять в случае, когда одна конструкция выведена из другой. Ассоциация обозначается сплошной линией, которая соединяет одинаковые или различные конструкции. Отношение ассоциации следует применять в случае, когда одна конструкция структурно связана с другой. Некоторые стереотипы и ограничивающие условия, которые применяются к зависимостям, приведены в табл. 10.2. Эти стереотипы используются для отображения зависимостей между классами, интерактивными объектами, состояниями и пакетами. Стереотипы и ограничивающие условия, которые могут применяться к обобщениям и ассоциациям, приведены в табл. 10.3 и 10.4. Если стереотипы используют графические «украшения», они показаны в таблицах.

Таблица 10.2. Стереотипы, применяемые к зависимостям

Зависимость Описание
<< bind >> (<< связать>>) источник реализует шаблонный приемник, используя peальные параметры
<<friend>>(<<друг>>)  видимость источника распространяется на содержимое приемника
<<instanceOf>> (<<экземпляр>>) источник является экземпляром приемника;используется для определения отношений между классами и объектами
<< instantiate>>(<< создать экземпляр>>)  источник создает экземпляры приемника;используется для определения отношений между классами и объектами
<< refine>> (<< уточнить >>) источник представляет более высокий уровень детализации, чем приемник; используетсядля определения отношений между производным и базовым классами
<< use >> источник зависит от открытого (public) интерфейса приемника
(<< использовать>>)
<< become>>(<< стать>>)  объект-приемник совпадает с объектом-источником, но в более поздний период жизненного цикла объекта; приемник может иметь другие значения, состояния и пр.
<<call>> объект-источник вызывает метод приемника
(<< вызвать>>)
<< сору >>(<< копировать>>)  объект-приемник является точной и независимой копией  объекта-источника
<<access >>(<< получить доступ>>)  исходному пакету предоставляется право ссылаться на элементы приемного пакета
<<extend>> (<< расширить>>) данный прецедент приемника расширяет поведение источника
<<include>>(<< включить>>)  данный прецедент источника может включать прецедент  приемника

Ассоциации имеют еще один уровень детализации, который может быть применен к стереотипам, перечисленным в табл. 10.4:

• Имя Ассоциация может и м еть и м я (название), которое используется для описания природы отношений. К имени может быть добавлен треугольник, указывающий направление, в котором должно читаться имя.

• Роль   Роль обозначает функцию, которую выполняет класс, представленный на одном конце линии ассоциации, относительно класса, представленного на другом конце этой линии.

• Множественность Обозначение множественности может использоваться для указания количества объектов, которые могут быть связаны с помощью данной ассоциации. Множественность можно отображать на обоих концах линии ассоциации.

• Передвижение Передвижение по ассоциации может быть однонаправленным, если объект 1 связан с объектом 2, но объект 2 не связан с объектом 1.

Таблица 10.3. Стереотипы и огра н ичивающие условия, которые могут   применяться к обобще н иям

• Стереотип << implementation >> (« реализация ») потомок наслелует реализацию родителя, но не делает открытыми (public) его интерфейсы и не поддерживает их

• Ограничение { complete } ({полнота}) Обусловливает, что все потомки в обобщении получили имена, и никаких дополнительных потомков больше не было выведено

• Ограничение { incomplete }({неполнота}) не все потомки в обобщении получили имена, и дополнительные потомки могут быть выведены

• Ограничение { disjoint } ({несовместимость}) объекты родителя не могут иметь больше одного потомка, используемого в качестве типа

• Ограничение { overlapping }({перекрытие}) объекты родителя могут иметь больше одного потомка,  используемого в качестве типа

Таблица 10.4. Стереотипы и ограничивающие условия, которые могут применяться к ассоциациям

• navigation (передвижение) Описывает однонаправленную (нереверсивную) ассоциацию, при которой объект 1 связан с объектом 2, но объект 2 не связан с объектом 1

• aggregation (агрегирование) Описывает связь «целое-часть», при которой «часть» во время своего существования связана не только с одним «целым»

• composition (композиция) Описывает связь «целое-часть», при которой «часть» во время своего существования может быть связана только с одним «целым»

• Ограничение { implicit } ({неявное}) Обусловливает, что отношение является концептуальным

• Ограничение { ordered } ({упорядоченность}) Обусловливает, что объекты на одном конце ассоциации упорядочены

• Свойство { changeable } ({модифицируемость}) Описывает, что может быть добавлено, удалено и изменено между двумя объектами

• Свойство { addOnly } ({расширяемость}) Описывает новые связи, которые могут быть добав л ены к объекту на противоположном конце ассоциации

• Свойство { frozen } ({жесткость}) Описывает связь, которая после добавления к объекту на противоположном конце ассоциации не может быть изменена или удалена

 

Интерфейсные классы

Интерфейсный класс используется для модификации интерфейса другого класса или множества классов. Такая модификация упрощает использование класса, делает его более функциональным, безопасным или семантически корректным. Примерами интерфейсных классов могут служить адаптеры контейнеров, которые являются частью стандартной библиотеки шаблонов (Standard Template Librаrу — STL). Адаптеры обеспечивают новый открытый (public) интерфейс для таких контейнеров, как deque (double-ended queue — очередь с двусторонни м доступо м), vector (вектор) и list (список). Расс м отри м при м ер. В листин г е 10.1 представлено определение класса stack, который используется в качестве интерфейсно г о для м одификации класса vector.

// Листинг 10.1. Использование класса stack в качестве

// интерфейсного класса

template < class Container > class stack {

//...

public:

typedef Container::value_type value_type;

typedef Container::size_type size_type; protected:

Container с;

public:

bool empty(void) const {return c.empty();}

size_type size(void) const {return c.size();}

value_type& top(void) {return c.back(); }

const value_type& top const {return c.back(); }

void push(const value_type& x) {c.push.back(x); }

void pop(void) {c.pop.back(); }

};

Класс stack объявляется путе м задания типа Container

stack < vector< T > > Stack;

В данном случае типом Container является класс vector, но в качестве класса реализации для интерфейсного класса stack (вместо класса vector) можно использо-ватьлюбой контейнер, который определяет следующие методы:

empty () size() back() push.back() pop.back()

Класс stack поддерживает се м антически корректный интерфейс, традиционно принятый для стеков.

Существует несколько способов отображения интерфейса. Один из них — круг, рядом с которым (чаще — под ним) записывается имя интерфейсного класса. Этот способ показан на рис. 10.5, а. Для отображения операций класса stack м ожно также использовать си м волическое обозначение класса (с м. рис. 10.5, б). Здесь над и м ене м класса отображается индикатор стереотипа << interface>>, обозначающий, что это — интерфейсный класс. Имя интерфейсного класса может начинаться с буквы «I», и тогда все операции этого класса булут заметнее отличаться от других классов.

Для отображения отношений м ежду класса м и stack и vector м ожно использовать понятие реализации. Реализация — это се м антическое отношение между классами, в котором один из них предлагает «контракт» (интерфейсный класс), а другой ero выполняет (класс реализации). В наше м при м ере класс stack определ я ет контракт, а класс vector его выполняет. Отношение реализации отображается отрезком пунктирной линии между двумя прямоугольниками классов с крупной полой стрелкой, указывающей на интерфейсный класс, т.е. на класс, который определяет контракт (рис. 10.5, в). Это изображение читается так: «Класс stack реализуется классом vector». Отношение между интерфейсным классом и его реализатором (средством реализации) также можно отобразить в виде «леденца на палочке» (рис. 10.5, г). Класс stack может быть реализован не только классом vector, но и классами list или deque .

#img_56.png Рис. 10.5. Способы представления интерфейсного класса

 

Организация интерактивных объектов

Как видите, классы и интерфейсы можно использовать в качестве строительных блоков (т.е. базовых элементов) при создании более сложных классов и интерфейсов. В распределенной или параллельной системе возможно существование больших исложных структур, сотрудничающих с другими структурами, что создает объединение классов и интерфейсов, работающих вместе над достижением общих целей системы. В языке UML такое поведение называется сотрудничеством. Упомянутые выше строительные блоки могут включать как структурные, так и поведенческие элементы системы. Конкретная задача, которую запрашивает пользователь, может включать множество выполняемых вместе объектов. При этом для выполнения разных задач могут использоваться одни и те же объекты, взаимодействующие в разных случалх с различными элементами. Такая коллекция элементов (с учетом взаимодействия между ними) формирует сотрудничество. Понятие сотрудничества состоит из двух частей: структурной части, в которой акцент делается на характере организации и построении сотрудничающих элементов, и поведенческой, в которой основное внимание уделяется взаимодействию между элементами. (Об этом пойдет речь в слелующем разделе.)

#img_57.png Рис. 10.6. Диаграмма сотрудничества для системы составления расписания

Сотрудничество отображается в виде эллипса (начертанного пунктирной линией), содержащего название вариа н та сотрудничества. Имя сотрудничества должно быть уникальным. Оно представляет собой существительное или короткую фразу, состоящую из существительных, которые входят в словарный состав моделируемой системы. Структурные и поведенческие части сотрудничества отображаются внутри эллипса сотрудничества. Пример структурной части системы составления расписания показан нарис. 10.6. Структурная часть сотрудничества представляет собой сочетание классов и интерфейсов, ко м понентов и узлов. Систе м а, показанная на рис. 10.6, может содержать множество вариантов сотрудничества. Каждый вариант сотрудничества уникален в системе, но его элементы — нет. Элементы одного варианта сотрудничества могут быть использованы в другом варианте за счет иной организации.

 

Отображение параллельного поведения

 

При отражении поведенческой характеристики системы акцент ставится на ее динамических аспектах. С этой точки зрения нас интересует, как ведут себя элементы системы при взаимодействии с другими элементами той же системы. Именно во взаимодействии одних элементов с другими и проявляются особенности параллелизма. Диаграммы, используемые в этом разделе, позволяют смоделировать:

• поведение объекта в течение его периода существования;

• поведение объектов, которые совместно работают ради достижения конкретной цели;

• поток управления с акцентом на определенном действии или последовательности действий;

• синхронизацию действий элементов и взаимодействие между ними.

В этом разделе также описаны диаграммы, используемые для моделирования распределенных объектов.

 

Сотрудничество объектов

 

Сотрудничество объектов заключается в привлечении друг друга к работе с целью выполнения некоторой конкретной задачи. Они не вступают в постоянные отношения. Одни и те же объекты могут привлекаться разными объектами для выполнения различных задач. Сотрудничество объектов можно представить в виде диаграммы сотрудничества. Диаграммы сотрудничества имеют структурную и интерактивную части. Структурную часть мы рассмотрели выше. Интерактивнал часть отображается в виде графа, вершинами которого являются объекты — участники рассматриваемого сотрудничества. Связи между объектами представляются ребрами. Ребра могут сопровождаться сообщениями, передаваемыми между объектами, вызовами методов и индикаторами стереотипов, которые позволяют подробнее отобразить характер связи.

Связь между объектами имеет тип ассоциации. С двумя связанными объектами мотут выполняться действия. В результате действия может измениться состояние одного или двух объектов. Приведем примеры различных типов действий, связанных с объектами.

• create  Объект может быть создан

• destroy  Объект может быть разрушен

• call  Операция, определенная в одном объекте, может быть вызвана другим объектом или им самим

• return  Объекту возвращается значение

• send  Объекту может быть послан сигнал

При вызове и выполнении любо г о м етода воз м ожно наличие передавае м ых параметров и возвра щ аемо г о значения (а также другие действия).

Эти действия могут иметь место, если принимающий объект видим для вызывающего. Для объяснения причины видимости объекта можно использовать следующие стереотипы.

• association Объект видим по причине существования ассоциации (самый общий случай)

• parameter Объект видим, поскольку он является параметром для вызывающего объекта

• local Объект видим, поскольку он имеет локальную область видимости для вызывающего объекта

• global Объект видим, поскольку он имеет глобальную область видимости для вызывающего объекта

• self Объект вызывает собственный метод

Помимо перечисленных, возможно применение и других стереотипов.

При вызове некоторого метода возможен вызов других методов иными объектами. Последовательность выполнения операций можно отобразить с помо щ ью комбинации порядковых номеров и двоеточия, отделяю щ его имя метода от соответствую щ его номера. Комбинация порядковых номеров выражает последовательность, в которой выполняются операции. Например, на рис. 10.7 показана диаграмма сотрудничества, в которой используются порядковые номера.

#img_58.png Рис. 10.7. Диаграмма сотрудничества, использующая порядковые номера для обозначения последовательности выполнения операций

Как показано на рис. 10.7, объект MainObject выполняет две операции в слелующей последовательности:

1: << create >>

2: Value := performAction(ObjectF)

При выполнении операции 1 объект MainObject создает объект Obj ectA. Объект ObjectA локален по отношению к объекту MainObject (поскольку имеет место включение объектов). Это инициирует первую последовательность операций во вложенном потоке управлени я. Дл я обозначения всех операций этой последовательности используется число 1, за которым следует число, отражающее порядок их выполнения. Итак, первая операция последовательности 1 такова: 1.1: initialize()

Объект ObjectA вызывает собственный метод. Выполнение объектом собственно г о метода выражается соединительной линией, связываю щ ей объект с самим собой, и индикатором стереотипа {self} ({caм } ).Onepaция ObjectA::initialize() также запускает другую последовательность действий:

1.1.1 : initializeB()

1.1.2: initializeC()

В этой последовательности два других объекта (которые локальны по отношению кобъекту ObjectA) инициализируются посредством вызова соответствую щ их методов инициализации. Операция 2: performAction(ObjectD)

является началом еще одной вложенной последовательности действий. Объекту ObjectA передается объект ObjectD. Объект ObjectA вызывает операцию, определенную в объекте ObjectD:

2.1: doAction()

Объект ObjectA имеет право вызвать эту операцию, поскольку объект ObjectD является параметро м (переданны м объекто м MainObject), как от м ечено стереотипо м {parameter}. В результате выполнения этой последовательности действий объекту ObjectA возвра щ ается значение и объекту MainObject также возвра щ ается значение. По м и м о ко м бинаций порядковых номеров, обозначение этих вложенных потоков управления можно усилить с помощью линии с зачерненной стрелкой, указывающей в направлении выполнения последовательности действий.

 

Процессы и потоки

Процесс — это часть работы (кода), создаваемая операционной системой. Он включает один или несколько потоков, выполняемых в его адресном пространстве. Если потоков несколько, то один из них является основным (main thread). Несколько процессов могут выполняться параллельно. Потоки одного процесса могут выполняться параллельно с потока м и дру г их процессов.

При использовании языка UML дл я отображения функционирования процессов и потоков каждый независи м ый поток выполнения считается активным объектом. Активный объект — это объект, который является владельце м процесса или потока. Каждый активный объект может активизировать то, чем он владеет. Активный класс — это класс, объекты которого являются активными. Активные классы можно использовать для моделирования группы процессов или потоков, которые разделяют одни и те же члены данных и методы. Объекты конкретной системы могут не иметь однозначной взаимосвязи с активными объектами. Как упоминалось в главах 3 и 4, при разделении программы на процессы и потоки следует учитывать, что методы объектов могут выполняться в отдельном процессе или отдельных потоках. Следовательно, при моделировании одного такого объекта его можно представить в виде нескольких активных объектов. Отношение между статическими и активными объектами можно изобразить с помощью диаграммы взаимодействия. В систе м е м ожет быть несколько PVM- или MPI-задач, или процессов, и каждую из них м ожно представить непосредственно как активный объект.

Язык UML позволяет представить активный объект или класс таким же способом, как статический объект, за исключением того, что периметр прямоугольника, обозначающего этот объект или класс, обводится более жирной линией. В этом случае можно также использовать следующие два стереотипа:

process

thread

Индикаторы этих стереотипов позволяют отобразить рааличие между двумя типами активных объектов. На рис. 10.8 показана PVM-задача в виде активного класса и активного объекта. Диаграмма сотрудничества может состоять из активных объектов.

#img_59.png Рис. 10.8. Активный объект и класс

 

Отображение нескольких потоков выполнения и взаимодействия между ними

В параллельной и распределенной системе возможно существование нескольких потоков выполнения, которые относятся к одному или нескольким процессам. Эти процессы и потоки могут выполняться в одной компьютерной системе с несколькими процессорами либо распределяться между несколькими различными компьютерами. Для представления каждого потока выполнения используется активный объект или класс При создании активного объекта инициируется независимый поток выполнения. При разрушении активного объекта этот поток прекращает свое существование. Моделирование потоков в системе позволяет успешно осуществить управление, синхронизацию и взаимодействие между ними.

В диаграмме сотрудничества для идентификации потоков используются числа и стрелки со сплошной заливкой наконечника. В диаграмме сотрудничества, которая состоит из активных объектов параллельной системы, имя активного объекта представляется порядковыми числами операций, выполняемых активным объектом. Активный обьект может вызвать метод, определенный в другом объекте, и приостановить выполнение до тех пор, пока этот метод не завершится. Стрелки используются не только для отображения направления хода выполнения потока, но и природы его поведения. Стрелки со сплошной заливкой наконечника используются для представления синхронного вызова, а стрелка с однореберным наконечником — для представления асинхронного вызова. Поскольку один и тот же метод может быть вызван сразу несколькими активными объектами, то для описания синхронизации этого метода можно использовать такие его свойства:

• sequential

• guarded

• concurrent

#img_60.png Рис. 10.9. Диаграмма сотрудничества статических и активных объектов в системе составления расписаний

На рис. 10 9 представлена диаграмма сотрудничс ства нескольких активных объектов, которые «совместными усилиями» создают расписание студента. Объект blackboard используется дл я ре г истрации результатов предварительной работы и ее координации, а также представления итогового расписания, сгенерированного решателями задач активных объектов, именуемых в данном случае агентами (agent).

MajorAgent Создает список имеющихся основных курсов

MinorAgent Создает список имеющихся непрофилирующих курсов

FilterAgent Фильтрует список курсов и генерирует список возможных курсов

ScheduleAgent Генерирует несколько вариантов расписаний на основе списка возможных курсов

Объект schedule_of_courses содержит все и м ею щ иеся курсы.

Объекты blackboard и schedule_of_courses доступны при параллельном к ним обращении со стороны нескольких агентов. В данном варианте сотрудничества оба эти объекта видимы для всех агентов. А г енты MajorAgent, MinorAgent, FilterAgent и ScheduleAgent вызывают методы объекта blackboard. Агенты MajorAgent и MinorAgent вызывают методы объекта schedule_of_courses. При этом а г енты Maj orAgent и MinorAgent имеют анало г ичную последовательность обращений к объектам blackboard и schedule_of_courses.

MajorAgentl: currentDegreePlan()

MajorAgent2 : coursesTaken()

MajorAgent3 : scheduleOfCourses ()

MajorAgent4 : suggestionsForMajor ()

MinorAgentl:currentDegreePlan()

MinorAgent2:coursesTaken()

MinorAgent3:scheduleOfCourses()

MinorAgent4:suggestionsForMinor()

Как видите, к имени активного объекта, который вызывает эти методы, присоединяется порядковый номер. Оба объекта параллельно вызывают методы объектов blackboard и schedule_of_courses. Все эти методы параллельно синхронизированы и защищены от одновременного вызова. Методы masterList() и possibleCourses() имеют свойство guarded. Одни объекты могут модифицировать содержимое курсов, а другие— считывать его. Поэтому методы masterList () и possibleCourses () защищены разрешением только последовательного к ним доступа (EREW).

 

Последовательность передачи сообщений между объектами

В то время как в диаграмме сотрудничества основное внимание уделяется структурной организации и взаимодействию объектов, совместно выполняющих некоторую за-далу или реализующих прецедент (вариант использования системы), в диаграмме последовательностей акцент ставится на временном упорядочении вызовов методов или процелур, составляющих данную задалу или прецедент. В диаграмме последовательностей имя каждого объекта или консгрукции отображается в собственном прямоугольнике. Все прямоугольники размещаются в верхней части диаграммы, вдоль ее оси X. В диаграмму следует включать только основных исполнителей прецедента и наиболее важные функции, в противном случае диаграмма будет перенасыщена деталями и утратит свою полезность. Объекты упорядочиваются слева направо, начинал с объекта или про-целуры, которая является инициатором действия для большинства второстепенных объектов или процедур. Вызовы функций отображаются вдоль оси Y сверху вниз в порядке возрастания значения времени. Под каждым прямоугольником наносятся вертикальные линии, представляющие «жизненные пути» (линии жизни) объектов. Стрелки со сплошной заливкой наконечника, направленные от линии жизни одного объекта клинии жизни другого, обозначают вызовы функций или методов (причем такая стрелка всегда направлена от инициатора вызова). Стрелки с «реберными» наконечниками имеют обратное направление (т.е. к инициатору вызова), обозначая возврат из функции или метода. Каждый вызов функции помечается ее именем. Помимо имени, при необходимости отображается информация об аргументах и условиях вызова, например:

[list != empty]

getResults()

Функция или метод не выполнится, если заданное условие не будет истинны м. Методы, которые должны быть вызваны несколько раз (напри м ер, при считывании значений из структуры), предваряются признако м итерации (*).

На рис. 10.10 показана диагра мм а последовательностей для объектов систе м ы составления расписания. Чтобы не перегружать эту де м онстрационную диагра мм у, количество объектов в ней ограничено лишь тремя. В диаграммах последовательностей для параллельных объектов или процедур используются символы активизации. Си м вол активизации представляет собой прямоугольник, отображаемый на линии жизни объекта. Наличие символа активизации означает активность объекта или процедуры. Символы активизации используются в случае, когда объект обращается к другому объекту без блокирования. Тем самым становится понятно, что объект или процедура продолжает выполняться или быть активной. На рис. 10.10 показано, что объект blackboard всегда активен. Он порождает объект schedule _agent и нс блокируется. Объект schedule_agent вызывает метод blackboard.masterList() и ожидает получения от него списка курсов. Как упоминалось выше, возвра щ ение метода обозначается стрелкой с «реберным» наконечником. Метод schedule_agent затем вызывает один из собственньвс методов createSchedules (). Для обозначения вызова объектом одного из собственных методов используется специальный символ, состоя щ ий из символа активизации и стрелки вызова. Символ активизации при этом накладывается на уже имеющийся символ активизации. Линия выходит из исходного символа активизации, а ее стрелкауказывает надополнительный символ. После передачи объектом schedule_agent результатов своей работы путем вызова метода blaekboard.possibleSchedule () объект blackboard аннулирует его. Аннулирование обозначается большим символом «X» в конце линии жизни объекта. Стрелка вызова метода, исходящал из объекта blackboard и указываю щ ая на символ «X», означает, что инициатором аннулирования является объект blackboard. Объект blackboard затем порождает объект filter_agent и опять-таки не блокируется. Объект filter_agent вызывает метод blackboard.possibleSchedules () и ожидает получения от него вариантов расписаний. Объект filter_agent после этого вызывает один из собственных методов filterCourses (). После передачи результатов объект filter_agent ликвидирует себя. Объект blackboard последовательно вызывает собственные методы organizeSolution () и updateRecords (), а затем также ликвидируется.

 

Деятельность объектов

Язык UML можно использовать для моделирования видов деятельности объектов — участников конкретной операции или прецедента. В этом случае строится диаграмма (видов) деятельности, которая представляет собой блок-схему, отражающую последовательные и параллельные действия (или виды деятельности) объектов, принимаю щ их участие в выполнении конкретной задачи. На этой диаграм м е с по м о щ ью стрелок указывается направление передачи управления для соответствую щ их видов деятельности. В то вре м я как в диагра мм ах сотрудничества основное внимание уделяется передаче управления от объекта к объекту, в диагра м мах последовательностей — временному упорядочению потоков выполнения, в диаграммах деятельности акцент ставится на передаче управления от одного действия (или вида деятельности) к другому. В результате действия (или вида деятельности) изменяется состояние объекта или возвра щ ается некоторое значение. Содержи м ое действия (или вида деятельности) называется состоянием действия (или вида деятельности). Состояние объекта представляется в это м случае как конкретный м о м ент в потоке выполнения.

#img_61.png Рис. 10.10. Диаграмма последовательностей некоторых объектов системы составления расписаний

Действие и деятельность и м еют различия. Действия не м огут быть логически подвергнуты декомпозиции или прерваны другими действиями или событиями. Примерами действий могут служить создание или разрушение объекта, вызов метода или функции. Деятельность можно разложить на составные части (другие виды деятельности). В качестве примеров деятельности можно назвать программу, прецедент или процедуpy. Деятельность можно прервать событием, другим видом деятельности или действием.

Диаграмма (видов) деятельности представляет собой граф, узлы которого обозначают действия или виды деятельности, а ребра — безусловные переходы. Безусловность перехода состоит в том, что для того, чтобы он произошел, не требуется никакого события. Переход происходит сразу же по завершении предыдущего действия или вида деятельности. Эта диаграмма содержит ветви решений, символы начала, останова и синхронизации, которые объединяют несколько действий (или видов деятельности) или обеспечивают их разветвление. Состояния действий и видов деятельности представляются аналогичным образом. Для представления состояния действия или деятельности в языке UML используется стандартный символ блок-схемы, который обычно служит для отображения точек входа и выхода. Этот символ применяется независимо от типа действия или деятельности. Мы предпочитаем использовать стандартные символы блоксхемы, которые позволяют отличить действия ввода-вывода (параллелограмм) от действий обработки или преобразования (прямоугольник). Описание действия или вида деятельности, т.е. имя функции, выражения, прецедента или программы, отображается в соответствующем элементе графа. Состояние деятельности может дополнительно включать отображение действий входа и/или выхода. Действие входа— это действие, которое происходит, ко г да и м еет м есто вход в состо я ние деятельности, а действие выхода — это действие, которое происходит непосредственно перед выходо м из состояния деятельности. Эти действия являются первы м и последни м действия м и соответственно, которые должны быть выполнены в состоянии активности.

По завершении одного действия происходит немедленный переход к началу следующего. Переход обозначается стрелкой с двухреберным наконечником, направленной от одного состояния к другому (следующему). Переход, который указывает на состояние, называется входящим, а перехо д, обозначаю щ ий выход из состояния, — выходящим. Прежде че м произойдет выходя щ ий переход, до л жно выпо л ниться действие выхода, ес л и таковое прелус м отрено. Действие входа, ес л и таковое предус м отрено, выпо л няется пос л е то г о, как произойдет входной переход. Начало потока выпо л нения представляется в виде крупной закрашенной точки. Первый переход ведет из закрашенной точки к перво м у состоянию диа г ра мм ы. Точка останова, или состояние останова, диа г ра мм ы деятельности представляется крупной закрашенной точкой, заключенной внутри окружности.

Диаграммы деятельности подобно блок-схемам имеют символ решения. Символ решения имеет форму ромба с одним входящим переходом и двумя (или более) выходящими переходами. Выходящие переходы сопровождаются условиями, которые определяют дальнейшее направление передачи управления. Это условие представляет собой обычное булево выражение. Выходящие переходы должны охватывать все возможные варианты ветвления. На рис. 10.11 показан символ решения, используемый при определении необходимости построения источника знаний.

Ино г да после завершения одно г о действия или вида деятельности начинается параллельное су щ ествование нескольких потоков, выполняю щ их различные последовательности действий или виды деятельности. В отличие от блок-схемы, язык UML определяет си м вол, который м ожно использовать для представления м о м ента, начинал с которо г о несколько потоков выполняются параллельно. Для отображения этого мо м ента используется си м вол синхронизации, который также служит для обозначения соединения параллельных путей. Этот си м вол и м еет фор м у жирной горизонтальной линии с нескольки м и выходя щ и м и перехода м и (разветвление) или нескольки м и входя щ и м и перехода м и (соединение). Переходы, выходя щ ие из линии синхронизации, означают состояние действия или деятельности, которое приводит к выполнению нескольких потоков. Переходы, входя щ ие в линию синхронизации, означают необходи м ость синхронизации нескольких потоков, а линия синхронизации в это м случае используется для отображения ожидания до тех пор, пока все ветви не соединятся в единую ветвь (поток). При м ер разветвления потоков и их соединения показан на рис. 10.12.

Рис. 10.11. Символ решения, используемый при определении необходимости построения источника знаний (ИЗ)

При создании объекта MajorAgent вызывается его конструктор, который (см. рис. 10.12) инициирует три параллельных потока выполнения. После завершения этих трех действий потоки соединяются в единый поток, назначение которо г о состоит в выполнении действия по созданию списка основных курсов.

Эту диаграмму можно разбить на три отдельных раздела, именуемых «плавательными дорожками». В каждой такой дорожке происходят действия или виды деятельности конкретного объекта, компонента или прецедента. «Плавательные дорожки» разделены на диаграмме вертикальными линиями. Одно действие (или вид деятельности) может происходить только в одной дорожке. Линии переходов и линии синхронизации могут пересекать одну или несколько дорожек. Действия или виды деятельности, обозначенные в одной и той же или различных дорожках, но находящиеся при этом на одном уровне, являются параллельными. Диаграмма деятельности с «плавательными дорожками» показана на рис. 10.13.

Назначение этой диаграммы деятельности — смоделировать последовательность действий объекта blackboard, который г енерирует сводный список курсов для систе м ы составления расписаний. Объект blackboard (с м. рис. 10.13) сначала принимает решение о том, нужно ли создавать объект MajorAgent. Если нужно, то вызывается конструктор объекта MajorAgent. Это приводит к созданию трех ветвей передачи управления. В двух из них действия выполняет объект blackboard («получает теку щ ий план выдачи дипломов» и «считывает курсы обучения»), а в третьей — объект ScheduleofCourses («считывает расписание курсов»). Все эти действия — входные (поэтому для их обозначения используются параллело г раммы). Затем три ветви объединяются в одну, и объект MajorAgent выполняет действие, которое состоит в создании списка основных курсов. После то г о как объект blackboard выполнит «свое» действие, а именно «получит список основных курсов», происходит удаление объекта MajorAgent. Объект blackboard «г енерирует сводный список курсов», и на этом деятельность рассматриваемых объектов прекращается.

 

Конечные автоматы

 

С помощью конечных автоматов отображается поведение единой логической конструкции, определяющей последовательность ее преобразований в качестве ответов на внутренние и внешние события в течение ее линии жизни. Такой единой логической конструкцией может быть система, прецедент или объект. Конечные автоматы используются для моделирования поведения одного элемента. Элемент может реагировать на такие события, как процедуры, функции, операции и сигналы. Элемент мо-жет также отвечать на факт истечения времени. Когда происходит подобное событие, элемент реагирует на него определенным видом деятельности или путем выполнения некоторого действия, которое приводит к изменению состояния этого элемента или созданию некоторого артефакта. Выполняемое в этом случае действие должно зависеть от текущего состояния элемента. Под состоянием понимается ситуация, которая создается в результате выполнения элементом некоторого действия или его ответа на некоторое событие в течение его линии жизни.

#img_62.png Рис. 10.13 Диаграмма деятельности с «плавательными дорожками», отображающая последовательность действий в системе составления расписаний

Конечный автомат можно представить в виде таблицы или ориентированного графа, именуемого диаграммой состояний. На рис. 10.14 изображена UML-диаграмма состояний для конечного автомата некоторого процесса. На этом рисунке показаны состояния, через которые проходит процесс в период своей активности. Рассматриваемый процесс может иметь в системе четыре состояния: готовности, выполнения, ожидания и останова. К наступлению этих четырех состояний процесса могут привести 8 событий. Три из них происходят только при выполнении определенного условия. Событие блокирования происходит только в том случае, если процесс запрашивает операцию ввода-вывода или ожидает наступления некоторого события. Событие блокирования инициирует переход процесса из состояния выполнения («бодрствования») в состояние ожидания («сна»). «Пробуждение» процесса происходит или из-за события пробуждения или в результате завершения операции ввода-вывода. Событие пробуждения заставляет процесс перейти из состояния ожидания (исходно г о состояния) в состояние г отовности (целевое состояние). Событие выхода происходит только в случае, если процесс выполнит все свои инструкции. Событие выхода заставляет процесс перейти из состояния выполнения в состояние ожидания. Остальные события относятся к категории внешних и не подвластны процессу. Они возникают по некоторым внешним причинам, вынуждающим процесс перейти из некоторого исходного в некоторое целевое состояние.

#img_63.png Рис. 10.14. Диаграмма состояний для процессов

Диаграммы состояний используются для моделирования динамических аспектов объекта, прецедента или системы. Диаграммы последовательностей, видов деятельности, сотрудничества и (добавленнал) диаграмма состояний используются для моделирования поведения системы (или объекта) в период ее (его) активности. Структур-нал часть диаграммы сотрудничества и диаграмма классов позволяют смоделировать структурную организацию объекта или системы. Диаграммы состояний прекрасно подходят для описания поведения объекта вне зависимости от конкретного прецедента. Их следует использовать не для описания поведения нескольких взаимодействующих или сотрудничающих объектов, а для описания поведения объекта, системы или прецедента, который претерпевает ряд преобразований, причем именно в случае, когда одно преобразование может быть вызвано несколькими событиями. Речь идет о таких логических конструкциях, которые весьма активно реагируют на внутренние или внешние события.

10.2. Отображение параллельного поведения 367

В диаграмме состояний узлы представляют состояния, а ребра— переходы. Состояния обозначаются прямоугольниками с закругленными углами, внутри которых записываются названия состояний. Переходы изображаются линиями с двухребер-ными стрелками, связывающими исходное и целевое состояния, причем острие стрелки должно указывать на целевое состояние. Существуют также начальное и конечное состояния. Начальное состояние представляет собой начало работы конечного автомата. Оно обозначается черной точкой с ребром перехода к первому состоянию автомата. Конечное состояние, означающее, что система, прецедент или объект достигли конца своей линии жизни, отображается черной точкой, встроенной в окружность.

Состояние имеет несколько частей (они перечислены в табл. 10.5). Состояние можно представить простым отображением его названия в центре соответствующей вершины диаграммы состояний (прямоугольника с закруглёнными углами). Если внутри этого прямоугольника необходимо отобразить также некоторые действия, то для названия состояния должен быть выделен отдельный раздел в верхней части прямоугольника. Действия перечисляются под этим разделом и должны иметь сле-лующий формат отображения:

метка [Условие] / действие или деятельность

Расс м отри м при м ер: do / validate(data)

Здесь do — это метка, которая используется для обозначения выполнения указанного действия до тех пор, пока объект находится в данном состоянии. Имя validate(data) — это имя вызываемой функции, а data — имя аргумента, с которым она вызывается. Если действие состоит в обращении к функции или метолу, то аргументы желательно указывать.

Таблица 10.5. Состав н ые час т и сос т оя н ия

Название Уникальное имя состояния, которое от л ичает е г о от других состо я ний; состояние может не иметь имени

Действия входа-выхода Действия, выполняемые при входе в состояние (состояние входа) или при выходе из него (состояние выхода)

Подсостояния Вложенные состояния; подсостояния — это составные части состояния, которые могут бытьактивизированы последовательно или параллельно. Составное состояние, или суперсостояние, — это состояние, которое содержит подсостояния

Внутренние переходы Переходы, которые совершаются внутри состояния, не вызывал при этом изменения состояния

Самопереходы Переходы, которые совершаются внутри состояния, не вызывая изменения состояния, но приводящие к выполнению входного, а затем выходного действия

Отсроченные события Список событий, которые происходят, пока объект находится вданном состоянии, но помещаются в очередь и обрабатываются, когда объект пребывает уже в другом состоянии

Условие — это условное выражение, которое приводится к значению ЛОЖЬ или ИСТИНА. Если условие дает значение ИСТИНА, выполняется действие или осуществляется деятельность, напри м ер: exit [data valid] / send(data)

Действие выхода (exit) send(data) защищено выражением data valid, которое при вычислении может дать ложное или истинное значение. Если при выходе из данного состояния это выражение даст значение ИСТИНА., то будет вызвана функция send(data). Использование выражения защиты необязательно.

Переходы из одного состояния (объекта, системы или прецедента) в другое происходят при наступлении событий. Существует два вида переходов, которые мотут осуществляться без изменения состояния (объекта, системы или прецедента) — это внутренние и самопереходы.

Самопереход и м еет м есто, когда возникновение конкретного события вынуждает объект выйти из текущего состояния. При выходе из него объект выполняет действие выхода (если таковое прелусмотрено), а затем — действие, связанное с самопереходом (если таковое прелусмотрено). Затем объект снова входит в прежнее состояние, выполняя при этом действие входа (если таковое прелусмотрено). При внутренних переходах объект вовсе не выходит из теку щ е г о состояния и, следовательно, никаких действий (ни входного, ни выходного) не выполняет. На рис. 10.15 показана общая структура состояния, включающая действия входа и выхода, осуществляемую деятельность, а также внутренние и самопереходы. Самопереход обозначается линией, направленной назад к тому же состоянию.

Переход между разными состояниями означает, что между ними существует некоторое отношение. В то время, как объект находится в одном (исходном) состоянии, может произойти некоторое событие или могут создаться определенные условия, которые заставят этот объект перейти в другое (целевое) состояние. Таким образом, переход объекта из состояния в состояние инициируется событием. Один переход может иметь несколько параллельно существующих исходных состояний. В этом случае они соединяются перед осуществлением перехода. Один переход также может иметь несколько параллельно существующих целевых состояний, и тогда имеет место разветвление. Составные части перехода перечислены в табл. 10.6. Переход изобра-кается линией, направленной от исходного состояния к целевому. Имя инициатора события отображается рядом с переходом. Подобно действиям и видам деятельности, события также могут быть защищены. Переход может быть безусловным, а это значит, что для его осуществления не требуется никакого специального события. При выходе из исходного состояния объект немедленно переходит в целевое состояние.

#img_64.png Рис. 10.15. Общая структура состояния

Таблица 10.6. Составные части перехода

Исходное состояние Первоначальное состояние объекта; при осуществлении перехода объект выходит из исходного состояния

Целевое состояние Состояние, в которое объект входит после осуществления перехода

Событийный инициатор Событие, которое инициирует осуществление перехода. Переход может быть безусловным (т.е. не иметь инициатора), в эгом случае переход происходит сразу же после того, как объект завершит все свои действия (видыдеятельности) в исходном состоянии

Защитное условие Булево выражение, связанное с событийным инициатором, которое обеспечивает осуществление перехода только в случае, если при вычислении дает значение ИСТИНА

Действие Действие, выполняемое объектом при осуществлении перехода; оно может быть связано с событийным инициатором и/или защитным условием

 

Параллельные подсостояния

Подсостояние позволяет еще больше упростить описание модели поведения системы с параллелизмом . Подсостояние— это состояние, которое является составной частью другого состояния, именуемого суперсостоянием или составным состоянием. Такое представление означает, что состояние можно разбить на несколько подсостояний. Эти подсостояния могут существовать последовательно или параллельно. Параллелизм подсостояний означает, что один объект может быть занят в двух независимых поведенческих множествах. Это справедливо для нашего объекта «классной доски» (blackboard). При обработке каждого возможного расписания он должен обновлять соответствующие структуры и выполнять другие обслуживающие процедуры. Каждое подсостояние отображается в отдельном разделе. Подсостояния синхронизируются и объединяются перед выходо м из составного состояния. Когда одно подсостояние подходит к концу, оно ожидает, пока другие состояния подойдут к концу, после чего подсостояния снова соединяются в одно. На рис. 10.16 показана диаграмма состояний для объекта blackboard, который генерирует расписание для студентов.

Состояние Генерирование расписания (с м. рис. 10.16) яв л яется составны м. Его параллельные подсостояния называются Фильтрование и Обновление. Подсостояния отделяются пунктирной линией и представляются собственными конечными автоматами, причем каждый конечный автомат имеет свои начальное и конечное состояния. В подсостояний Фильтрование объект последовательно проходит через следующие состояния: Фильтрование временных конфликтов, Балансировка и Персонификация. В под-состоянии Поддержка объект проходит только через одно состояние: Обновление. Ко г да оба подсостояния Фильтрование и Поддержка (вернее, соответствую щ ие им конечные автоматы) достигают своих конечных состояний, то перед выходом из составного состояния Генерирование расписания происходит их объединение.

#img_65.png Рис. 10.16. Диаграмма состояний для объекта blackboard

 

Распределенные объекты

Распределенные объекты — это объекты, выполняющиеся на различных процессорах, принадлежащих различным компьютерам. Диаграмма развертывания используется для построения такой м одели системы, в которой отображаются физические отношения между ее программным и аппаратным компонентами. Диаграмма развертывания позволяет отобразить маршрутизацию компонентов и объектов в распределенной системе. Компоненты могут представлять собой выполняемые программы, библиотеки или базы данных. Поэтому весьма полезно четко представлять, где именно размещается в системе конкретный компонент или объект. Понять, как именно стоит распределить параллельные компоненты системы — задача непростая. Поэтому моделирование распределенных компонентов поможетвуправлении конфигурацией, функционированием и производительностью систе м ы.

Диаграмма развертывания состоит из узлов и объектов или компонентов, которые размещаются в этих узлах. Узел — это вычислительное устройство или блок оборудования, который оснащен средствами хранения и обработки данных (например, это может быть отдельное периферийное устройство, компьютер, универсальнал вычислительная машина или кластер компьютеров). Узлы этой диаграммы связаны между собой зависимостями. Эти зависимостями представляют, как компоненты взаимодействуют друг с другом. Направление зависимости означает, какой компонент осведомлен о существовании другого компонента. Даже если связь между узлами является двунаправленной, один компонент может не «знать» о том, с кем он связан.

Существует два способа смоделировать местоположение компонентов или объектов в UML-диаграмме развертывания: посредством вложения или использования тегированного значения.

Согласно первому способу компоненты, которые располагаются в узле, перечисляются внутри символьного обозначения узла. Второй способ предлагает отображать местоположение компонентов в символе компонента. Узлы являются частью диаграммы развертывания. В качестве символа узла используется куб. Куб может иметь два отдельных раздела: один будет содержать индикатор стереотипа, описывающий тип узла, а второй — список компонентов, относящихся к этому узлу (первый способ). При использовании символа компонента (второй способ) тегу location (местоположение) присваивается имя уала, в котором размещается данный компонент. Тег location имеет следующий формат: {location = имя узла}

Тег location может быть частью любой диаграммы, в которой местоположение компонентов является существенным фактором (например, в диаграммах сотрудничества, объектов или видов деятельности). На рис. 10.17 отображены два способа обозначения местоположения компонентов в распределенной системе. В части а этого рисунка показан символ узла, содержащий список компонентов, а в части б представлен символ активного объекта, в котором используется тег location.

 

Визуализация всей системы

 

#img_66.png Рис. 10.17. Способы отображения местоположения компонента в распределенной системе

Система состоит из множества элементов, включал подсистемы, которые сотрудничают между собой с целью выполнения конкретных задач. Сотрудничество — это агрегирование конструкций, соединяемых в процессе регулярного взаимодействия.

Рассмотренные в этой главе диаграммные методы позволяют разработчику взглянуть на систему с различных точек зрения, с различных уровней, как извне, так и изнутри. В этом разделе мы обсудим моделирование системы в целом. Это означает, что на самом высоком уровне моделирования следует отображать только основные компоненты или функциональные элементы. Диаграммные методы, предлагаемые для рассмотрения в этом разделе, используются для моделирования развертывания системы и ее архитектуры. И хотя этот раздел — последний в этой главе, моделирование и документирование системы в целом должно быть первым этапом ее проектирования и разработки.

 

Визуализация развертывания систем

Развертывание системы — последний этап в ее разработке. При развертывании системы имеет смысл смоделировать реальные физические компоненты исполняемой версии системы. Диаграмма развертывания отображает конфигурацию элементов оборудования и программных компонентов. Программные компоненты представляют собой такие реальные выполняемые модули, как активные объекты (процессы), библиотеки, базы данных и пр. Диаграмма развертывания состоит из узлов и компонентов. Компоненты - это экземпляры физической реализации логических элементов. Например, класс— это логический элемент, который может быть реализован в виде одного или нескольких компонентов. Класс можно разделить на процессы или потоки, и каждый процесс или поток в диаграмме развертывания может быть компонентом. Компоненты класса могут выполняться на различных узлах одного компьютера (потоки/процессы) или различных компьютерах (процессы).

Узел обозначается в виде куба. Узлы соединяются связями. Компоненты и узлы также могут соединяться связями. Как упоминалось выше, узел может содержать список компонентов, либо компонент может быть отображен отдельно от узла, но при этом необходимо показать связь между ними. Компонент можно представить в виде прямоугольника с указанием тегов в его левой части. Имя компонента указывается внутри его символьного обозначения.

Для отображения более крупных частей системы компоненты можно сгруппировать в пакеты или подсистемы. Пример диаграммы развертывания показан на рис. 10.18. Здесь пользователи подключаются к системе через intranet. Узлы являются частью кластера компьютеров. Они группируются в пакет. Пользователи подключаются к кластеру как к единому элементу. В каждом узле перечисляются программные компоненты, которые на немустановлены. Взаимодействие межлуузлами обеспечивается посредством сетевого узла.

#img_67.png Рис. 10.18. Диаграмма развертывания, использующая пакеты

 

Архитектура системы

Моделирование и документирование архитектуры системы — это ее описание па самом высоком уровне. Гради Буч, Джеймс Рамбау и Айвар Джекобсон определяю, архитектуру как

набор важных решений по организации системы программного обеспечения, выбор структурных элементов и их интерфейсов, посредством которых составляется система, вместе с их поведением, определенным на периоды их сотрудничества, объединение этих структурных и поведенческих элементов в более крупные подсистемы и архитектурный стиль, который направляет эту организацию — эти элементы и их интерфейсы, их варианты взаимодействия и их композицию.

Моделирование и документирование архитектуры системы должно охватывать ее логические и физические элементы, а также структуру и поведение системы на самом высоком уровне.

Архитектура системы — это ее описание с различных точек зрения, но с акцентом на структуре и организации системы. Ниже представлены различные точки зрения.

Прецедент (вариант использования)  Описывает поведение системы с точки зрения конечно г о пользователя

Процесс  Описывает процессы и потоки, используемые в механизмах обеспечения параллелизма и синхронизации

Назначение  Описывает функции системы и услу г и, предоставляемые конечному пользователю

Реализация  Описывает аппаратные компоненты, используемые для создания физической системы

Развертывание  Описывает про г раммные компоненты и узлы, на которых они выполняются, в поставляемой системе

Очевидно, что эти «поля зрения» (представления о системе) частично перекрываются и взаимодействуют между собой. Например, в описании назначения системы могут упоминаться прецеденты, а при описании ее реализации процессы часто представляют в качестве компонентов. Программные компоненты используются как в части реализации, так и части развертывания системы. При описании архитектуры системы очень полезно строить диаграммы, которые отражают каждый из перечисленных выше ее «портретов».

Систему можно разложить иа подсистемы и модули. Подсистемы и модули могут быть подвергнуты дальнейшей декомпозиции и разложены на компоненты, узлы, классы, объекты и интерфейсы. В языке UML подсистемы и модули, используемые на архитектурном уровне документации, называются пакетами. Пакет можно использовать для организации элементов в группу, которая описывает общую цель этих элементов. Пакет представляется в виде прямоугольника со вкладкой (ярлыком), расположенной над его верхним левым углом. Символ пакета должен содержать его название. Пакеты в системе могут связывать отношения, построенные на основе композиции, агрегирования, зависимости и наследования. Для того чтобы отличать один тип пакета от другого, можно использовать индикаторы стереотипов. На рис. 10.19 показаны пакеты, входящие в систему составления расписаний. Для системного пакета используется индикатор <> (<<система>>), а для пакета уровня подсистемы — индикатор «subsystem>> (<<подсистема>>). Подсистемы связаны с системой отношением агрегирования.

Одни пакеты могут содержать другие пакеты. В этом случае имя пакета указывается во вкладке. На рис. 10.19 также показано содержимое каждой подсистемы.

 

Резюме

#img_68.png Рис. 10.19. Пакеты, используемые в системе составления расписаний (NLI- естественно-языковый интерфейс; NLP — обработка данных на естественном языке; NLG — генерация словаря естественного языка)

Модель системы представляет собой своего рода информационное тело, «собранное» с целью изучения системы. При моделировании любой системы не обойтись без документирования ее различных аспектов. Поскольку в создании системы обычно занято множество людей, очень важно, чтобы все они пользовались одним языком. Таким языко м стал у н ифицированный язык м оделирования (United Modeling Language — UML), который представляет собой совокупность графических средств, используемых для проектирования, визуализации, моделирования и документирования артефактов системы программного обеспечения. Этот язык создан Гради Бучем, Джеймсом Рамбау и Айваром Джекобсоном. Язык UML стал фактическим стандартом для моделирования объектно-ориентированных систем. Его средства также успешно можно использовать для моделирования параллельных и распределенных систем в плане описания ее структурных и поведенческих аспектов.

Диа г ра мм ы UML м ожно использовать для моделирования основных модулей системы, отдельных объектов и системы в целом. Объект — это основная «единица» моделирования, используемая во многих диаграммах UML. Композиция, агрегирование, зависимость и наследование — это некоторые из отношений, который могут существовать между объектами. Для отображения поведения объектов и идентификации параллелизма в системе используются диаграммы взаимодействия. Диаграммы сотрудничества позволяют отобразить взаимодействие между объектами, совместно работающими над выполнением некоторой конкретной задачи. Для представления взаимодействия между объектами во времени используются диаграммы последовательностей. С помощью диаграмм состояний можно отобразить действия одного объекта в течение всего периода его существования. Для распределенных объектов преусмотрена возможность указать их местоположение в системе.

Диаграммы развертывания используются для моделирования системы с точки зрени я их поставки. Базовыми элементами диаграммы развертывания являются узлы и компоненты. Узлы представляют блоки оборудования, а компоненты— части программного обеспечения. В символах узлов указывается, какие объекты или компоненты установлены на них. При моделировании всей системы базовым элементом является пакет. Пакеты можно использовать для представления систем и подсистем. Межлу пакетами могут существовать отношения, которые также отражаются на диаграмме.