- •Оглавление
- •Предисловие
- •Введение
- •Часть I Обзор Глава 1 "Расслоение" системы
- •Развитие модели слоев в корпоративных программных приложениях
- •Три основных слоя
- •Где должны функционировать слои
- •Глава 2 Организация бизнес-логики
- •Выбор типового решения
- •Глава 3 Объектные модели и реляционные базы данных
- •Архитектурные решения
- •Функциональные проблемы
- •Считывание данных
- •Взаимное отображение объектов и реляционных структур
- •Отображение связей
- •Наследование
- •Реализация отображения
- •Двойное отображение
- •Использование метаданных
- •Соединение с базой данных
- •Другие проблемы
- •Дополнительные источники информации
- •Глава 4 Представление данных в Web
- •Типовые решения представлений
- •Типовые решения входных контроллеров
- •Дополнительные источники информации
- •Глава 5 Управление параллельными заданиями
- •Проблемы параллелизма
- •Контексты выполнения
- •Изолированность и устойчивость данных
- •Стратегии блокирования
- •Предотвращение возможности несогласованного чтения данных
- •Разрешение взаимоблокировок
- •Транзакции
- •Типовые решения задачи обеспечения автономного параллелизма
- •Параллельные операции и серверы приложений
- •Дополнительные источники информации
- •Глава 6 Сеансы и состояния
- •В чем преимущество отсутствия "состояния"
- •Состояние сеанса
- •Глава 7 Стратегии распределенных вычислений
- •Соблазны модели распределенных объектов
- •Интерфейсы локального и удаленного вызова
- •Когда без распределения не обойтись
- •Сужение границ распределения
- •Интерфейсы распределения
- •Глава 8 Общая картина
- •Предметная область
- •Источник данных
- •Платформы и инструменты
- •Другие модели слоев
- •Часть II Типовые решения Глава 9 Представление бизнес-логики Сценарий транзакции (Transaction Script)
- •Модель предметной области (Domain Model)
- •Модуль таблицы (Table Module)
- •Слой служб (Service Layer)
- •Глава 10 Архитектурные типовые решения источников данных Шлюз таблицы данных (Table Data Gateway)
- •Шлюз записи данных (Row Data Gateway)
- •Активная запись (Active Record)
- •Преобразователь данных (Data Mapper)
- •Глава 11 Объектно-реляционные типовые решения, предназначенные для моделирования поведения Единица работы (Unit of Work)
- •Коллекция объектов (Identity Map)
- •Загрузка по требованию (Lazy Load)
- •Глава 12 Объектно-реляционные типовые решения, предназначенные для моделирования структуры Поле идентификации (Identity Field)
- •Отображение внешних ключей (Foreign Key Mapping)
- •Отображение с помощью таблицы ассоциаций (Association Table Mapping)
- •Отображение зависимых объектов (Dependent Mapping)
- •Внедренное значение (Embedded Value)
- •Сериализованный крупный объект (Serialized lob)
- •Наследование с одной таблицей (Single Table Inheritance)
- •Наследование с таблицами для каждого класса (Class Table Inheritance)
- •Наследование с таблицами для каждого конкретного класса (Concrete Table Inheritance)
- •Преобразователи наследования (Inheritance Mappers)
- •Глава 13 Типовые решения объектно-реляционного отображения с использованием метаданных Отображение метаданных (Metadata Mapping)
- •Объект запроса (Query Object)
- •Хранилище (Repository)
- •Глава 14 Типовые решения, предназначенные для представления данных в Web Модель-представление-контроллер (Model View Controller)
- •Контроллер страниц (Page Controller)
- •Контроллер запросов (Front Controller)
- •Представление по шаблону (Template View)
- •Представление с преобразованием (Transform View)
- •Двухэтапное представление (Two Step View)
- •Контроллер приложения (Application Controller)
- •Глава 15 Типовые решения распределенной обработки данных Интерфейс удаленного доступа (Remote Facade)
- •Объект переноса данных (Data Transfer Object)
- •Глава 16 Типовые решения для обработки задач автономного параллелизма Оптимистическая автономная блокировка (Optimistic Offline Lock)
- •Пессимистическая автономная блокировка (Pessimistic Offline Lock)
- •Блокировка с низкой степенью детализации (Coarse-Grained Lock)
- •Неявная блокировка (Implicit Lock)
- •Глава 17 Типовые решения для хранения состояния сеанса Сохранение состояния сеанса на стороне клиента (Client Session State)
- •Сохранение состояния сеанса на стороне сервера (Server Session State)
- •Сохранение состояния сеанса в базе данных (Database Session State)
- •Глава 18 Базовые типовые решения Шлюз (Gateway)
- •Преобразователь (Mapper)
- •Супертип слоя (Layer Supertype)
- •Отделенный интерфейс (Separated Interface)
- •Реестр (Registry)
- •Объект-значение (Value Object)
- •Деньги (Money)
- •Частный случай (Special Case)
- •Дополнительный модуль (Plugin)
- •Фиктивная служба (Service Stub)
- •Множество записей (Record Set)
- •Список типовых решений
- •Шпаргалка
- •Как управлять сложным потоком функций приложения?
- •Как взаимодействовать с базой данных?
- •Как избежать загрузки в оперативную память всего содержимого базы данных?
- •Как сохранить структуры наследования в реляционной базе данных?
Типовые решения входных контроллеров
Существует два типовых решения проблемы организации входных контроллеров. Наиболее общий подход состоит в создании объекта входного контроллера для каждой страницы Web-сайта. В простейшем случае подобный контроллер страниц (Page Controller) можно оформить в виде страницы сервера, сочетая в нем функции представления и входного контроллера. Во многих ситуациях, однако, легче выделить входной контроллер в самостоятельный объект. Нередко взаимно однозначного соответствия между контроллерами страниц и представлениями не существует. Точнее говоря, следует иметь контроллер страниц для каждого действия, где действием является кнопка или гиперссылка. В большинстве случаев действия соответствуют страницам, но бывает и так, что ссылка, например, указывает на разные страницы в зависимости от определенного условия.
На входной контроллер возлагаются две основные обязанности: обработка HTTP-запроса и принятие решения о том, что с ним делать дальше, которые зачастую имеет смысл разделить, поручив первую функцию странице сервера, а вторую — вспомогательному объекту. В то же время типовое решение контроллер запросов (Front Controller) предусматривает использование единственного объекта, предназначенного для обработки всех запросов. Обработчик интерпретирует полученный адрес URL, определяет, с какого рода запросом он имеет дело, и создает отдельный объект для дальнейшего обслуживания запроса. Таким образом удается централизовать деятельность по обработке всех HTTP-запросов в рамках единого объекта и избежать необходимости изменения конфигурации Web-сервера в случае модификации структуры действий сайта.
Дополнительные источники информации
В большинстве книг по Web-технологиям найдется пара глав, посвященных удачным образцам организации Web-серверов (подобная информация, однако, часто изобилует ненужными деталями). Прекрасный пример Java-проекта обсуждается в главе 9 руководства [9]. Лучший источник информации о других типовых решениях — книга [3]; многие из них не привязаны к Java и носят универсальный характер. Терминология, касающаяся разделения функций входного контроллера и контроллера приложения, заимствована из [25].
Глава 5 Управление параллельными заданиями
Мартин Фаулер и Дейвид Райе
Параллельное (concurrent) выполнение операций — одна из наиболее сложных дисциплин в области разработки программного обеспечения. Проблемы параллелизма возникают всякий раз, когда, скажем, несколько процессов или потоков вычислений предпринимают попытки манипуляций одними и теми же элементами данных. Восприятие множества параллельных операций затруднено, поскольку перечислить все возможные сценарии развития событий, способные привести к тем или иным неприятностям, крайне сложно. Что бы вы ни делали, всегда кажется, что какие-то вещи упущены. Более того, параллельные операции трудно тестировать. Всем нам нравятся средства автоматического тестирования, сопровождающие процессы разработки программного обеспечения от начала и до конца, но найти тесты, которые смогли бы убедить в достаточной надежности параллельного кода, практически невозможно.
Забавно и парадоксально, что с возрастанием степени параллелизма операций в корпоративных приложениях разработчики все меньше заботятся о сопутствующих проблемах. Причиной подобного легкомысленного отношения служит наличие готовых подсистем — диспетчеров транзакций. Модель транзакций позволяет избежать массы трудностей: если вы манипулируете данными внутри транзакции, будьте уверены, что ничего плохого с ними не случится.
Впрочем, это не значит, что проблемами управления параллельными заданиями можно полностью пренебречь, так как многие аспекты взаимодействия приложения и системы нельзя свести к контексту единой транзакции, обращенной к базе данных, — во многих случаях приходится иметь дело с данными, модифицируемыми несколькими транзакциями. Последняя задача получила название автономного параллелизма (offline concurrency).
Еще одна ситуация, в которой феномен параллелизма проявляет свою угрожающую сущность, связана с серверами приложений, поддерживающими множество одновременно протекающих потоков вычислений. Впрочем, автору прикладной программы беспокоиться не о чем — все обязанности принимает на себя серверная платформа.
Чтобы разобраться в проблемах, надлежит освоиться по меньшей мере с некоторыми базовыми понятиями; с этого и начнем. Однако не стоит трактовать эту главу как сколько-нибудь полное введение в технологии управления параллельными операциями, так как для достижения подобной цели потребовалась бы, как минимум, толстенная книга. Вы познакомитесь с аспектами параллелизма, имеющими отношение к корпоративным программным приложениям. Затем на ваш суд будут представлены типовые решения в области управления параллельными заданиями в автономном режиме и некоторые подходы к обеспечению многопоточного функционирования серверов приложений.
На протяжении всей главы для иллюстрации концепций параллелизма приводятся примеры из области, которая, вероятно, вам хорошо знакома: речь идет о системах контроля версий исходного кода, которые применяются командами разработчиков для координации вносимых изменений. (Между прочим, если вы не осведомлены о подобных системах, то не сможете плодотворно работать над корпоративными приложениями.)
