Analysis Patterns 1.0 Help

13. Фасады приложения

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

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

Фасад домена выглядит так же, как и любой другой тип: у него есть атрибуты и операции. Однако все атрибуты берутся из модели домена. Модели приводятся на примере здравоохранения (13.1). Содержимое фасада (13.2) определяется рядом методов, которые привязаны к каждому атрибуту. Эти методы описывают, как извлекается атрибут, как он обновляется, как можно найти набор доступных значений, как его можно проверить и как можно получить значение по умолчанию.

Некоторые общие методы (13.3) могут использоваться во многих фасадах домена, поэтому их можно перенести в доменные модели. Фасады домена также содержат операции (13.4), которые могут быть локальными для фасада или делегированными в доменную модель. Фреймворки пользовательского интерфейса обычно не знают о множестве взаимосвязанных типов в доменной модели, поэтому приложение может выполнять преобразования типов (13.5), создавая более примитивные типы, понятные пользовательскому интерфейсу. Приложение часто содержит несколько фасадов (13.6), которые могут быть описаны с помощью структурной модели.

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

13.1 Пример из области здравоохранения

Фасады домена лучше всего понимать на основе достаточно сложной и абстрактной модели домена. На рис. 13.1 показана такая модель, базовая структура которой основана на модели Cosmos, разработанной для здравоохранения [1]. Дальнейшее объяснение многих идей можно найти в главе 3, и, возможно, стоит прочитать эту главу, прежде чем продолжить работу над этой главой.

13 1

Рисунок 13.1. Пример модели домена из области здравоохранения. Это модель, на основе которой строится уровень домена.

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

Модель описывает всю информацию, которая может быть записана о пациенте, в терминах биологических явлений и типов биологических явлений. Например, существует тип биологического явления «пол» с биологическими явлениями «мужчина» и «женщина», а также тип биологического явления «группа крови» с биологическими явлениями «A», «B», «A/B» и «O». Чтобы сказать, что у пациента группа крови «O», мы используем наблюдение, которое связывает пациента с соответствующим биологическим явлением. Мы также можем указать другую соответствующую информацию о наблюдении, например, кто его сделал (исполнитель), когда оно было сделано (дата) и как оно было сделано (протокол). Если впоследствии выяснится, что это неверно и правильная группа крови — А, то мы отбрасываем исходное наблюдение и заменяем его новым. Это необходимо для того, чтобы иметь полную запись о пациенте.

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

13.2 Содержание фасада

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

13 2

Рисунок 13.2. Составные части фасада домена.

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

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

  • Фасад приложения: донор

  • Тема: пациент

  • Атрибуты: — имя: строка — группа крови: биологическое явление — дата последнего переливания крови: дата

  • Операции: — заказать анализ крови

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

13.2.1 Типы методов

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

Метод проверки предоставляет набор допустимых значений, которые можно использовать для проверки валидности. Часто (как в случае с именем) не существует конечного набора допустимых значений; для проверки достаточно типа. Для группы крови, однако, требуется нечто более сложное: тип атрибута — биологическое явление, но допускаются только такие у которых тип биологического явления — группа крови. Таким образом, легальные значения предоставляются запросом, который возвращает набор биологических явлений A, B, A/B и O. Помимо того, что эти значения полезны для проверки достоверности, их можно использовать для заполнения меню или списка в пользовательском интерфейсе.

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

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

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

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

НАЗВАНИЕ МЕТОДА

ОПИСАНИЕ

Извлечение

Значение в соответствии с доменной моделью

Допустимые значения

Список значений, если типа недостаточно

Обновление

Как обновить модель при изменении значения. Для многозначных атрибутов необходимо указать как добавление, так и удаление обновлений.

Валидация

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

По умолчанию

Начальное значение, которое будет использоваться при создании нового объекта из фасада

Таблица 13.1 Краткое описание методов.

13.2.2 Примеры методов

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

13.3 Общие методы

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

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

valueOf (aBiologicalPhenomenonType): aBiologicalPhenomenon.

Атрибут

Метод

Тело метода

Имя

Получение

subject.name

Обновление

Изменить subject.name

Группа крови

Получение

subject.observation. Биологические явления где тип = «группа крови»

Обновление

oldObs:= все subject.observation где тип явления = «группа крови». Создает новое наблюдение (newObs), где newObs.patient = subject, newObs.bioPhenomenon = new BloodGroup, и newObs.rejectedObs = oldObs.

Доступные значения

Все биологические явления с типом «группа крови».

Дата последнего переливания

Получение

Последний subject.observation.date среди subject.observation.protocol = «blood transfusion»

Обновление

Создать новое наблюдение с patient = subject, protocol = «blood transfusion», и date = дата последнего переливания

Валидация

новая «дата последнего переливания» новее, чем предыдущая «дата последнего переливания»

Таблица 13.2 Примеры методов для фасада.

Обратите внимание, что для пациента может существовать соответствующая операция обновления, которая также будет включать в себя метод обновления фасада домена.

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

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

13.4 Операции

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

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

13 3

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

Рисунок 13.3 Операции в фасадах приложений.

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

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

13.5 Преобразования типов

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

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

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

13 4

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

Рисунок 13.4 Примеры объектов для преобразования типов.

Таким образом, атрибут группы крови имеет соответствующий словарь BloodGroupValues в части класса. Ключами этого словаря являются строки 'A', 'B' и так далее, а значениями — объекты в базе данных. При получении группа крови переводится в строку (с помощью функции имени или словаря) и сохраняется в атрибуте. При обновлении новая строка используется для поиска в словаре, а соответствующее значение используется для обновления в базе данных.

При использовании этого подхода мы должны описывать атрибуты фасада как имеющие внутренний и внешний типы. Внутренний тип — это тип в доменной модели, а внешний тип — это тип, предоставляемый в представлении. В примере с группой крови внутренний тип — Biological Phenomenon, а внешний — String.

13.6 Несколько фасадов

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

Структурная модель, показанная на рис. 13.5, иллюстрирует, как связаны эти фасады. Я использую агрегирование для отображения информации, отображаемой в одной презентации (например, в таблице), и обычные ассоциации для информации, отображаемой при открытии другой презентации. Аналогичным образом я использую однонаправленные ассоциации, чтобы отразить пути, по которым может идти пользователь, открывая одну презентацию из другой.

13 5

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

Рисунок 13.5 Пример диаграммы фасадов домена.

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

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

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

Ссылки

  1. Cairns, T., A. Casey, M. Fowler, M. Thursz, and H. Timimi. The Cosmos Clinical Process Model. National Health Service, Information Management Centre, 15 Frederick Rd, Birmingham, B15 1JD, England., Report ECBS20A & ECBS20B http://www.sm.ic.ac.uk/medicine/cpm, 1992.

Last modified: 16 January 2025