Пример из практики и законченная глава, посвященная шаблонам из моей книги, были недавно перенесены в MEAP , и вот еще один шаблон из главы 6 (шаблоны для потребителей услуг):
Когда мы пытаемся думать о потребителях услуг, очевидными кандидатами, конечно же, являются другие услуги. Тем не менее, существуют другие программные компоненты, которые взаимодействуют со службами, например, устаревшие системы, внешние системы, отличные от SOA, или базы данных отчетов. Шаблон Composite Frontend имеет дело с еще одним типом потребителя услуг — пользовательским интерфейсом.
Сначала давайте просто убедимся, что пользовательские интерфейсы на самом деле не являются сервисами. Одна из причин, по которой пользовательские интерфейсы не являются сервисами, заключается в том, что они объединяют несколько бизнес-областей, например, если вы хотите ввести заказ, вам, вероятно, также понадобится поискать информацию о клиенте, возможно, вы также захотите просмотреть каталог продуктов, посмотрите открытые счета и т. д. В дополнение к конвергенции пользовательские интерфейсы доставляют данные, а не обрабатывают их. Пользовательские интерфейсы являются производителями данных (на самом деле есть одно исключение из этого — где пользовательский интерфейс является фронтом «человеческой службы», см. Оркестрованную схему хореографии (в главе 7) для более подробной информации.
Итак, пользовательские интерфейсы не являются службами, это имеет значение? Ну, это так, и проблема не в том, что пользовательские интерфейсы не являются сервисами как таковыми. Основная проблема, связанная с пользовательскими интерфейсами, связана с их основным отличием, то есть объединением или конвергенцией нескольких служб в единый и полезный пользовательский интерфейс.
6.1.1 Проблема
Чтобы лучше понять проблемы, вызванные пользовательским интерфейсом, работающим с несколькими сервисами, давайте рассмотрим пример с одной точкой трения.
В проекте, над которым я работал, мы разработали систему C4ISR (командование, управление, связь, компьютеры, разведка, наблюдение и разведка) для беспилотного военно-морского патрульного корабля (UNPV). Одна из служб в системе была названа «Общая операционная картина» или сокращенно COP. Ответственность КС заключалась в том, чтобы обрабатывать все, что обнаруживается датчиками, например корабли, самолеты и т. Д. (Есть технический жаргон для всего, что касается целей, обнаружений, следов и т. Д., Но это здесь не важно). Одним из основных представлений пользовательского интерфейса КС была карта, такая как та, что на рис. 6.4 ниже, на которой были показаны все обнаружения. Нажав на значок карты, скажем, корабль, вы увидите некоторую информацию, которую знает об этом КС, например, идентификатор, национальность, курс и т. Д.
Рис. 6.4. Упрощенная иллюстрация внешнего интерфейса для службы «Common Operational Picture» военно-морской системы командования и управления. Мы видим береговую линию и затем используем символику НАТО: 2 радара, подводная лодка и корабль (беспилотный военно-морской патрульный автомобиль)
Система имела несколько других услуг, помимо КС, среди которых была «служба UNPV». Служба UNPV отвечала за все, например, за саму UNPV, устанавливая его на навигационном курсе, поворачивая его и т. Д. Служба UNPV имела несколько экранов пользовательского интерфейса, позволяющих управлять и контролировать эти функции. Еще одна обязанность службы UNPV заключалась в том, чтобы отправить свое местоположение в COP (местоположения являются обязанностью COP, помните?), Поэтому в пользовательском интерфейсе одной из значков карты является UNPV.
Что происходит, когда пользователь нажимает на значок UNPV на карте? Помните, что в то время как желаемым результатом является отображение всплывающего окна с параметрами, связанными с управлением UNPV, щелчок находится на карте, элемент управления, обслуживаемый другой службой (КС). В объектно-ориентированной системе UNPV может быть подклассом обнаружения, чтобы он мог принять одно и то же событие и ответить немного по-другому (более специализированным образом). Здесь, однако, КС и UNPV — это совершенно разные услуги, разработанные двумя разными группами и, возможно, даже двумя разными компаниями.
Возможно, мы сможем отклонить этот конкретный пример и просто решить его с помощью конкретного решения, например, добавить оператор «если» где-нибудь для вызова правильных команд и взаимодействия с правильными службами. Проблема, однако, в том, что этот пример — лишь вершина айсберга. Например: как мы справляемся с безопасностью? — нам нужно войти в систему для каждой услуги отдельно? Как мы обращаемся с вещами, в которых нуждаются все услуги? Исходная предпосылка SOA заключается в том, что мы получим некое подобие лего предприятия, где мы сможем легко составлять различные бизнес-процессы. Есть ли способ, которым мы можем получить это в пользовательском интерфейсе? В итоге:
Как вы взаимодействуете с несколькими сервисами, получаете интегрированный, целостный пользовательский интерфейс и при этом сохраняете принципы SOA и преимущества модульности?
Один из вариантов, как упомянуто выше, — написать конкретный код клиента. Используя этот подход «приложение», любой конкретный состав услуг. Для приведенного выше примера приложение будет включать две службы (COP и UNPV) и пользовательский интерфейс, который связывает их вместе. Преимущество этого подхода заключается в том, что каждое приложение обеспечивает согласованное взаимодействие с пользователем. В конце концов, конкретное или индивидуальное применение может быть очень сплоченным. Кроме того, существует множество проверенных и проверенных способов создания гибких пользовательских интерфейсов с надлежащим разделением задач, например, с использованием Model-View-Controller и его разновидностей (во множестве богатых клиентских и веб-технологий), поэтому мы, вероятно, сможем использовать некоторые логики на стороне пользовательского интерфейса, даже переходя от приложения к приложению. Тем не менее, мы теряем гибкость. Для одного,любое изменение службы, имеющее аспекты пользовательского интерфейса, должно быть переделано для каждого из его экземпляров пользовательского интерфейса (приложений). Более того, поскольку пользовательский интерфейс специально связывает несколько сервисов, изменения в одном сервисе могут привести к неправильной работе другого в унифицированном пользовательском интерфейсе. Мы также теряем на Composability или способность заменить услуги и создавать новые бизнес-потоки (относительно) легко. В целом это плохой вариант в долгосрочной перспективе, но его можно использовать в качестве краткосрочного решения.
Схожим вариантом является использование аналогичного подхода, связывающего несколько сервисов вместе, но вместо того, чтобы интегрировать их на стороне клиента, мы интегрируем сервисы вместе на стороне сервера. Этот подход разделяет его плюсы и минусы с предыдущим решением. Однако существуют определенные обстоятельства, в которых это имеет смысл, и вы можете прочитать о них в следующем шаблоне (раздел 6.5 Клиент / Сервер / Сервис)
Наконец, у нас есть возможность иметь независимые компоненты пользовательского интерфейса для каждой службы. Это позволит преодолеть ограничения, о которых мы упоминали выше, поскольку соответствующий пользовательский интерфейс каждого сервиса может развиваться независимо, и вы можете просто создать столько из них, сколько захотите, для создания приложения. К сожалению, при всех своих преимуществах это даже не вариант здесь, так как по определению у нас не будет механизмов для компонентов пользовательского интерфейса, которые работают между службами. т.е. это не решит проблемы, подобные той, что в примере, и мы не сможем получить целостный интерфейс.
6.1.2 Решение
По сути, нам нужен способ объединения сервисов, сохраняя при этом их соответствующую автономию с одной стороны и предоставляя механизмы для их склеивания в единое целое — вот что такое шаблон Composite Frontend:
Примените шаблон составного внешнего интерфейса для агрегирования сервисов, предоставляя им унифицированные клиентские сервисы, такие как компоновка и тематика, а также сервисы координации для интеграции сервисов на стороне клиента.
Примените шаблон составного внешнего интерфейса для агрегирования сервисов, предоставляя им унифицированные клиентские сервисы, такие как компоновка и тематика, а также сервисы координации для интеграции сервисов на стороне клиента.
Рисунок 6.5. Составной шаблон внешнего интерфейса. Каждая служба имеет портлет, который является агентом службы в сочетании с логикой пользовательского интерфейса (скорее всего, модель в шаблоне пользовательского интерфейса MVC). Хост пользовательского интерфейса предоставляет сервисы для различных фрагментов, чтобы объединить их в единый интерфейс.
Шаблон Composite Frontend предназначен для того, чтобы взять идеи (а иногда и технологии) за веб-портал и применить их к сервисам SOA. Веб-порталы предоставляют единую точку доступа, которая объединяет несколько веб-страниц. Они также обеспечивают единый вход и персонализацию. Интерфейсам SOA нужно это и многое другое.
Составной интерфейсный шаблон состоит из двух основных компонентов: портлета и хоста. Портлеты являются строительными блоками, «композитами», которые объединены вместе для формирования пользовательского интерфейса. Портлеты состоят как минимум из двух компонентов. Логика пользовательского интерфейса (представления и контроллеры в языке MVC). Второй компонент, сервисный прокси (или агент), является более интересным с точки зрения SOA. Прокси-сервер службы представляет собой представление службы на стороне клиента. Прокси-сервер служит моделью для компонентов пользовательских интерфейсов. Обычно рекомендуется иметь один прокси для каждой службы — так же, как рекомендуется для каждой службы поддерживать свое собственное хранилище данных. Кроме того, с точки зрения управления продуктом его можно рассматривать как часть самой услуги
Хост — это «добавленная стоимость» части составного шаблона внешнего интерфейса. Хост предоставляет клей, который связывает разные портлеты в единое целое. Таким образом, хост предоставляет несколько ролей. Во-первых, это холст или поверхность, на которой отображаются портлеты. Кроме того, он контролирует жизненный цикл портлетов и, наконец, предоставляет возможности (избегая загруженных терминов служб…), такие как обмен данными между портлетами и единый вход.
Давайте вернемся к проблеме, обсуждавшейся в предыдущем разделе. У нас был щелчок правой кнопкой мыши на компоненте пользовательского интерфейса, который должен был создать контекстное меню с опциями двух сервисов. Как бы это было с композитным интерфейсом? Один из вариантов заключается в том, что хост сначала перехватит щелчок, который затем отправит его любому зарегистрированному портлету. Другой вариант, показанный на рисунке 6.6 ниже, предназначен для перехвата щелчка первым портлетом Common Operation Picture (или COP), чтобы он уведомил хост, а хост попросил все портлеты iixnvolved для отображения меню правого щелчка. Портлет COP должен передавать достаточно информации как часть события, чтобы другие портлеты могли что-то сделать с ними.
Рисунок 6.6. Пример потока событий в составном интерфейсе. События перехватываются компонентами пользовательского интерфейса отдельных портлетов. События передаются на хост, который отправляет их зарегистрированным протетам для обработки. Хост может затем представить результаты для отображения
Составной шаблон внешнего интерфейса представляет собой шаблон потребителя службы, поэтому прокси-сервер будет использовать различные шаблоны взаимодействия служб, такие как saga, запрос / ответ и т. Д. (См. Главу 5), и он может использовать различные шаблоны компоновки служб, такие как Service Registry и Servicbus (см. Главу). 7)
Вы, вероятно, заметили использование термина портлеты для описания сервисных агентов, и вам может быть интересно, почему шаблон называется Composite Frontend, а не Portal. Основная причина этого заключается в том, что шаблон также можно использовать с реализациями с расширенными возможностями клиентов, а не только с веб-интерфейсами — давайте рассмотрим это далее в разделе «Отображение технологий».
6.1.3 Картографирование технологий
Как правило, вы не будете разрабатывать свой собственный контейнер Composite Frontend, а вместо этого будете использовать существующие продукты, которые предоставляют среду и, как правило, инструменты для создания портлетов.
Очевидным примером этого являются платформы веб-порталов. Современные корпоративные веб-порталы обычно поддерживают что угодно — от JSR 168/286 (спецификация Java-портлета) до WSRP (веб-сервисы для удаленного портлета), чтобы открывать веб-стандарты, такие как RSS, простые REST-сервисы или стандарты, такие как open social. В этой области существует множество продуктов, как коммерческих, таких как сервер портала ibm WebSphere и Microsoft Sharepoint, так и варианты с открытым исходным кодом, такие как Jboss Gatein и Lifray. На рисунке 6.7 ниже показана функциональность макета хоста пользовательского интерфейса в том виде, как он реализован в Jboss Gatein.
Рисунок 6.7: Возможность компоновки хоста пользовательского интерфейса Composite Frontend, реализованного на портале Jboss Gatein.
Веб-порталы — не единственный вариант реализации составных интерфейсов. Вы также можете реализовать концепцию для настольных («богатых клиентов») приложений. Примером этого является структура призмы, созданная группой Microsoft Pattern and Practices. Prism реализует шаблон составного внешнего интерфейса для приложений Silverlight и WPF. Prism предоставляет все функциональные возможности хоста пользовательского интерфейса и позволяет создавать портлеты, использующие эти возможности. В приведенном ниже фрагменте кода 6.4 демонстрируется использование средства EventAggregator, которое обеспечивает связь между портлетами (например, ту, которая необходима для примера сценария в примере компонента карты выше):
Листинг кода 6.4 Пример использования EventAggregator в Prism для отправки событий между различными портлетами, объединенными оболочкой prism
[Export(typeof(SampleView))] public partial class SampleView : UserControl { [ImportingConstructor] public SampleView([Import] IEventAggregator eventAggregator { InitializeComponent(); eventAggregator.GetEvent>().Subscribe(OnItemSelectedReceived); #1 } public void ItemSelectedReceived(ItemSelectedEvent item) { //do something with item... } }
# 1 подписка на temSelectedEvent. Другой портлет может вызвать get для EventAggregator, чтобы получить ссылку на событие и вызвать ее, не зная, есть ли подписчики.
Наконец, в дополнение к фреймворкам веб-порталов и десктопам вы можете реализовать собственную реализацию Composite Frontend. однако, как уже упоминалось выше, обычно лучше выбрать один из доступных вариантов, так как это правильное вложение.
6.1.4 Атрибуты качества
Прежде чем перейти к следующему шаблону, давайте рассмотрим некоторые бизнес-факторы (или сценарии), которые могут побудить нас использовать шаблон Composite Frontend.
По сути, основными драйверами Composite Frontend являются гибкость добавления и изменения сервисов и потребность в интегрированном пользовательском интерфейсе, который воспринимается как единое целое. В таблице 6.X приведены примеры обоих атрибутов качества:
Атрибут качества (уровень1) |
Атрибут качества (уровень2) |
Пример сценария |
Удобство использования | работоспособность | При нормальном использовании системы конечный пользователь хочет свободно выполнять бизнес-задачи. Система должна повторно использовать введенные данные (например, личные данные) между различными задачами |
гибкость | Changability | В обычных условиях изменение процесса выставления счетов для поддержки нового поставщика услуг по оформлению кредитных карт может занять не более одной недели |
Таблица 6.3. Сценарии атрибутов качества составного внешнего интерфейса. Это архитектурные сценарии, которые могут заставить нас задуматься об использовании составного шаблона внешнего интерфейса.
Composite Frontend, вероятно, является предпочтительным способом предоставления пользовательского интерфейса SOA. Однако одна проблема, которую нам еще предстоит решить с помощью интеграции UI, — это UI, которые не поддерживают SOA — например, что происходит, когда у нас есть существующий UI, который мы хотим предоставить сервисам? Следующая модель попытается ответить именно на это.