понедельник, 5 декабря 2011 г.

Отзыв на книгу Фаулера "Архитектура корпоративных приложений"


Просмотрел сильно разрекламированную книжку Мартина Фаулера «Архитектура корпоративных приложений» (точная ссылка: Фаулер, Мартин. Архитектура корпоративных приложений.: Пер. с англ. – М.: Издательский дом «Вильямс», 2006. – 544 с.: ил.). Книжка описывает архитектурные паттерны, которые можно использовать при разработке корпоративных (как правило, web-based) приложений. Поскольку такие приложения практически не обходятся без использования базы данных, очень много места в книжке уделяется объектно-реляционному отображению.

А. Общие впечатления.

Основные впечатления от книжки:

1)       Книга не содержит описания архитектур, хотя в названии используется слово «архитектура». Книга содержит отдельные частные решения, которые можно использовать при проектировании – и только-то!

2)       Книга не содержит перечня архитектурных задач (хотя бы неполного). Отсутствует какая-либо модель постановки задач при разработке архитектуры. Что такое творческая задача в архитектуре? Автор об этом умалчивает.

3)       Поскольку описание задач отсутствует, нет критерия для отбора паттернов. Паттерны включены в книгу в произвольном порядке. Приведенные решения не разделены на качественные уровни. В результате «слабые» паттерны соседствуют вместе с «сильными».

4)       Многие паттерны образованы по схеме: «преобразование + объект, к которому оно применяется». В результате паттерны дублируются. Хоть преобразования, лежащие в их основе, одинаковые, но вот объекты разные.

Вывод:
Многое можно свернуть. Думаю, саму книгу объемом в 540 страниц можно свернуть в методическую сильно концентрированную статью.

Б. Подход к проектированию.

Б.1. Разделение на слои.

Мартин Фаулер является сторонником архитектуры с тремя основными слоями:

1)       Источник данных (обращение к базе данных, обмен сообщениями).
2)       Предметная область (бизнес-логика приложения).
3)       Представление (слой презентации бизнес-данных и коммуникации с пользователем).

(Источник: стр. 46.)

Аналогом слоя в системном анализе является системный уровень или уровень абстракции. Каждый слой n-го системного уровня – в предельном случае – может использовать интерфейс слоя (n – 1)-го системного уровня и предоставляет интерфейс для слоя (n + 1)-го системного уровня. На практике этого правила придерживаются не слишком строго. n-ый слой может использовать не только интерфейс (n – 1)-го слоя, но и интерфейсы (n – 2)-го, (n – 3)-го слоев. В свою очередь, интерфейс n-го слоя может использовать не только (n + 1)-ый слой, но и (n + 2)-ой, (n + 3)-й слой и т.д.

Б.2. Представление бизнес-логики.

Для проектирования бизнес-слоя Автор предлагает 3 подхода: надсистемный, системный и подсистемный.

1) Надсистемный подход инкапсулирован в паттерне «Сценарий транзакции» (Transaction Script). Он заключается в том, чтобы выявить запросы, инициируемые слоем представления, и организовать каждый запрос в виде отдельной процедуры.

Положительной стороной такого подхода, на мой взгляд, является то, что система (бизнес-логика) проектируется под нужды надсистемы (представление данных и коммуникация с пользователем), т.е. слой n-го системного уровня создается под нужды (n + 1)-го системного уровня. Собственно, поэтому я и назвал такой метод надсистемным.

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

Из-за этого неудобства М. Фаулер рекомендует применять «Сценарий транзакции» лишь для небольших и несложных систем.

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

2) Системный подход (с точки зрения системы) представлен в виде паттерна «Модель предметной области» (Domain Model). Суть подхода – необходимо построить (объектную) модель предметной области. Как строится такая модель, Автор не раскрывает.

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

К сожалению, М. Фаулер опять смешивает подход и реализацию. Он рекомендует использовать паттерн «Модель предметной области» в случаях, когда бизнес-логика сложна или существуют предположения о том, что она будет усложнена в будущем.

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

Сам подход к проектированию кажется мне неправильным, т.к. требования к функционалу системы всегда выдвигает надсистема.

3) Подсистемный подход (с точки зрения подсистемы) представлен в виде паттерна «Модуль таблицы» (Table Module). Суть подхода: нужно взять таблицы базы данных и для каждой таблицы написать по классу.

На мой взгляд, это – все равно, что сложить дом из кирпичей без всякого проекта. Рекомендации очень легко последовать – нет необходимости продумывать архитектуру бизнес-слоя. Но вряд ли с помощью такого подхода можно построить что-то сложное и безглючное.

Примечание: Иногда бывает полезно «обернуть» таблицу базы данных в некоторый класс, который содержит в себе операции по работе с записями этой таблицы (инкапсулирует в себе запросы к базе данных). Но бизнес-логику на таких «врапперах» («обертках») не построишь.

В. Что Мартин Фаулер понимает под паттерном?

В отличие от ТРИЗ, где под приемом понимается преобразование: увеличить – уменьшить, сделать динамичным – сделать статичным, – паттерны, приведенные в книге, содержат преобразование + объект.

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

·         Шлюз таблицы данных (Table Data Gateway)
·         Шлюз записи данных (Row Data Gateway)
·         Активная запись (Active Record)
·         Преобразователь данных (Data Mapper)

Функцию обмена данными с базой данных можно:

1.       реализовать прямо в классе модели предметной области;
2.       вынести в отдельный слой.

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

Во втором случае, программист разрабатывает класс Загрузчик Пользователя, который выполняет операции загрузки и сохранения и инициализирует объект класса Пользователь.

Первому случаю соответствуют паттерны «Шлюз таблицы данных», «Шлюз записи данных», «Активная запись». Второму случаю соответствуют паттерн «Преобразователь данных».

Если за основу для класса предметной области берется таблица базы данных, то получаем «Шлюз таблицы данных». Если за основу берется лишь отдельная строка таблицы, то получаем либо «Шлюз записи данных», либо «Активную запись».

Таким образом, выходит, что основное различие между паттернами – в объектах, а не в преобразованиях.

Г. Задачи.

По сравнению с книгой «банды четырех», у книги Мартина Фаулера есть преимущество: паттерны сгруппированы в главы по решаемым задачам. Например:

·         «Глава 9. Представление бизнес-логики».
·         «Глава 10. Архитектурные типовые решения для источников данных».
·         «Глава 11. Объектно- реляционные типовые решения, предназначенные для моделирования поведения».
·         И т.д.

Не смотря на это, отсутствует единый перечень задач, решаемых архитектурными паттернами, а сами формулировки – весьма произвольны и иногда содержат в описании объект, а не функцию. Пример: «Глава 10. Архитектурные типовые решения для источников данных».

В некоторых случаях функции сформулированы попросту неправильно. Например, «Глава 11. Объектно-реляционные типовые решения, предназначенные для моделирования поведения» на самом деле содержит паттерны, которые решают задачу «Загружать – не загружать»: когда данные из базы данных загружать надо, но нельзя, т.к. эти запросы выполняться будут слишком долго.

Творческие архитектурные задачи:

1)       Загружать – не загружать.
2)       Должно быть одно (таблица, группа таблиц) и должно быть другое (класс, иерархия классов).
3)       ……………………………………………………………………………

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

Функции:

1)       Обмен данными с базой данных (загрузка объекта, добавление объекта, обновление объекта, сохранение объекта, поиск объекта и т.д.).
2)       Какая-нибудь бизнес-функция (например, подготовить документ, вычислить цену с учетом налогов и т.д.).

Дата написания – 2006 год.