2. Язык UML. Руководство пользователя. Буч_ Рамбо_ Якобсон (2-е издание) (2006) (1185732), страница 42
Текст из файла (страница 42)
Поскольку это компоненты одинаковоготипа, их потребуется различать по именам. Другие два компонентатипов SeatAssignment (УказаниеМест) и InventoryManagement (УправлениеСписками) не требуют имен, поскольку присутствуют в одномэкземпляре внутри компонента Air Ticket Sales.Air Ticket SalesБазовые понятия215link). Простая ссылка – это экземпляр обычной ассоциации.
Временная ссылка представляет связь использования между двумякомпонентами. Вместо обычной ассоциации она может быть обеспечена параметром процедуры или локальной переменной, которая служит целью операции. Преимущество портов и интерфейсовв том, что эти два компонента не обязаны ничего «знать» друг о друге на этапе дизайна, до тех пор пока совместимы их интерфейсы.Коннекторы изображаются двумя способами (рис. 15.5). Еслидва компонента явно связаны друг с другом (либо напрямую, либочерез порты), достаточно провести линию между ними или их портами.
Если же два компонента подключены друг к другу, потому чтоимеют совместимые интерфейсы, вы можете использовать нотацию«шарик–гнездо», чтобы показать, что между этими компонентамине существует постоянной связи, хотя они и соединены внутриобъемлющего компонента. Вы в любое время подставите вместокаждого из них любой другой компонент, если он удовлетворяетинтерфейсу.Catalog Sales:SeatAssignmentnormalSales:Sales:Fulfillment:inventory:Findtems:InventoryManagementprioritySales:Sales:ShipItemsпрямой коннекторделегирующий коннектор:OrderHandoff:OrderEntryРис.
15.4. Части одного типаЕсли части представляют собой компоненты с портами, вы можете связать их друг с другом через эти порты. Два порта могут бытьподключены друг к другу, если один из них предоставляет данныйинтерфейс, а другой требует его.
Подключение портов подразумевает, что для получения сервиса требующий порт вызовет предоставляющий . Преимущества портов и интерфейсов в том, чтокроме них больше ничего не важно; если интерфейсы совместимы,то порты могут быть подключены друг к другу. Инструментальныесредства способны автоматически генерировать код вызова одногокомпонента от другого.
Также их можно подключить к другим компонентам, предоставляющим те же интерфейсы, когда таковые появятся и станут доступны. «Проводок» между двумя портами называется коннектором. В экземпляре охватывающего компонента онпредставляет просто ссылку (link) или временную ссылку (transientcharging:Credit:OrderTaking:OrderHandingконнекторчерез интерфейсыРис.
15.5. КоннекторыТакже можно связать внутренние порты с внешними портамиобъемлющего компонента. В таком случае речь идет о делегирующем коннекторе, поскольку сообщения из внешнего порта делегируются внутреннему. Подобная связь изображается стрелочкой,направленной от внутреннего порта к внешнему. Вы можете представить ее двояко, как вам больше нравится. ВоFпервых, можно считать, что внутренний порт – то же самое, что и внешний; он вынесенна границу и допускает подключение извне. ВоFвторых, примите216Компонентыво внимание, что любое сообщение, пришедшее на внешний порт,немедленно передается на внутренний, и наоборот. Это неважно –поведение будет одинаковым в любом случае.В примере на рис.
15.5 показано использование внутренних портов и разных видов коннекторов. Внешние запросы, приходящиена порт OrderEntry (ПередачаЗаказа), делегируются на внутреннийпорт подкомпонента OrderTaking (ПриемЗаказа). Этот компонент,в свою очередь, отправляет свой вывод на свой порт OrderHandoff(ПереводЗаказа). Последний подключен по схеме «шарикFгнездо»к подкомпоненту OrderHandling (УправлениеЗаказами). Данный видподключения предполагает, что у компонентов не существует знаний друг о друге; вывод может быть подсоединен к любому другомукомпоненту, который соответствует интерфейсу OrderHandOff. Компонент OrderHandling взаимодействует с компонентом Inventory (Опись)для поиска элементов на складе.
Это взаимодействие выраженопрямым коннектором; поскольку никаких интерфейсов не показано, можно предположить, что данное подключение более плотно, тоесть обеспечивает более сильную связь. Как только элемент найденна складе, компонент OrderHandling обращается к внешнему сервисуCredit (Кредит) – об этом свидетельствует делегирующий коннектор к внешнему порту changing (изменение).Как только внешний сервис Credit дает ответ, компонент OrderДиаграммывзаимодейст- Handling связывается с другим портом ShipItems (ДеталиДоставки)вия обсужкомпонента Inventory, чтобы подготовить пересылку заказа.
Комподаютсянент Inventory обращается к внешнему сервису Fullfillment (Исполв главе 19.нение) для осуществления доставки.Отметим, что диаграмма компонентов показывает структуруи возможные способы доставки сообщений компонента. Последовательность сообщений в компоненте она, однако, не отражает.Последовательности и другие виды динамической информации могут быть представлены на диаграмме взаимодействия.На заметку. Внутренняя структура, включая порты, частии коннекторы, может быть использована как реализация любыхклассов – не обязательно компонентов. На самом деле нетбольшой разницы в семантике между классами и компонентами.
Однако зачастую удобно применять соглашениео том, что компоненты используются для инкапсуляции концепций, имеющих внутреннюю структуру (в частности, таких,которые не отображаются непосредственно на отдельныйкласс в реализации).Типичные приемы моделирования217Типичные приемы моделированияМоделирование структурированных классовСтруктурированный класс может быть использован для моделирования структур данных, в которых части имеют контекстноFзависимыесоединения, существующие только в пределах класса. Обычныеатрибуты или ассоциации могут определять составные части класса,но части не могут быть связаны друг с другом на простой диаграммеклассов.
Класс, внутренняя структура которого показана с помощьючастей и коннекторов, позволяет избежать этой проблемы.Чтобы смоделировать структурированный класс, необходимо: Идентифицировать внутренние части класса и их типы. Дать каждой части имя, отражающее ее назначение в структурированном классе, а не ее тип. Нарисовать коннекторы между частями, которые обеспечивают коммуникацию или имеют контекстноFзависимые связи. Не стесняться использовать другие структурированные классы как типы частей, но помнить, что подключение к частямнельзя осуществлять внутри другого структурированногокласса – можно подключаться только к их внешним портам.Рис.
15.6 демонстрирует дизайн структурированного классаTicketOrder (ЗаказБилетов). Этот класс имеет четыре части и одинобычный атрибут price (цена). Далее, customer (покупатель) – этообъект Person (Человек); он может иметь или не иметь статус priority(приоритет), поэтому часть priority показана с множественностью0..1. Коннектор от customer к priority имеет ту же множественность.Поскольку каждый клиент вправе бронировать одно или несколькопосадочных мест, у объекта seat (место) тоже есть значение множественности. Нет необходимости показывать коннектор от customerк seats, потому что эти объекты и так находятся в одном структурированном классе.
Отметим, что класс Attraction (Категория) обведен пунктирной рамкой. Это значит, что данная часть представляетсобой ссылку на объект, которым не владеет структурированныйкласс. Ссылка создается и уничтожается вместе с экземпляромкласса TicketOrder, но экземпляры Attraction независимы от классаTicketOrder. Часть seat подключена к ссылке attraction, поскольку заказ может включать посадочные места разных категорий и каждоебронирование билета должно быть сопоставлено определенной категории посадочного места.
Мы видим по значению множественности, что каждое резервирование Seat подключено строго к одномуобъекту Attraction.218КомпонентыМоделирование программного интерфейса APIЕсли вы разрабатываете систему, состоящую из частейFкомпонентов, вам часто требуется видеть интерфейсы прикладного программирования (application programming interfaces, API), посредством которых эти части связываются друг с другом. API представляютпрограммные соединения в системе, которые можно смоделировать,используя интерфейсы и компоненты.По сути, API – это интерфейс, который реализуется одним илинесколькими компонентами. Как разработчик, вы на самом деле заботитесь только о самом интерфейсе – какие именно компоненты реализуют операции интерфейса, неважно до тех пор, пока какойFнибудькомпонент реализует их.
С точки зрения управления конфигурациейсистемы, однако, эти реализации важны, потому что вам необходимобыть уверенным в том, что когда вы опубликуете API, то будет доступна некая соответствующая ему реализация. К счастью, с помощью UML можно смоделировать оба представления.Операции, ассоциированные с любым семантически насыщенным API, будут встречаться достаточно часто, потому в большинстве случаев вам не понадобится визуализировать все их сразу. Напротив, вы будете стремиться к тому, чтобы оставлять операциина периферии ваших моделей и использовать интерфейсы в качестве дескрипторов, посредством которых можно будет найти всеэти наборы операций.
Если вы хотите конструировать исполнимыесистемы на основе таких API, то вам понадобится детализироватьмодели настолько, чтобы инструменты разработки были способныпроизводить компиляцию в соответствии со свойствами интерфейсов. Наряду с сигнатурой каждой операции вы, возможно, захотите отобразить варианты использования, объясняющие, как нужноприменять каждый интерфейс.Чтобы смоделировать API, необходимо: Идентифицировать соединения в системе и смоделироватькаждое из них в виде интерфейса, собирая вместе образующие его атрибуты и операции. Показать только те свойства интерфейса, которые важныдля визуализации в данном контексте; в противном случаескрыть их, сохраняя только в спецификации интерфейса дляпоследующей ссылки (по мере необходимости). Смоделировать реализацию каждого API лишь в той мере,в которой она важна для показа конкретной конфигурации.На рис.