Задача: Проектирование подсистемы
Данная задача посвящена документированию подсистем, их поведения и зависимостей.
Дисциплины: Анализ и проектирование
Назначение
  • Сформулировать поведение, описанное в интерфейсах подсистем, в терминах взаимодействия внутренних элементов и внешних интерфейсов и подсистем.
  • Описать внутреннюю структуру подсистемы.
  • Описать реализацию интерфейсов подсистемы через внутренние классы.
  • Установить зависимость от других подсистем.
Взаимосвязи
Основное описание

 Представление в UML 1.x

Приведенная ниже информация о зависимостях подсистем распространяется и на UML 1.5:


Диаграмма, описанная в тексте.

Пример структуры подсистем с непосредственными зависимостями.

Диаграмма, описанная в тексте.

Пример структуры подсистем с зависимостями через интерфейсы

Дополнительные сведения приведены в разделе Различия между UML 1.x и UML 2.0.

Шаги
Распределить поведение подсистемы на элементы.
Цель: Описать внутреннее поведение подсистемы.
Выявить дополнительные классы проекта и подсистемы проекта, необходимые для удовлетворения требований к поведению подсистем.  

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

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

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

В системах реального времени для инкапсуляции таких нитей будет применяться Рабочий продукт: капсула.

Пример:

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

Диаграмма, описанная в тексте.

На этой диаграмме показано, как интерфейсы подсистем применяются для выполнения последовательности операций. В частности, для подсистемы Network Handling указаны конкретные интерфейсы (в данном случае - ICoordinator) и операции, которые она должна поддерживать. Кроме того, на диаграмме видно, что подсистема NetworkHandling зависит от интерфейсов IBHandler и IAHandler.

Взглянув внутрь подсистемы, можно увидеть, как реализован интерфейс ICoordinator:

Диаграмма, описанная в тексте.

Класс Coordinator выступает в роли посредника для интерфейса ICoordinator и отвечает за обработку операций интерфейса и координацию его поведения.

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

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

При создании новых элементов проекта необходимо пересматривать содержание и границы подсистем. Постарайтесь избежать создания одинаковых классов в разных подсистемах. Наличие таких классов - косвенный признак неоптимального формулирования границ подсистемы. Регулярно возвращайтесь к задаче Задача: Определение элементов проекта для коррекции баланса ответственности подсистем.

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

Создайте описание элементов подсистемы
Цель: Описать внутреннюю структуру подсистемы.  

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

Ниже приведен пример диаграммы класса:

Диаграмма, описанная в тексте.

Пример диаграммы класса для системы регистрации заказов.

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

Ниже приведен пример диаграммы компонентов, на которой показаны подсистема Order, ее внутренние компоненты, предоставляемые и необходимые интерфейсы.

Диаграмма, описанная в тексте.

Пример диаграммы компонентов подсистемы Order

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

На следующей иллюстрации показан пример составной диаграммы структуры подсистемы Order с интерфейсами и портами.

Диаграмма, описанная в тексте.

Пример составной диаграммы структуры подсистемы Order.



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

Описание классов подсистемы создается при выполнении задачи Задача: Проектирование классов.

Опишите зависимости подсистемы
Цель: Описать интерфейсы, от которых зависит подсистема.  

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

Причин тому две:

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

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

Зависимости между подсистемами, равно как зависимости между подсистемами и пакетами, можно описать напрямую, как показано ниже. В данном случае одна подсистема (например, Invoice Management) напрямую зависит от другой (например, Payment Scheduling Management).


Диаграмма, описанная в тексте.

Пример структуры подсистем с непосредственными зависимостями.

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


Диаграмма, описанная в тексте.

Пример структуры подсистем с зависимостями через интерфейсы

 

Дополнительные сведения