На этом шаге рассмотрим типичные приемы моделирования соединений в системе.
Наиболее общее назначение интерфейсов – моделировать соединения в системах, состоящих из программных компонентов, как Eclipse, . NET или Java Beans. Некоторые компоненты можно заимствовать из других систем, другие – покупать, а иные создавать самостоятельно, "с нуля". В любом случае вам придется писать связующий код, предназначенный для их соединения. А это потребует понимания интерфейсов, предоставляемых и требуемых каждым компонентом.
Идентификация соединений в системе включает в себя идентификацию четких линий разделения архитектуры. С каждой стороны от этих линий вы найдете компоненты, которые могут изменяться независимо, не оказывая влияния на противоположный компонент (до тех пор пока компоненты на обеих сторонах придерживаются требований контракта, специфицированного интерфейсом).
Когда вы используете компонент из другой системы или покупаете его, то, вероятно, находите в нем ряд операций с каким-то минимумом документации, где описывается суть каждой из них. Это удобно, но недостаточно. Гораздо важнее для вас понимать порядок, в котором следует вызывать операции, и механизм, который они заключают в себе. Имея малодокументированный компонент, лучшее, что вы можете сделать, – путем проб и ошибок построить концептуальную модель работы его интерфейса. Затем вы вправе изложить свое понимание предмета, моделируя соединение в системе с помощью интерфейсов на UML, с тем чтобы впоследствии вы и другие пользователи без труда в нем разбирались. Точно так же, когда вы создаете свой собственный компонент, то должны обеспечить понимание контекста, в котором он должен применяться, – иными словами, специфицировать интерфейсы, на которые он опирается при выполнении своей работы, а также интерфейсы, которые он предоставляет окружающей среде.
Чтобы смоделировать соединения в системе, выполните следующие действия:
В качестве примера рассмотрим рис. 1, где показаны соединения, окружающие компонент Ledger (Гроссбух), взятый из системы управления финансами.
Рис.1. Моделирование соединений в системе
Этот компонент предоставляет (реализует) три интерфейса: IUnknown (IНеизвестный), ILedger (IГроссбух) и IReports (IОтчеты). На данной диаграмме IUnknown показан в своей расширенной форме, другие два интерфейса – в упрощенной, как "леденцы" (lollipops). Все три интерфейса и экспортированы для использования другими компонентами.
Также на диаграмме показано, что Ledger требует (использует) два интерфейса: IStreaming (IПоток) и ITransaction (IТранзакция), причем второй показан в расширенной форме. Эти два интерфейса необходимы компоненту Ledger для правильной работы. Таким образом, в работающей системе вы должны подставить компоненты, которые реализуют оба этих интерфейса. Идентифицируя такие интерфейсы, как ITransaction, вы получаете эффективно разъединенные компоненты, лежащие по разные стороны интерфейса, что позволяет "нанимать" любой компонент, который соответствует интерфейсу.
Такие интерфейсы, как ITransaction, представляют собой нечто большее, чем пул операций. Указанный интерфейс делает определенные предположения о порядке вызова его операций. Хотя это здесь и не продемонстрировано, вы должны сопроводить его вариантами использования и перечислить общие способы его применения.
На следующем шаге рассмотрим типичные приемы моделирования статических и динамических типов в UML.