Лекция № 3. Уровень служб. Обсуждение. Уровень служб. (Service Layer) Логика слоя представления взаимодействует с бизнес логикой через слой служб, который выступает в качестве API приложения. Дополнительно – размещение логики управления транзакциями и обеспечение безопасности Уровень служб. (Service Layer) Основная проблема определяющее решение: Какая часть функций DM передается на SL? Крайность 1. «Скромный» SL SL = промежуточному интерфейсу. Задача этого интерфейса в перенаправлении вызовов из HI объектам лежащим в DM. SL обеспечивает API, ориентированный на определенные варианты использования и предоставляет возможность включить в код функции-оболочки отвечающие еще за чтонибудь. Например, управление транзакциями, проверку безопасности и т.д. Крайность 2. «Толстый» SL Большая часть логики в рамках SL реализуется в виде сценариев транзакции. Объекты домена в этом случае могут быть тривиальными. Если при этом используется модель предметной области, то можно обеспечить их однозначное отображение на уровень хранения. Например, применив решение активная запись (Active record) Модель «контроллер-сущность» (controller-entity). Главная особенность модели: логика, которая относится к отдельным бизнес-транзакциям или вариантам использования, располагается в соответствующих сценариях транзакции (В этом случае их называют контролерами или службами). Сценарии тразакции выполняют роль контроллеров в типовых решениях MVC и контроллер приложения (Application Controller). Функции, характерные для нескольких вариантов использования, передаются объектам сущностям (entities) домена. Лекция 6. Часть 2. Базовые типовые решения. Шлюз (Gateway). Класс, инкапсулирующий доступ к внешней системе или источнику данных Клиент Скидка Класс, Шлюз к пакету представляющий собой объектную скидок надстройку над этим API Внешняя система, для которой определен или существует некоторый APIинтерфейс Товар Проблема взаимодействия ООП приложений со структурами, которые не являются объектными Шлюз (Gateway). Принцип действия. Идея: 1. Берем некоторый внешний источник. 2. Отвечаем на вопрос: «Какие действия должно совершать приложение по отношению к этому внешнему источнику?» 3. Создаем простой API, наполняем его необходимой функциональностью. 4. Делаем шлюз, который представляет оболочку над API. Вызовы методов шлюза приводят к обращениям к внешнему источнику. Шлюз (Gateway). Принцип действия. Некоторые моменты: Шлюз – основа для реализации фиктивных служб (Service Stub). Изменения в шлюзе ради размещения фиктивной службы оправданы. Шлюз – как можно более простой! Шлюз обрабатывает задания и одновременно обладает минимальной функциональностью. Все более сложное в клиентах шлюза. Шлюз, который создается CASE-средством (системой автоматической генерации кода). Реализация шлюза в терминах двух объектов – прикладной части (back end) и интерфейсной части (front end). Прикладная часть - это минимальная оболочка для функций доступа к внешнему источнику она не упрощает API. Интерфейсная часть преобразует неудобный API в класс, оптимально приспособленный под конкретное приложение. Шлюз (Gateway). Назначение. Некоторые моменты: Применяется, когда интерфейс доступа к внешнему источнику НЕУДОБНЫЙ. Шлюз концентрирует все неудобство в одном месте, а не во всей системе. Шлюз облегчает тестирование, так как предоставляет потенциальную точку внедрения фиктивной службы. Шлюз предоставляет возможность легко переключаться между источниками данных. Это простое и гибкое средство для инкапсуляции изменений. Альтернатива снижения зависимостей от внешних источников преобразователь (Mapper), но он более сложный. Шлюз и похожие решения (Фасад, Адаптер, Медиатор) Фасад – задается разработчиком внешней службы, а шлюз клиентом. Адаптер подстраивает существующие интерфейсы. Медиатор разделяет множество объектов, шлюз только ДВА. В медиаторе объекты знают о существовании объекта медиатора, а в шлюзе источник не подозревает о существовании шлюза. Преобразователь (Mapper). Класс, устанавливающий связь между двумя независимыми объектами Клиент Скидка Класс, представляющий Преобразователь собой объектную к пакету скидок надстройку над этим API Внешняя система, для которой определен или существует некоторый APIинтерфейс Товар Проблема установления взаимодействия между двумя подсистемами, которые при этом не должны знать о существовании друг друга Преобразователь (Mapper). Принцип действия. Некоторые моменты: Преобразователь – «изоляционный слой» между подсистемами. Основное назначение: перемещение данных из одной подсистемы в другую. Основная проблема: кто запускает преобразователь? Принцип работы зависит от природы отображаемых слоев. Наиболее часто используется преобразователь данных (Data Mapper). Преобразователь (Mapper). Назначение. Преобразователь – Шлюз. Последний лучше, в смысле проще. Условие использование преобразователя – независимость. Преобразователь и Медиатор. Объекты использующие медиатор знают об его наличии, даже если им неизвестно о существовании друг друга. Объекты разделенные преобразователем НЕ знают о существовании друг друга. Супертип слоя (Layer Supertype). Тип, выполняющий роль суперкласса для всех классов своего слоя. Проблема: что делать, если одни и те же методы дублируются во всех объектах слоя? Принцип действия: Создается класс, который является суперклассом для всех объектов слоя Если в слое несколько разных видов объектов можно создать несколько разных супертипов для этого слоя. Назначение: Используется, если все объекты соответствующего слоя имеют некоторые общие свойства или поведение. Альтернатива – композитное делегирование. Отделенный интерфейс (Separated Interface). Типовое решение, предполагающее размещение интерфейса и его реализации в разных пакетах. Домен Преобразователь данных Независимый Клиент интерфейс ЕдиницаРаботы (Интерфейс) Зависимая от интерфейса реализация ЕдиницаРаботы (Исполнитель) Заказ Улучшение структуры системы за счет снижения зависимостей между ее составными частями. Выполняем группировку и определяем, кому что можно. Проблема, как осуществить вызов операций, которые противоречат общей структуре зависимостей? Отделенный интерфейс (Separated Interface). Принцип действия. Основная идея: Реализация зависит от своего интерфейса, но не наоборот. Следовательно, интерфейс и его реализацию можно разместить в разных пакетах. Пакет, содержащий реализацию, будет зависеть от пакета, содержащего интерфейс, а вот все другие пакеты, будут могут зависеть от пакета с интерфейсом, но не будут зависеть от пакета с реализацией. Для того, чтобы все заработало, интерфейс кто-то должен реализовывать. Это можно сделать с помощью некоторого третьего пакета, который будет связывать интерфейс с реализацией во время компиляции или связывать их во время инициализации (настройки) приложения посредством типового решения дополнительный модуль (Plugin). Отделенный интерфейс (Separated Interface). Принцип действия. Размещение интерфейса: пакет клиента или в отдельном промежуточном пакете. Решение зависит от того сколько клиентов и кто разрабатывает интерфейс. Проблема создания экземпляра реализации. Чтобы создать экземпляр реализации необходимо знать об ее классе. Часто для этих целей используется объект фабрика = дополнительный модуль. Более простая альтернатива – отдельный пакет, который знает и интерфейсы и реализации. Отделенный интерфейс (Separated Interface). Назначение. Применяется для того, чтобы избежать зависимостей между частями системы. Если в пакете инфраструктуры размещен абстрактный код для обработки стандартных случаев, который должен вызывать конкретный код приложения. Если код одного слоя должен обратиться к коду другого слоя о существовании которого он не знает. Если нужно вызвать чьи-то чужие методы, но нет желания попадать в зависимость от вызова этих методов.