WWW.DISUS.RU

БЕСПЛАТНАЯ НАУЧНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА - Авторефераты, диссертации, методички

 

Pages:     || 2 | 3 | 4 | 5 |   ...   | 7 |

«Мартин Фаулер при участии Дейвида Раиса, Мэттыо Фоммела, Эдварда Хайета, Роберта Ми и Рэнди Стаффорда Москва • Санкт-Петербург • Киев 2006 УДК 681.3.07 Ф28 ББК 32.973.26-018.2.75 Издательский дом Вильяме' По общим ...»

-- [ Страница 1 ] --

Архитектура

корпоративных

программных

приложений

ИСПРАВЛЕННОЕ ИЗДАНИЕ

Мартин Фаулер

при участии

Дейвида Раиса, Мэттыо Фоммела,

Эдварда Хайета, Роберта Ми и Рэнди

Стаффорда

Москва • Санкт-Петербург • Киев

2006

УДК 681.3.07

Ф28 ББК

32.973.26-018.2.75

Издательский дом "Вильяме'

По общим вопросам обращайтесь в Издательский дом "Вильяме" по адресу:

[email protected], http://www.williamspublishing.com 115419, Москва, а/я 783; 03150, Киев, а/я 152 Фаулер, Мартин.

Ф28 Архитектура корпоративных программных приложений.: Пер. с англ. — М.: Издательский дом "Вильяме", 2006. — 544 с.: ил. — Парал. тит. англ.

ISBN 5-8459-0579-6 (рус.) Создание компьютерных систем — дело далеко не простое. По мере того как возрастает их сложность, процессы конструирования соответствующего программного обеспечения становятся все более трудоемкими, причем затраты труда растут экспоненциально. Как и в любой профессии, прогресс в программировании достигается исключительно путем обучения, причем не только на ошибках, но и на удачах — как своих, так и чужих. Книга дает ответы на трудные вопросы, с которыми приходится сталкиваться всем разработчикам корпоративных систем. Автор, известный специалист в области объектно-ориентированного программирования, заметил, что с развитием технологий базовые принципы проектирования и решения общих проблем остаются неизменными, и выделил более 40 наиболее употребительных подходов, оформив их в виде типовых решений.

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

ББК 32.973.26-018.2. Все названия программных продуктов являются зарегистрированными торговыми марками соответствующих фирм.

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

Authorized translation from the English language edition published by Pearson Education, Inc., Copyright © 2003 All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher.

Russian language edition published by Williams Publishing House according to the Agreement with R&I Enterprises International, Copyright © !SRN olf ml?1,(РУС-\ ° И^ьский дом "Вильяме", ISBN 0-321-12742-0 (англ.) © Peaison Educationj Inc, Оглавление Предисловие Введение Часть I. Обзор Глава 1. "Расслоение" системы Глава 2. Организация бизнес-логики Глава 3. Объектные модели и реляционные базы данных Глава 4. Представление данных в Web Глава 5. Управление параллельными заданиями Глава 6. Сеансы и состояния Глава 7. Стратегии распределенных вычислений Глава 8. Общая картина Часть П. Типовые решения Глава 9. Представление бизнес-логики Глава 10. Архитектурные типовые решения источников данных Глава 11. Объектно-реляционные типовые решения, предназначенные для моделирования поведения Глава 12. Объектно-реляционные типовые решения, предназначенные для моделирования структуры Глава 13. Типовые решения объектно-реляционного отображения с использованием метаданных Глава 14. Типовые решения, предназначенные для представления данных в Web Глава 15. Типовые решения распределенной обработки данных Глава 16. Типовые решения для обработки задач автономного параллелизма Глава 17. Типовые решения для хранения состояния сеанса Глава 18. Базовые типовые решения Список основных источников информации Предметный указатель Содержание Предисловие Введение Часть I. Обзор Глава 1. "Расслоение" системы Развитие модели слоев в корпоративных профаммных приложениях Три основных слоя Где должны функционировать слои Глава 3. Объектные модели и реляционные базы данных Взаимное отображение объектов и реляционных структур Содержание Предотвращение возможности несогласованного чтения данных Типовые решения задачи обеспечения автономного параллелизма Глава 7. Стратегии распределенных вычислений Источник данных для модели предметной области Содержание Часть II. Типовые решения Глава 9. Представление бизнес-логики Принцип действия Задача определения зачтенного дохода Пример: определение зачтенного дохода (Java) Модель предметной области (Domain Model) Принцип действия Назначение Пример: использование диспетчера данных для объекта домена (Java) Содержание Глава П. Объектно-реляционные типовые решения, Пример: регистрация посредством изменяемого объекта (Java) Пример: методы для работы с коллекцией объектов (Java) Пример: использование диспетчера значения (Java) Пример: использование фиктивных объектов (С#) Глава 12. Объектно-реляционные типовые решения, Представление поля идентификации в объекте Пример: использование таблицы ключей (Java) Пример: использование составного ключа (Java) Отображение внешних ключей (Foreign Key Mapping) Содержание Отображение с помощью таблицы ассоциаций (Association Table Mapping) Пример: использование SQL для непосредственного обращения Пример: загрузка сведений о нескольких служащих посредством Пример: сериализация иерархии отделов в формат XML (Java) Наследование с одной таблицей (Single Table Inheritance) Наследование с таблицами для каждого класса (Class Table Inheritance) Наследование с таблицами для каждого конкретного класса Содержание Глава 13. Типовые решения объектно-реляционного отображения Пример: использование метаданных и метода отражения (Java) Глава 14. Типовые решения, предназначенные для представления данных в Web Пример: простое отображение с помощью контроллера-сервлета Пример: использование страницы JSP в качестве обработчика запросов (Java) Пример: обработка запросов страницей сервера с применением Содержание Пример: использование страницы JSP в качестве представления Интерфейс удаленного доступа и типовое решение интерфейс сеанса Пример: использование компонента сеанса Java Содержание Глава 16. Типовые решения для обработки задач автономного параллелизма Оптимистическая автономная блокировка (Optimistic Offline Lock) Пессимистическая автономная блокировка (Pessimistic Offline Lock) Блокировка с низкой степенью детализации (Coarse-Grained Lock) Пример: обшая оптимистическая автономная блокировка (Java) Пример: обшая пессимистическая автономная блокировка (Java) Пример: оптимистическая автономная блокировка корневого элемента (Java) Пример: неявная пессимистическая автономная блокировка (Java) Сохранение состояния сеанса на стороне клиента (Client Session State) Сохранение состояния сеанса на стороне сервера (Server Session State) Сохранение состояния сеанса в базе данных (Database Session State) Пример: создание шлюза к службе отправки сообщений (Java) Содержание Пример: реестр с единственным экземпляром (Java) Пример: реестр, уникальный в пределах потока (Java) Пример: генератор идентификаторов (Java) Пример: служба определения величины налога (Java) Предисловие Весной 1999 года меня пригласили в Чикаго для консультаций по одному из проектов, осуществляемых силами ThoughtWorks — небольшой, но быстро развивавшейся компании, которая занималась разработкой программного обеспечения. Проект был достаточно амбициозен: речь шла о создании корпоративного лизингового приложения уровня сервера, которое должно было охватывать все аспекты проблем имущественного найма, возникающих после заключения договора: рассылку счетов, изменение условий аренды, предъявление санкций нанимателю, не внесшему плату в установленный срок, досрочное возвращение имущества и т.п. Все это могло бы звучать не так уж плохо, если не задумываться над тем, сколь разнообразны и сложны формы соглашений аренды. "Логика" бизнеса редко бывает последовательна и стройна, так как создается деловыми людьми для ситуаций, в которых какой-нибудь мелкий случайный фактор способен обусловить огромные различия в качестве сделки — от полного краха до неоспоримой победы.

Это как раз те вещи, которые интересовали меня прежде и не перестают волновать поныне: как прийти к системе объектов, способной упростить восприятие конкретной сложной проблемы. Я действительно убежден, что основное преимущество объектной парадигмы как раз и состоит в облегчении понимания запутанной логики. Разработка хорошей модели предметной области (Domain Model, 140)1 для изощренной проблемы реального бизнеса весьма трудна, но ее решение приносит громадное удовлетворение.

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

Несмотря на все трудности, мы обладали большим преимуществом— обширным опытом. Я длительное время проделывал аналогичные вещи с помощью C++, Smalltalk и CORBA. Многие члены команды ThoughtWorks в свое время серьезно поднаторели в Forte. В наших головах уже вертелись основные архитектурные идеи, оставалось только выплеснуть их на холст J2EE. (Теперь, по прошествии трех лет, я могу констатировать, что проект не блистал совершенством, но проверку временем выдержал очень хорошо.) Для разрешения именно таких ситуаций и была задумана эта книга. На протяжении долгого времени мне доводилось иметь дело с массой корпоративных профаммных приложений. Эти проекты часто основывались на сходных идеях, эффективность которых 'Таким образом обозначается ссылка на страницу книги, где описано указанное типовое решение.

была доказана при решении сложных проблем, связанных с управлением на уровне предприятия. В книге делается попытка представить подобные проектные подходы в виде типовых решений (patterns).

Книга состоит из двух частей. Первая содержит несколько ознакомительных глав с описанием ряда важных тем, имеющих отношение к сфере проектирования корпоративных приложений. Здесь бегло формулируются различные проблемы и варианты их решения. Все подробности и нюансы вынесены в главы второй части. Эту информацию уместно трактовать как справочную, и я не настаиваю на том, чтобы вы штудировали ее от начала до конца. На вашем месте я поступил бы так: детально ознакомился с материалом первой части для максимально полного понимания предмета и обратился к тем главам или типовым решениям из второй части, близкое знакомство с которыми действительно необходимо. Поэтому книгу можно воспринимать как краткий учебник (часть I), дополненный более увесистым руководством (часть II).

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

Корпоративные приложения имеют ряд особенностей, связанных с подходами к решению возникающих проблем: они существенным образом отличаются от встроенных систем, систем управления, телекоммуникационных приложений, программных продуктов для персональных компьютеров и т.д. Поэтому, если вы специализируетесь в каких-либо "иных" направлениях, не связанных с корпоративными системами, эта книга, вероятно, не для вас (хотя, может быть, вам просто хочется "вкусить" нового?). За общей информацией об архитектуре программного обеспечения рекомендую обратиться к работе [33].

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

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

"расслоение" приложения по уровням;

структурирование логики предметной области;

разработка пользовательского Web-интерфейса;

связывание модулей, размещаемых в памяти (в частности, объектов), с реляцион принципы распределения программных компонентов и данных.

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

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

В намерения автора не входила ориентация на какую бы то ни было конкретную профаммную платформу. Рассматриваемые типовые решения прошли первое испытание в конце 1980-х и начале 1990-х годов, когда я работал с C++, Smalltalk и CORBA. В конце 1990-х я начал интенсивно использовать Java и обнаружил, что те же подходы оказались приемлемыми при реализации и ранних гибридных систем Java/CORBA, и более поздних проектов на основе стандарта J2EE. Недавно я стал присматриваться к платформе Microsoft.NET и пришел к заключению, что решения вновь вполне применимы. Мои коллеги по ThoughtWorks подтвердили аналогичные выводы в отношении Forte. Я не собираюсь утверждать, что то же справедливо для всех платформ, современных и будущих, используемых для развертывания корпоративных приложений, но до сих пор дело обстояло именно так.

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

Java в этом смысле выглядит наиболее привлекательно. Всякий, кто знаком с С или C++, разберется и в Java; кроме того, Java намного проще, нежели C++. Практически любой профаммист, использующий C++, способен воспринимать Java-код, но не наоборот.

Я стойкий приверженец объектной парадигмы, поэтому речь могла идти только об одном из объектно-ориентированных языков. Итак, примеры написаны преимущественно на языке Java. Период работы над книгой совпал с этапом становления среды.NET и системы профаммирования С#, которая, по моему мнению, обладает многими свойствами, присущими Java. Поэтому я реализовал некоторые примеры и на С#, впрочем, с определенным риском, поскольку у разработчиков еще нет достаточного опыта взаимодействия с платформой.NET, так что идиомы ее использования, как говорится, не созрели. Оба выбранных мною языка наследуют черты С, поэтому если вы владеете одним, то сможете воспринимать — хотя бы поверхностно — и код, написанный на другом. Моей задачей было найти такой язык, который удобен для большинства разработчиков, даже если он не является их основным инструментом. (Приношу свои извинения всем, кому нравится Smalltalk, Delphi, Visual Basic, Perl, Python, Ruby, COBOL и т.д. Я знаю: вы хотите сказать, что есть языки получше, чем Java или С#. Полностью с вами согласен!) Примеры, приведенные в книге, преследуют цель объяснить и проиллюстрировать основные идеи, лежащие в основе типовых решений. Их не нужно трактовать как окончательные результаты; если вы намерены воспользоваться ими в реальных ситуациях, вам придется проделать определенную работу. Типовые решения — удачная отправная точка, а не пункт назначения.

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

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

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

Поскольку типовые решения — это общеупотребительные результаты анализа повторяющихся проблем, вполне вероятно, что с некоторыми из них вы уже когда-либо сталкивались. Если профаммированием корпоративных приложений вы занимаетесь долгое время, не исключено, что вам знакомо многое. Я не утверждаю, что книга представляет собой коллекцию свежих знаний. Напротив, я стараюсь убедить вас в обратном: книга трактует (пусть зачастую по-новому) старые идеи, проверенные временем. Если вы новичок, книга, я надеюсь, поможет вам изучить предмет. Если вы уже с ним знакомы, книга поспособствует формализации и структурированию ваших знаний. Важная функция типовых решений связана с выработкой общего терминологического словаря: если вы скажете, что разрабатываемый вами класс является, например, разновидностью интерфейса удаленного доступа (Remote Facade, 405), собеседникам должно быть понятно, о чем идет речь.

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

Начну с непосредственных участников проекта. Дейвид Райе (David Rice), мой коллега по ThoughtWorks, внес громадный вклад: добрый десяток процентов всего содержимого — это его прямая заслуга. На завершающей фазе проекта, стремясь поспеть к сроку (а Дейвид к тому же обеспечивал взаимодействие с заказчиком), мы провели вместе немало вечеров, и в одной из бесед он признался, что наконец-то понял, почему работа над книгой требует полной самоотдачи.

Еще один "мыслитель"2, Мэттью Фоммел (Matthew Foemmel), оказался непревзойденным поставщиком примеров кода и немногословным, но острым критиком, хотя легче было бы растопить льды Арктики, нежели заставить его написать забавы ради пару абзацев текста. Я рад поблагодарить Рэнди Стаффорда (Randy Stafford) за его лепту в виде слоя служб (Service Layer, 156), а также вспомнить Эдварда Хайета (Edward Hieatt) и Роберта Ми (Robert Мее). Сотрудничество с Робертом началось с того, что, просматривая материал, он обнаружил какое-то логическое несоответствие. Со временем он стал самым пристрастным и полезным критиком: его заслуги состоят не только в обнаружении каких-то пробелов, но и в их заполнении!

Я в большом долгу перед всеми, кто вошел в число официальных рецензентов книги, — Джоном Бруэром (John Brewer), Кайлом Брауном (Kyle Brown), Дженс Колдуэй (Jens Coldewey), Джоном Крапи (John Crupi), Леонардом Фенстером (Leonard Fenster), Аланом Найтом (Alan Knight), Робертом Ми, Жераром Месарашем (Gerard Meszaros), Дерк Райел (Dirk Riehle), Рэнди Стаффордом, Дейвидом Сигелом (David Siegel) и Каем Ю (Kai Yu). Я мог бы привести здесь полный список служащих ThoughtWorks — так много коллег помогали мне, сообщая о своих проектах и результатах. Многие типовые решения оформились благодаря счастливой возможности общения с талантливыми сотрудниками компании, поэтому у меня нет другого выбора, как поблагодарить коллектив в целом.

Кайл Браун, Рейчел Рейниц (Rachel Reinitz) и Бобби Вулф (Bobby Woolf) отложили все свои дела, чтобы встретиться со мной в Северной Каролине и подробнейшим образом обсудить материалы книги. Я с удовольствием вспоминаю и наши с Кайлом телефонные беседы.

В начале 2000 года я вместе с Аланом Найтом и Каем Ю подготовил доклад для конференции Java One, который послужил первым прототипом книги. Я признателен моим соавторам, а также Джошуа Маккензи (Josh Mackenzie), Ребекке Парсонз (Rebecca Parsons) и Дейвиду Раису за помошь, оказанную ими и тогда и позже. Джим Ньюкирк (Jim Newkirk) сделал все необходимое, чтобы познакомить меня с новым миром Microsoft.NET.

Я многому научился у специалистов, с которыми мне приходилось общаться и сотрудничать. В частности, хотелось бы поблагодарить Коллин Роу (Colleen Roe), Дейвида Мьюрэхеда (David Muirhead) и Рэнди Стаффорда за то, что они поделились со мной результатами работы над проектом системы Foodsmart в Джемстоуне. Не могу не упомянуть добрым словом всех, кто участвовал в плодотворных дискуссиях на конференциях Crested Butte, проводимых Брюсом Эклем (Bruce Eckel) в течение нескольких последних лет. Джошуа Керивски (Joshua Kerievsky) не смог выкроить время для полномасштабного рецензирования, но он прекрасно справился с функциями технического консультанта.

Название компании ThoughtWorks можно перевести, скажем, как "работа мысли". — Прим. пер.

Предисловие Я получил заметную помощь со стороны участников одного из читательских кружков, организованных при университете штата Иллинойс. Вот эти люди: Ариель Герценстайн (Ariel Gertzenstein), Боско Живальевич (Bosko Zivaljevic), Брэд Джонс (Brad Jones), Брайан Футей (Brian Foote), Брайан Марик (Brian Marick), Федерико Бэлэгур (Federico Balaguer), Джозеф Йодер (Joseph Yoder), Джон Брант (John Brant), Майк Хьюнер (Mike Hewner), Ральф Джонсон (Ralph Johnson) и Вирасак Витхаваскул (Weerasak Witthawaskul). Всем им большое спасибо.

Драгое Манолеску (Dragos Manolescu), экс-глава кружка, собрал собственную, группу рецензентов, в которую вошли МухаммадАнан (Muhammad Anan), Брайан Доил (Brian Doyle), ЭмадГоше (Emad Ghosheh), Гленн Грэйссл (Glenn Graessle), Дэниел Хайн (Daniel Hein), Прабхахаран Кумаракуласингам (Prabhaharan Kumarakulasingam), Джо Куинт (Joe Quint), Джон Рейнк (John Reinke), Кевин Рейноддз (Kevin Reynolds), Шриприя Шринивасан (Sripriya Srinivasan) и Тирумала Ваддираджу (Tirumala Vaddiraju).

Кент Бек (Kent Beck) внес столько предложений, что я затрудняюсь вспомнить их все.

Он, например, придумал название для типового решения частный случай (Special Case, 511). ДжимОделл (JimOdell) был первым, кто познакомил меня с миром консалтинга, преподавания и писательства; мне не хватает слов, чтобы выразить всю глубину моей благодарности.

По мере работы над книгой я размещал ее черновики в Web. Среди тех, кто откликнулся и прислал свои вопросы, варианты возможных проблем и их решения, были Майкл Бэнкс (Michael Banks), Марк Бернстайн (Mark Bernstein), Грэхем Беррисфорд (Graham Berrisford), Бьерн Бесков (Bjorn Beskow), Брайан Борхэм (Brian Boreham), Шен Бродли (Sean Broadley), Перис Бродски (Peris Brodsky), Пол Кемпбелл (Paul Campbell), Честер Чен (Chester Chen), Джон Коукли (John Coakley), Боб Коррик (Bob Corrick), Паскаль Костэнза (Pascal Costanza), Энди Червонка (Andy Czerwonka), Мартин Дайл (Martin Diehl), Дэниел Дрейзин (Daniel Drasin), Хуан Гомес Дуазо (Juan Gomez Duaso), Дон Дуиггинз (Don Dwiggins), Питер Форман (Peter Foreman), Рассел Фриман (Russell Freeman), Питер Гэзмен (Peter Gassmann), Джейсон Горман (Jason Gorman), Дэн Грин (Dan Green), Ларе Грегори (Lars Gregori), Рик Хансен (Rick Hansen), Тобин Харрис (Tobin Harris), Рассел Хили (Russel Healey), Кристиан Геллер (Christian Heller), Ричард Хендерсон (Richard Henderson), Кайл Херменин (Kyle Hermenean), Карстен Хейл (Carsten Heyl), Акира Хирасава (Akira Hirasawa), Эрик Кон (Eric Kaun), Кирк Кнорнсчайлд (Kirk Knoernschild), Джеспер Лейдегаард (Jesper Ladegaard), Крис Лопес (Chris Lopez), Паоло Марино (Paolo Marino), Джереми Миллер (Jeremy Miller), Иван Митрович (Ivan Mitrovic), Томас Нейманн (Thomas Neumann), Джуди Оби (Judy Obee), Паоло Паровел (Paolo Parovel), Тревор Пинкни (Trevor Pinkney), Томас Рестрепо (Tomas Restrepo), Джоуэл Ридер (Joel Rieder), Мэттью Роберте (Matthew Roberts), Стефан Рук (Stefan Roock), Кен Роша (Ken Rosha), Энди Шнайдер (Andy Schneider), Александр Семенов, Стен Силверт (Stan Silvert), Джефф Суттер (Jeoff Soutter), Уолкер Термат (Volker Termath), Кристофер Тейм (Christopher Thames), Уолкер Тюро (Volker Turau), Кнут Ванхеден (Knut Wannheden), Марк Уоллес (Marc Wallace), Стефан Уэниг (Stefan Wenig), Брэд Уаймерслэдж (Brad Wiemerslage), Марк Уиндхолц (Mark Windholtz) и Майкл Юн (Michael Yoon).

Тех, кто здесь не упомянут, я тоже благодарю с не меньшей сердечностью. Как всегда, моя самая горячая признательность любимой жене Синди (Cindy), чье общество я ценю намного больше, чем кто-либо сумеет оценить эту книгу.

И еще несколько слов Это моя первая книга, оформленная с помощью языка XML и связанных с ним технологий и инструментов. Текст был набран в виде серии XML-документов с помощью старого доброго TextPad. Я пользовался и доморощенными шаблонами определения типа документа (Document Type Definition — DTD). Для генерации HTML-страниц Web-сайта применялся язык XSLT, а для построения диаграмм — надежный Visio, пополненный замечательными UML-шаблонами от Павла Храби (Pavel Hruby) (намного превосходящими по качеству аналоги из комплекта поставки редактора; на моем сайте приведен адрес, где их можно получить). Я написал небольшую программу, которая позволила автоматически включать примеры кода в выходной файл, избавив меня от кошмара многократного повторения операций копирования и вставки. При подготовке первого варианта рукописи я использовал XSL-FO в сочетании с Apache FOP, а позже для импорта текста в среду FrameMaker создал ряд сценариев XSLT и Ruby.

В процессе работы над книгой мне приходилось применять несколько инструментов из категории программ с открытым исходным кодом — JUnit, NUnit, ant, Xerces, Xalan, Tomcat, Jboss, Ruby и Hsql. Я искренне признателен всем авторам. Не обошлось, разумеется, и без коммерческих продуктов. В частности, я активно пользовался пакетом Visual Studio.NET и прекрасной интегрированной Java-средой разработки Idea от intelliJ — первой, которая меня по-настоящему вдохновила со времен работы с языком Smalltalk.

Книга была приобретена для издательства Addison Wesley Майком Хендриксоном (Mike Hendrickson) и Россом Венаблзом (Ross Venables), которые руководили проектом.

Я начал трудиться над рукописью в ноябре 2000 и закончил работу в июне 2002 года.

Сара Уивер (Sarah Weaver) выполняла обязанности главного редактора и координировала все стороны проекта, связанные с редактированием, версткой, корректурой, составлением предметного указателя и получением окончательной электронной версии книги.

Диана Вуд (Dianne Wood), литературный редактор, предприняла все возможное, чтобы "подчистить" словесную форму, не испортив идейного содержания. Ким Арни Мулки (KimArney Mulcahy) окончательно скомпоновал материал, "отшлифовал" рисунки и подготовил для передачи в типографию итоговые файлы FrameMaker. При верстке мы придерживались того же формата, который был выбран ранее для книги [18]. Шерил Фергюсон (Cheryl Ferguson), корректор, позаботилась, чтобы в тексте осталось как можно меньше ошибок, а Ирв Хершман (Irv Hershman) составил предметный указатель.

Предисловие Поддержка Эта книга отнюдь не совершенна. Несомненно, в ней есть какие-то неточности; может быть, я упустил что-то важное. Если вы найдете то, что считаете ошибочным, или сочтете, что в книгу следует включить дополнительный материал, пожалуйста, пошлите свое сообщение по адресу: f owler@acm. org. Обновления и исправления будут представлен ы н а стран и ц еhtt p://www. martinf owl er.com/ eaa Errat a.ht ml 3.

О фотографии, размещенной на обложке книги Когда писалась эта книга, в Бостоне происходило нечто более знаменательное. Я имею в виду строительство моста Bunker Hill Bridge (попробуйте-ка втиснуть это название в небольшой дорожный указатель) через Чарлз-ривер по проекту Леонарда П. Закима (Leonard P. Zakim). Мост Закима, изображенный на обложке книги, относится к разряду подвесных, которые до сих пор не приобрели в США такого распространения, как, скажем, в Европе. Мост не особенно длинен, но зато самый широкий в мире (в своей категории) и первый в Штатах, имеющий асимметричный дизайн. Кроме того (может быть, это самое главное), он очень красив.

Мартин Фаулер, Мелроуз, Массачусетс, август 2002 года http://martinfowler.com В переводном издании этой книги учтены исправления, опубликованные на этой Web-странице, по состоянию на 1 марта 2005 года. — Прим. ред.

Ждем ваших отзывов!

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

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

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

Наши координаты:

E-mail:

WWW:

Информация для писем:

из России:

из Украины:

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

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

Архитектура Одно из странных свойств, присущих индустрии программного обеспечения, связано с тем, что какой-либо термин может иметь множество противоречивых толкований. Вероятно, наиболее многострадальным оказалось понятие архитектура (architecture). Мне кажется, оно принадлежит к числу тех нарочито эффектных слов, которые употребляются преимущественно для обозначения чего-то, считающегося значительным и серьезным. (Нет, я слишком прагматичен, чтобы цинично пользоваться этим фактом, стараясь привлечь внимание читающей публики.:—)) Термин "архитектура" пытаются трактовать все, кому не лень, и всяк на свой лад.

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

Время от времени Ралф Джонсон (Ralph Johnson), участвуя в списке рассылки, отправлял туда замечательные сообщения, одно из которых, касающееся проблем архитектуры, совпало с периодом завершения мною чернового варианта книги. В этом сообщении он подтвердил мое мнение о том, что архитектура— весьма субъективное понятие.

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

В этой книге представлено мое видение основных компонентов корпоративного приложения и решений, которые должны приниматься на ранних фазах его жизни. Мне по душе трактовка системы в виде набора архитектурных слоев (layers) (подробнее о слоях — в главе 1, "«Расслоение» системы"). Поэтому в книге предлагаются ответы на вопросы, как осуществить декомпозицию системы по слоям и как обеспечить надлежащее взаимодействие слоев между собой. В большинстве корпоративных приложений прослеживается та или иная форма архитектурного "расслоения", но в некоторых ситуациях большее значение могут приобретать другие подходы, связанные, например, с организацией каналов (pipes) или фильтров (filters). Однако мы сконцетрируем внимание на архитектуре слоев как на наиболее плодотворной структурной модели.

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

Корпоративные приложения Созданием программного обеспечения занимается множество людей. Но говорить о программном обеспечении в целом — значит, не сказать ничего, поскольку разновидностей программных приложений чрезвычайно много и каждая ситуация вьщвигает особые проблемы, отличающиеся собственным уровнем сложности. Наглядным примером могут служить дискуссии с коллегами, работающими в сфере телекоммуникаций. С определенной точки зрения "мои" корпоративные приложения намного проще, нежели телекоммуникационное программное обеспечение, — мне не приходится решать чрезвычайно сложные проблемы обеспечения многопоточного функционирования и тесной интеграции аппаратных и программных компонентов. Но во всем остальном мои задачи существенно сложнее. Корпоративные приложения чаще всего имеют дело с изощренными данными большого объема и бизнес-правилами, логика которых иногда просто противоречит здравому смыслу. Хотя некоторые приемы и решения более-менее универсальны, большинство из них адекватны только в контексте определенных ситуаций.

На протяжении всей профессиональной карьеры я занимался преимущественно корпоративными приложениями, и это, разумеется, обусловило выбор типовых решений, представленных на страницах книги. (В числе близких аналогов понятия "приложение" можно назвать термин "информационная система"; читатели постарше, вероятно, вспомнят выражение "обработка данных".) Но что именно подразумевает понятие корпоративное приложение (enterprise application)! Точное определение сформулировать трудно, но дать смысловое толкование вполне возможно.

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

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

Данных, с которыми имеет дело корпоративное приложение, как правило, бывает много: даже скромная система способна манипулировать несколькими гигабайтами информации, организованной в виде десятков миллионов записей; и задача манипуляции этими данными вырастает в одну из основных функций приложения. В старых системах информация хранилась в виде индексированных файловых структур, подобных разработанным компанией IBM VSAM и ISAM. Сейчас для этого применяются системы управления базами данных (СУБД), большей частью реляционные. Проектирование таких систем и их сопровождение превратились в отдельные специализированные дисциплины.

Множество пользователей обращаются к данным параллельно. Как правило, их количество не превышает сотни, но для систем, размещенных в среде Web, этот показатель возрастает на несколько порядков. Как гарантировать возможность одновременного доступа к базе данных для всех, кто имеет на это право? Проблема остается даже в том случае, если речь идет всего о двух пользователях: они должны манипулировать одним элементом данных только такими способами, которые исключают вероятность возникновения ошибок. Большинство обязанностей по управлению параллельными заданиями принимает на себя диспетчер транзакций из состава СУБД, но полностью избавить прикладные системы от подобных забот программистам чаще всего не удается.

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

Корпоративные приложения редко существуют в изоляции. Обычно они требуют интеграции с другими системами, построенными в разное время и с применением различных технологий (файлы данных COBOL, CORBA, системы обмена сообщениями). Время от времени корпорации стараются провести интеграцию собственных подсистем с применением некоторой универсальной технологии. Поскольку обычно такой работе концакраю не видно, все сводится к применению нескольких различных методов интеграции.

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

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

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

(Для того чтобы увидеть полную картину происходящего, следует учесть также тот факт, что данные подвержены постоянным изменениям, вносимым, как правило, без какоголибо предупреждения.) Не стоит забывать и о том, что принято обозначать расплывчатым термином бизнеслогика. Я нахожу его забавным, поскольку могу припомнить только несколько вещей, менее логичных, нежели так называемая бизнес-логика. При создании операционной системы, например, без строгой логики не обойтись. Но бизнес-правила, которые нам сообщают, следует принимать такими, какие они есть, поскольку без серьезного политического вмешательства их не преодолеть. Мы вынуждены иметь дело со случайными наборами странных условий, которые сочетаются между собой самым непредсказуемым образом. Определенно известно только одно: вся эта мешанина еще и изменяется во времени. Разумеется, тому есть какие-то причины. Так, например, выгодный клиент может выговорить для себя особые условия оплаты кредита, отвечающие срокам поступления средств на его расчетный счет. И пару тысяч таких вот частных случаев способны сделать бизнес-логику совершенно нелогичной, а соответствующее профаммное приложение — запутанным и не поддающимся восприятию с позиций здравого смысла.

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

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

Первый — электронная коммерческая система типа "поставщик—потребитель" ("business to customer" — В2С); к ней обращаются с помощью Web-обозревателей, находят нужные товары, вводят необходимую информацию и осуществляют покупки. Подобная система предназначена для обслуживания большого количества пользователей одновременно, поэтому проектное решение должно быть не только эффективным по критерию использования ресурсов, но и масштабируемым: все, что требуется для повышения пропускной способности такой системы, — это приобретение дополнительного аппаратного обеспечения. Бизнес-логика подобного приложения довольно прямолинейна: прием заказа, незамысловатые финансовые операции и отправка уведомления о доставке. Необходимо, чтобы каждый мог быстро и легко обратиться к системе, поэтому Web-интерфейс должен быть предельно простым и доступным для воспроизведения с помощью максимально широкого диапазона обозревателей. Информационный источник включает базу данных для хранения заказов и, возможно, некий механизм обмена данными с системой складского учета для получения информации о наличии товаров и их отгрузке.

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

Подобная система отличается сложностью и в отношении пользовательского интерфейса. Зачастую требования к интерфейсу таковы, что их нельзя удовлетворить только средствами HTML; приходится пользоваться интерфейсными средствами, предоставляемыми более традиционной моделью "толстого" клиента. Усложнение процедур взаимодействия пользователя с программой вынуждает применять и более изощренные варианты транзакций: например, оформление договора аренды может продолжаться несколько часов, и все это время пользователь выполняет одну логическую транзакцию. Схема базы данных также заметно расширяется и может включать несколько сотен таблиц и соединений с внешними пакетами, предназначенными для оценки стоимости активов и цены аренды.

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

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

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

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

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

Все сказанное применимо и к выбору инструментальных средств программирования.

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

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

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

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

Существует одно важное обстоятельство: значительное изменение конфигурации приложения способно перечеркнуть все ранее установленные факты, касающиеся вопросов производительности. Поэтому, обновив версию виртуальной машины, СУБД, аппаратного обеспечения или любого другого компонента системы, вы обязаны заново провести оптимизацию и убедиться, что принятые меры возымели действие. Нередко бывает и так, что приемы оптимизации, с успехом применявшиеся в прошлом, в новых условиях вызывают обратный эффект.

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

Наиболее характерный пример — понятие, описывающее способность приложения к масштабированию (scalability): тут можно назвать не менее пяти-шести различных толкований. Ниже рассмотрены термины, применяемые в этой книге.

Время отклика (response time) — промежуток времени, который требуется системе, чтобы обработать запрос извне, подобный щелчку на кнопке графического интерфейса или вызову функции API сервера.

Быстрота реагирования (responsiveness) — скорость подтверждения запроса (не путать с временем отклика— скоростью обработки). Эта характеристика во многих случаях весьма важна, поскольку интерактивная система, пусть даже обладающая нормальным временем отклика, но не отличающаяся высокой быстротой реагирования, всегда вызывает справедливые нарекания пользователей. Если, прежде чем принять очередной запрос, система должна полностью завершить обработку текущего, параметры времени отклика и быстроты реагирования, по сути, совпадают. Если же система способна подтвердить получение запроса раньше, ее быстрота реагирования выше. Например, применение динамического индикатора состояния процесса копирования повышает быстроту реагирования экранного интерфейса, хотя никак не сказывается на значении времени отклика.

Время задержки (latency) — минимальный интервал времени до получения какоголибо отклика (даже если от системы более ничего не требуется). Параметр приобретает особую важность в распределенных системах. Если я "прикажу" программе ничего не делать и сообщить о том, когда именно она закончит это "ничегонеделание", на персональном компьютере ответ будет получен практически мгновенно. Если же программа Введение выполняется на удаленной машине, придется подождать, вероятно, не менее нескольких секунд, пока запрос и ответ проследуют по цепочке сетевых соединений. Снизить время задержки разработчику прикладной программы не под силу. Фактор задержки — главная причина, побуждающая минимизировать количество удаленных вызовов.

Пропускная способность (thmughput) — количество данных (операций), передаваемых (выполняемых) в единицу времени. Если, например, тестируется процедура копирования файла, пропускная способность может измеряться числом байтов в секунду. В корпоративных приложениях обычной мерой производительности служит число транзакций в секунду (transactions per second — tps), но есть одна проблема — транзакции различаются по степени сложности. Для конкретной системы необходимо рассматривать смесь "типовых" транзакций.

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

Загрузка (load) — значение, определяющее степень "давления" на систему и измеряемое, скажем, количеством одновременно подключенных пользователей. Параметр загрузки обычно служит контекстом для представления других функциональных характеристик, подобных времени отклика. Так, нередко можно слышать выражения наподобие следующего: "время отклика на запрос составляет 0,5 секунды для 10 пользователей и 2 секунды для 20 пользователей".

Чувствительность к загрузке (load sensitivity) — выражение, задающее зависимость времени отклика от загрузки. Предположим, что система А обладает временем отклика, равным 0,5 секунды для 10-20 пользователей, а система В — временем отклика в 0,2 секунды для 10 пользователей и 2 секунды для 20 пользователей. Это дает основание утверждать, что система А обладает меньшей чувствительностью к загрузке, нежели система В.

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

Эффективность (efficiency) — удельная производительность в пересчете на одну единицу ресурса. Например, система с двумя процессорами, способная выполнить 30 tps, более эффективна по сравнению с системой, оснащенной четырьмя аналогичными процессорами и обладающей продуктивностью в 40 tps.

Мощность (capacity) — наибольшее значение пропускной способности или загрузки.

Это может быть как абсолютный максимум, так и некоторое число, при котором величина производительности все еще превосходит заданный приемлемый порог.

Способность к масштабированию (scalability) — свойство, характеризующее поведение системы при добавлении ресурсов (обычно аппаратных). Масштабируемой принято считать систему, производительность которой возрастает пропорционально объему приобщенных ресурсов (скажем, вдвое при удвоении количества серверов). Вертикальное масштабирование (vertical scalability, scaling up) ~ это увеличение мощности отдельного сервера (например, за счет увеличения объема оперативной памяти). Горизонтальное масштабирование (horizontal scalability, scaling out)— это наращивание потенциала системы путем добавления новых серверов.

Следует отметить, что существует проблема: выбор проектного решения оказывает не одинаковое влияние на факторы производительности. Рассмотрим для примера две программные системы, работающие на однотипных серверах: первая (назовем ее Swordfish) обладает мощностью в 20 tps, а вторая, Camel, — в 40 tps. Какая система более производительна? Какая из них в большей мере способна к масштабированию? На основании имеющейся информации мы не можем ответить на вопрос, касающийся возможностей масштабирования. Единственное, что понятно, — Camel более эффективна в конфигурации с одним сервером. Добавим еще один сервер и допустим, что производительность Swordfish теперь исчисляется величиной 35 tps, а продуктивность Camel возрастает до 50 tps. Мощность Camel все еще выше, но параметры масштабирования Swordfish выглядят предпочтительнее. Продолжив пополнение систем серверами, мы обнаружим, что производительность Swordfish всякий раз возрастает на 15 tps, в то время как аналогичный показатель Camel — только на 10 tps. Полученные данные позволяют прийти к заключению, что Swordfish лучше поддается горизонтальному масштабированию, хотя Camel демонстрирует большую эффективность при количестве серверов, меньшем пяти.

Проектируя корпоративную систему, часто следует уделять больше внимания обеспечению средств масштабирования, а не наращиванию мощности или повышению эффективности. Производительность масштабируемой системы всегда удастся увеличить, если такая потребность действительно возникнет. Помимо того, добиться возможности масштабирования проще. Нередко проектировщикам и программистам приходится изворачиваться, чтобы увеличить мощность системы для конкретной аппаратной конфигурации, хотя, вероятно, было бы дешевле приобрести дополнительное оборудование. Если, скажем, система Camel стоит дороже, чем Swordfish, и разница в стоимости покрывает цену нескольких серверов, то Swordfish обойдется дешевле даже в том случае, когда необходимый уровень производительности составляет всего 40 tps. Сейчас модно сетовать на возрастающие требования к аппаратному обеспечению, непременно сопровождающие выпуск очередных версий популярных программ, и я присоединяю свой голос к хору возмущенных потребителей, когда при установке последней версии Word мне велят обновить конфигурацию компьютера. Но использовать более новое оборудование зачастую просто выгоднее, нежели заставлять программу "крутиться" на устаревшей технике. Если корпоративное приложение поддается масштабированию, добавить несколько серверов дешевле, чем приобрести услуги нескольких программистов.

Типовые решения Концепция типовых решений (patterns) известна уже давно, и мне не хотелось бы выступать здесь с очередным очерком истории ее развития. Однако я не собираюсь упускать удачную возможность рассказать о собственной точке зрения на предмет.

Какого бы то ни было общеупотребительного определения типового решения не существует. Вероятно, лучше всего начать с цитаты из книги Кристофера Александера (Christopher Alexander), вдохновившей не одно поколение энтузиастов: "Каждое типовое решение описывает некую повторяющуюся проблему и ключ к ее разгадке, причем таким Введение образом, что вы можете пользоваться этим ключом многократно, ни разу не придя к одному и тому же результату" [1]. К. Александер — архитектор, и говорит он о сооружениях, но данное им определение, по моему мнению, прекрасно подходит и для типовых решений в программировании. Основа типового решения — подход, достаточно обший и эффективный для того, чтобы обеспечить преодоление периодически возникающих проблем определенной природы. Типовое решение можно воспринимать и в виде некоторой рекомендации: искусство создания типовых решений состоит в вычленении и кристаллизации таких относительно независимых рекомендаций, которые допускают возможность более или менее обособленного применения.

Типовые решения уходят своими корнями в практику. Чтобы распознать их, необходимо присмотреться к тому, что и как делают другие, изучить полученные результаты и выявить их главную составляющую. Это нелегко, но коль скоро хорошие типовые решения найдены, они обретают большую ценность. Для меня эта ценность в данный момент проявляется в том, что дает основание написать книгу, которую будут использовать как руководство к действию. Вам не обязательно читать ее (или любое другое аналогичное издание) от корки до корки, чтобы убедиться в полезности предлагаемых рекомендаций.

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

Как только вы ощутили потребность в типовом решении, следует подумать, как применить его в конкретных обстоятельствах. Основная особенность типовых решений состоит в том, что ими нельзя пользоваться слепо; вот почему многие инструментальные оболочки, основанные на типовых решениях, и получаемые с их помощью результаты так убоги. Мне кажется, что типовые решения можно сравнить с полуфабрикатом: чтобы получить удовольствие от еды, вам придется довершить приготовление блюда по собственному рецепту. Используя типовое решение, я "поджариваю" его всякий раз подругому и наслаждаюсь отменным и своеобразным вкусом.

Каждое типовое решение относительно независимо от других, но говорить об их полной взаимной изолированности нельзя. Зачастую одно решение непосредственно приводит к другому либо может применяться только в контексте некоего базового решения.

Так, например, решение наследование с таблицами для каждого класса (Class Table Inheritance, 305) обычно используется совместно с решением модель предметной области (Domain Model, 140). Границы между решениями не отличаются четкостью, но я предпринял все возможное для того, чтобы представить каждое решение в самодостаточной форме. Поэтому, если кто-то предлагает "применить решение единица работы (Unit of Work, 205)", будет довольно проследовать к соответствующему разделу книги, не читая всего остального.

Если у вас есть опыт проектирования корпоративных приложений, многие типовые решения, о которых речь пойдет ниже, вам, вероятно, уже знакомы. Надеюсь, вы не будете разочарованы (ваше возможное недоумение я уже пытался предупредить в предисловии). Типовые решения — не научные открытия; они в большой мере представляют собой обобщения результатов, накопленных в соответствующей области. Поэтому более уместно говорить о "поиске" типового решения, а не о его "изобретении". Моя роль состоит в обнаружении общих подходов, выделении главного и оформлении полученных выводов. Ценность типового решения для проектировщика заключается не в новизне идеи; главное — это помощь в описании и сообщении этой идеи. Если собеседники осведомлены о том, что именно представляет собой интерфейс удаленного доступа (Remote Facade, 405), одному из них достаточно произнести фразу "этот класс является интерфейсом удаленного доступа", чтобы расставить все точки над /. А новичку вы сможете подсказать, что, дескать, "для этой задачи больше подойдет объект переноса данных (Data Transfer Object, 419)", и он, обратившись к странице 646 настоящей книги, найдет все необходимое. Классификация типовых решений способствует созданию словаря проектировщика, а потому выбору их названий следует уделять должное внимание.

В главе 18, "Базовые типовые решения", упомянут ряд базовых типовых решений универсального характера; они используются при описании всех остальных решений, ориентированных на корпоративные приложения.

Структура типовых решений Каждому автору приходится выбирать форму представления типовых решений. Некоторые принимают за основу подходы, которые изложены в классических книгах, посвященных типовым решениям (например, [1, 20, 34]). Другие изобретают что-то свое.

Я долго не мог составить твердое мнение о том, в чем же состоит превосходство того или иного варианта над остальными. С одной стороны, меня не могло удовлетворить нечто столь же краткое, как форма из [20]; с другой — описание каждого решения должно было бы уместиться в пределах небольшого раздела книги. Ниже описан компромиссный результат, к которому я пришел после длительных размышлений.

Первое — название решения. Выбор подходящего имени довольно важен, поскольку одна из целей, преследуемых при использовании типовых решений, состоит в создании словаря, который облегчает взаимодействие проектировщиков в ходе выполнения проекта. Например, если я сообщу, что мой Web-сервер реализован на основе контроллера запросов (Front Controller, 362) и представления с преобразованием (Transform View, 379), и эти типовые решения будут знакомы и вам, у вас наверняка сложится однозначное представление об архитектуре приложения.

За именем следуют аннотация и эскиз. Аннотация состоит из одного-двух предложений и содержит краткое описание типового решения; эскиз служит визуальной иллюстрацией решения и часто (хотя не всегда) представляет собой UML-диаграмму. Аннотация и эскиз предназначены для создания наглядного "образа" решения и облегчают его запоминание. Если у вас уже есть решение (в том смысле, что оно вам известно, хотя, возможно, вы не знаете его названия), аннотация и эскиз — это, пожалуй, все, с помощью чего можно его быстро отыскать.

Далее вкратце обозначается проблема, которая стимулировала появление типового решения. Если таких проблем несколько, выбирается более характерная. Затем приводятся два обязательных раздела.

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

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

Введение Многие из решений, упомянутых в этой книге, взаимозаменяемы: таковыми являются, скажем, контроллер страшщ (Page Controller, 350) и контроллер запросов (Front Controller, 362). Часто одинаково пригодными оказываются несколько решений, поэтому, обнаружив одно из них, я спрашиваю себя, в каких случаях им не стоило бы пользоваться. Ответ на этот вопрос нередко подводит меня к выбору альтернативного решения.

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

В конце раздела, посвященного тому или иному решению, по мере необходимости могут быть приведены простые примеры использования, проиллюстрированные фрагментами кода на языках Java и/или С#. Выбор языков программирования (это уже отмечалось в предисловии) обусловлен вероятными предпочтениями большинства читателей.

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

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

Код примеров написан так, чтобы обеспечить простоту восприятия. В результате некоторые вещи остались, что называется, "за кадром" (в частности, так произошло с обработкой ошибок— вопросом, недостаточно хорошо проработанным мною для того, чтобы предложить здесь какое-либо типовое решение). Каждый пример обставлен слишком большим количеством упрощающих условий, и поэтому я посчитал нецелесообразным обеспечить возможность загрузки образцов кода с моего Web-сайта.

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

Представленные здесь сведения касаются всех типовых решений в области корпоративных приложений, известных мне на данный момент. Я не собираюсь утверждать, что полностью осведомлен обо всех их разновидностях и взаимозависимостях. Книга отражает уровень моего сегодняшнего опыта с учетом тех знаний, которые были приобретены в процессе ее написания. Но мысль не стоит на месте, и опыт, разумеется, будет пополняться и после выхода книги в свет. Программирование — бесконечный процесс, и в нем нет предела совершенству.

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

Глава "Расслоение" системы Концепция слоев (layers) — одна из общеупотребительных моделей, используемых разработчиками программного обеспечения для разделения сложных систем на более простые части. В архитектурах компьютерных систем, например, различают слои кода на языке программирования, функций операционной системы, драйверов устройств, наборов инструкций центрального процессора и внутренней логики чипов. В среде сетевого взаимодействия протокол FTP работает на основе протокола TCP, который, в свою очередь, функционирует "поверх" протокола IP, расположенного "над" протоколом Ethernet.

Описывая систему в терминах архитектурных слоев, удобно воспринимать составляющие ее подсистемы в виде "слоеного пирога". Слой более высокого уровня пользуется службами, предоставляемыми нижележащим слоем, но тот не "осведомлен" о наличии соседнего верхнего слоя. Более того, обычно каждый промежуточный слой "скрывает" нижний слой от верхнего: например, слой 4 пользуется услугами слоя 3, который обращается к слою 2, но слой 4 не знает о существовании слоя 2. (Не в каждой архитектуре слои настолько "непроницаемы", но в большинстве случаев дело обстоит именно так.) Расчленение системы на слои предоставляет целый ряд преимуществ.

Отдельный слой можно воспринимать как единое самодостаточное целое, не осо бенно заботясь о наличии других слоев (скажем, для создание службы FTP необ ходимо знать протокол TCP, но не тонкости Ethernet).

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

Зависимость между слоями можно свести к минимуму. Так, при смене среды пере дачи информации (при условии сохранения функциональности слоя IP) служба FTP будет продолжать работать как ни в чем не бывало.

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

Созданный слой может служить основой для нескольких различных слоев более высокого уровня (протоколы TCP/IP используются приложениями FTP, telnet, SSH и HTTP). В противном случае для каждого протокола высокого уровня при шлось бы изобретать собственный протокол низкого уровня.

Схема расслоения обладает и определенными недостатками.

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

Однако самое трудное при использовании архитектурных слоев — это определение содержимого и границ ответственности каждого слоя.

Развитие модели слоев в корпоративных программных приложениях По молодости лет мне не довелось пообщаться с ранними версиями систем пакетной обработки данных, но, как мне кажется, тогда люди не слишком задумывались о какихто там "слоях". Писалась программа, которая манипулировала некими файлами (ISAM, VSAM и т.п.), и этим, собственно говоря, функции приложения исчерпывались.

Понятие слоя приобрело очевидную значимость в середине 1990-х годов с появлением систем клиент/сервер (client/server). Это были системы с двумя слоями: клиент нес ответственность за отображение пользовательского интерфейса и выполнение кода приложения, а роль сервера обычно поручалась СУБД. Клиентские приложения создавались с помощью таких инструментальных средств, как Visual Basic, PowerBuilder и Delphi, предоставлявших в распоряжение разработчика все необходимое, включая экранные компоненты, обслуживающие интерфейс SQL: для конструирования окна было достаточно перетащить на рабочую область необходимые управляющие элементы, настроить параметры доступа к базе данных и подключиться к ней, используя таблицы свойств.

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

Одной из альтернатив было описание логики в тексте хранимых процедур, размещаемых в базе данных. Языки хранимых процедур, однако, отличались ограниченными возможностями структуризации, что вновь негативно сказывалось на качестве кода. Помимо того, многие отдали предпочтение реляционным системам баз данных, поскольку используемый в них стандартизованный язык SQL открывал возможности безболезненного перехода от одной СУБД к другой. Хотя воспользовались ими на практике только единицы, мысль о возможной смене поставщика СУБД, не связанной со сколько-нибудь ощутимыми затратами, согревала всех. А наличие жесткой зависимости языков хранимых процедур от конкретных версий систем фактически разрушало эти надежды.

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

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

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

Радикальный сдвиг произошел с появлением Web. Всем внезапно захотелось иметь системы клиент/сервер, где в роли клиента выступал бы Web-обозреватель. Если, однако, вся бизнес-логика приложения сосредоточивалась в коде толстого клиента, при переходе к Web-интерфейсу приходилось пересматривать ее полностью. А в удачно спроектированной трехуровневой системе достаточно было просто заменить уровень представления, не затрагивая слой предметной области. Позже, с появлением Java, все увидели объектно-ориентированный язык, претендующий на всеобщее признание. Появившиеся инструментальные средства конструирования Web-страниц были в меньшей степени связаны с SQL и потому более подходили для реализации третьего уровня.

При обсуждении вопросов расслоения программных систем нередко путают понятия слоя (layer) и уровня, или яруса (tier). Часто их употребляют как синонимы, но в большинстве случаев термин уровень трактуют, подразумевая физическое разделение. Поэтому системы клиент/сервер обычно описывают как двухуровневые (в общем случае "клиент" действительно отделен от сервера физически): клиент — это приложение для настольной машины, а сервер — процесс, выполняемый сетевым компьютером-сервером. Я применяю термин слой, чтобы подчеркнуть, что слои вовсе не обязательно должны располагаться на разных машинах. Отдельный слой бизнес-логики может функционировать как на персональном компьютере "рядом" с клиентским слоем интерфейса, так и на сервере базы данных. В подобных ситуациях речь идет о двух узлах сети, но о трех слоях или уровнях. Если база данных локальна, все три слоя могут соседствовать и на одном компьютере, но даже в этом случае они должны сохранять свой суверенитет.

Три основных слоя В этой книге внимание акцентируется на архитектуре с тремя основными слоями:

представление (presentation), домен (предметная область, бизнес-логика) (domain) и источник данных (data source). В табл. 1.1 приведено их краткое описание (названия заимствованы из [9]).

Таблица 1.1. Основные слои Представление Предоставление услуг, отображение данных, обработка событий Источник данных Обращение к базе данных, обмен сообщениями, управление Слой представления охватывает все, что имеет отношение к общению пользователя с системой. Он может быть настолько простым, как командная строка или текстовое меню, но сегодня пользователю, вероятнее всего, придется иметь дело с графическим интерфейсом, оформленным в стиле толстого клиента (Windows, Swing и т.п.) или основанным на HTML. К главным функциям слоя представления относятся отображение информации и интерпретация вводимых пользователем команд с преобразованием их в соответствующие операции в контексте домена (бизнес-логики) и источника данных.

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

Логика домена {бизнес-логика или логика предметной области) описывает основные функции приложения, предназначенные для достижения поставленной перед ним цели.

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

Иногда слои организуют таким образом, чтобы бизнес-логика полностью скрывала источник данных от представления. Чаще, однако, код представления может обращаться к источнику данных непосредственно. Хотя такой вариант менее безупречен с теоретической точки зрения, в практическом отношении он нередко более удобен и целесообразен:

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

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

До сих пор предполагалось обязательное наличие пользователя. Возникает закономерный вопрос: что произойдет, если в управлении программным приложением человек участия не принимает (примерами могут служить и новейшие Web-службы, и традиционный процесс пакетной обработки)? В этом случае в роли пользователя приложения выступает сторонняя клиентская программа и становится очевидным сходство между слоями представления и источника данньа: оба они задают связь приложения с внешним миром. Именно этот вариант логики лежит в основе типового решения шестигранная архитектура (Hexagonal Architecture) Алистера Коуберна (Alistair Cockburn) [39], которое трактует любую систему как ядро, окруженное интерфейсами к внешним системам.

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

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

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

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

Часть I. Обзор Самым сложным в работе над бизнес-логикой является, вероятно, выбор того, что именно и как следует относить к тому или иному слою. Мне нравится один неформальный тест. Вообразите, что в программу добавляется принципиально отличный слой, например интерфейс командной строки для Web-приложения. Если существует некий набор функций, которые придется продублировать для осуществления задуманного, значит, здесь логика домена "перетекает" в слой представления. Можно сформулировать тест иначе: нужно ли повторять логику при необходимости замены реляционной базы данных XML-файлом?

Хорошим примером ситуации является система, о которой мне когда-то рассказали.

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

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

Впрочем, мне не хотелось бы выглядеть сухим доктринером. Рецензируя эту книгу, Алан Найт (Alan Knight) как-то признался, что он "разрывался между тем, считать ли передачу подобной функции в ведение пользовательского интерфейса первым шагом на скользкой дорожке, ведущей прямиком в преисподнюю, либо вполне разумным компромиссным решением, с которым не согласился бы только отъявленный буквоед". Причина, которая беспокоит нас обоих, состоит в том, что на самом деле верны оба вывода!

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

В большинстве случаев существует только два варианта размещения и выполнения компонентов корпоративных приложений — на персональном компьютере и на сервере.

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

Общие аргументы в пользу размещения каких-либо слоев на компьютере клиента состоят в повышении быстроты реагирования (responsiveness) приложения и в обеспечении возможности локальной работы. Чтобы код сервера смог отреагировать на действия, предпринимаемые пользователем на клиентской машине, требуется определенное время.

А если пользователю необходимо быстро опробовать несколько вариантов и немедленно увидеть результат, продолжительность сетевого обмена становится серьезным препятствием. Помимо того, приложению требуется сетевое соединение как таковое. В частности, размышляя над этими строками, я находился в десяти километрах от ближайшего пункта, где можно было бы подключиться к сети, но хотелось бы, чтобы сетевой доступ обеспечивался везде. Может быть, в обозримом будущем так и случится, но что делать жителям какой-нибудь тьмутаракани, которые не желают ждать, пока кто-то из операторов беспроводной связи удосужится обеспечить "покрытие" их Богом забытого селения?

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

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

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

Решение о том, где должен функционировать слой представления, большей частью зависит от предпочтений в выборе типа пользовательского интерфейса. Применение интерфейса толстого клиента автоматически влечет за собой необходимость размещения слоя представления на клиентской машине. Использование Web-интерфейса означает, что логика представления сосредоточена на сервере. Существуют и исключения, например удаленное управление клиентским программным обеспечением (таким, как Х-сервер в UNIX) с запуском Web-сервера на настольном компьютере, но они редки.

Если речь идет о создании системы типа "поставщик-потребитель" ("business to customer" — В2С), у вас просто нет выбора. К серверу может подключиться любой, и вы вряд ли будете мириться с потерей посетителя только из-за того, что он использует какоето экзотическое программное или аппаратное обеспечение. Поэтому целесообразно все функции сконцентрировать на сервере, а клиенту передавать материал в формате HTML, полностью готовый для воспроизведения с помощью Web-обозревателя. Подобное архитектурное решение ограничено в том, что реализация самой незначительной логики пользовательского интерфейса требует обращения к серверу, а это не может не сказаться на быстроте реагирования приложения. Уменьшить зависимость от сервера можно за счет применения фрагментов кода на языках сценариев Web-обозревателя (подобных JavaScript) и загружаемых аплетов, но подобные меры снижают уровень совместимости обозревателей и вызывают другие проблемы. Чем более "чист" код HTML, тем проще жизнь.

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

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

А как быть с кодом бизнес-логики? Его можно активизировать или целиком на сервере, или полностью в контексте клиентской части, или используя смешанный стиль.

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



Pages:     || 2 | 3 | 4 | 5 |   ...   | 7 |


Похожие работы:

«Федеральная служба по гидрометеорологии и мониторингу окружающей среды Федеральное государственное бюджетное учреждение ГЛАВНАЯ ГЕОФИЗИЧЕСКАЯ ОБСЕРВАТОРИЯ им. А.И. ВОЕЙКОВА МЕТОДИЧЕСКОЕ ПИСЬМО ОБ ИТОГАХ РАБОТЫ В 2012 ГОДУ ФУНКЦИОНИРУЮЩЕЙ СЕТИ МРЛ-ШТОРМООПОВЕЩЕНИЯ И СЕТИ ДОПЛЕРОВСКИХ МЕТЕОРОЛОГИЧЕСКИХ РАДИОЛОКАТОРОВ С-ДИАПАЗОНА (ДМРЛ-С), СОЗДАВАЕМОЙ В РАМКАХ ФЦП. Санкт- Петербург 2013 Поручением Федеральной службы по гидрометеорологии и мониторингу окружающей среды (Росгидромета) от 29.11.1999г....»

«УТВЕРЖДАЮ Зав. кафедрой УМС _Д.Г.Арсеньев 25.12.2013 Программа государственного итогового междисциплинарного экзамена специалистов (2013/2014 учебный год) 1. Основы менеджмента 1. Сущность управления. Организации и их общие характеристики. 2. Профессиональные качества и функции менеджера. 3. Организационные решения. Факторы, влияющие на принятие управленческих решений. 4. Мотивация персонала. 5. Разработка организационной структуры и распределение полномочий. 6. Сущность и процесс контроля в...»

«Министерство культуры Свердловской области Свердловская областная специальная библиотека для слепых Отдел внестационарного обслуживания Технологии адаптации мира: организация обслуживания незрячих и слабовидящих пользователей в библиотечном пункте Методическое пособие Екатеринбург 2012 УДК 02 ББК 78.3 Т 38 Технологии адаптации мира: организация обслуживания неТ 38 зрячих пользователей в библиотечном пункте : методическое пособие / Свердл. обл. спец. б–ка для слепых ; сост.: В. В. Арсентьева, И....»

«10-11 класс СРЕДНЕЕ (полное) ОБЩЕЕ ОБРАЗОВАНИЕ Русский язык Дрофа Соответствует федеральному компоненту государственного стандарта общего Розенталь Д.Э. Русский 1 2012 образования 2006г. Подготовка к ЕГЭ-2013. Н.А. Сенина. язык. 10-11 кл. Греков В.Ф., Крючков Сиденко Н.В. Пособие для занятий по русскому языку в старших классах, Просвещение 2 С.Е., Чешко Л.А. Волгоград, 2006. Сочинение на ЕГЭ. Курс интенсивной подготовки. Н.А. Сенина, 2012 А.Г. Нарушевич. Пособие для занятий по русскому языку в...»

«ПЕНЗЕНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Кафедра Экономическая теория и мировая экономика КОНТРОЛЬНЫЕ РАБОТЫ И МЕТОДИЧЕСКИЕ УКАЗАНИЯ К ИХ ВЫПОЛНЕНИЮ по дисциплине Макроэкономика для студентов заочного отделения экономических специальностей (2 семестр) 2013 – 2014 учебного года Преподаватель: к.э.н., доцент Сафонова О.Н. Литература: 1. Макроэкономика: учебное пособие / А. А. Рыжков, Ю. А. Рыжкова. – Пенза : ИИЦ ПГУ, 2008. 2. Экономическая теория: учебно-методическое пособие / А.И. Дралин, С.Г....»

«МИНИСТЕРСТВО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ ПЕНЗЕНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ВЫБОР И РАСЧЕТ ТЕПЛООБМЕННИКОВ Учебное пособие Пенза 2001 УДК 66.021.1:532.5 Предложены: последовательность выбора и расчета теплообменников, даны методики расчетов основных узлов и справочный материал, необходимые при выполнении курсовых и дипломных проектов по темам ставящим своей целью разработку и модернизацию конструкций теплообменников. Учебное пособие подготовлено на кафедре Химическое машиностроение и...»

«ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ РФ ГОУ ВПО АЛТАЙСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Исторический факультет Кафедра отечественной истории Методические указания к спецкурсу Барнаул 2008 Текст печатается по решению кафедры отечественной истории Алтайского государственного университета. Составитель: доктор ист. наук, профессор Ю.М. Гончаров Рецензент: доктор ист. наук, профессор А.Р.Ивонин Быт горожан Сибири во второй половине XIX – начале XX в.: Методические указания к спецкурсу для студентов и...»

«Федеральное агентство по образованию Федеральное государственное образовательное учреждение среднего профессионального образования Прокопьевский горнотехнический колледж им. В.П.Романова МЕТОДИЧЕСКИЕ УКАЗАНИЯ Единые требования к содержанию и оформлению курсовых и дипломных проектов Тимофеева Е.Л., Самородова Е.П. Методические указания по составлению и оформлению курсовых и дипломных проектов стр. 1 из 80 По решению методического Совета Федерального государственного образовательного учреждения...»

«Удмуртский государственный университет НАУЧНАЯ БИБЛИОТЕКА МЕТОДИЧЕСКОЕ ПОСОБИЕ по оформлению списка литературы к курсовым и дипломным работам Сост.: Никитина И. В., Гайнутдинова И. Х., Зайцева Л. Е., Попова С. Л. Ижевск 2010 Содержание 1. Оформление курсовых и дипломных работ 2. Оформление списка литературы к курсовым и дипломным работам 3. Библиографическое описание документов Аналитическое описание Сокращения слов и словосочетаний, используемые в списке 13 4. Оформление библиографических...»

«По заказу кафедры охраны окружающей среды и безопасности жизнедеятельности. Новые издания учебно-методической и научной литературы в области экологии и охраны окружающей среды Дончева А. В. Экологическое проектирование и экспертиза: Практика: Учебное пособие для студентов вузов / А. В. Дончева. — М.: Аспект Пресс, 2005. — 286 с. Учебное пособие посвящено основам практической деятельности в области экологического проектирования и экологических экспертиз. В пособии даны правовая и нормативная...»

«Старославянский язык: учебник для филологических факультетов университетов, 2003, Галина Ивановна Климовская, 5946210629, 9785946210621, Томский государственный университет, 2003 Опубликовано: 5th May 2008 Старославянский язык: учебник для филологических факультетов университетов СКАЧАТЬ http://bit.ly/1cpGSVM Лексическая семантика синонимические средства языка, Юрий Дереникович Апресян, 1974, Semantics, 366 страниц.. Мифология славян, Алексей Николаевич Соболев, Юрий Сандулов, 1999,...»

«ПРОБЛЕМЫ СОВРЕМЕННОГО ОБРАЗОВАНИЯ www.pmedu.ru 2011, №3, 88-93 СОВРЕМЕННЫЕ ПОДХОДЫ К ИЗУЧЕНИЮ ЛИТЕРАТУРЫ MODERN APPROACHES TO LITERATURE STUDYING Ланин Б.А. Главный научный сотрудник Института содержания и методов обучения РАО, доктор филологических наук, профессор E-mail: [email protected] Lanin B.A. Chief research scientist at the Institute for content and methods of training (Russian Academy of Education), Doctor of Philology, Professor Рецензия на книги: Самарские филологи: Яков...»

«СОДЕРЖАНИЕ Образовательной программы по велосипедному спорту МБОУ ДОД велосипедной ДЮСШ Импульс РАЗДЕЛ СТР. ПОЯСНИТЕЛЬНАЯ ЗАПИСКА 2 стр. ОБЩЕЕ ОПИСАНИЕ ДЕЯТЕЛЬНОСТИ 5 стр. ЭТАПЫ ПОДГОТОВКИ И ИХ ЗАДАЧИ 9 стр. ОРГАНИЗАЦИОННО-МЕТОДИЧЕСКИЕ УКАЗАНИЯ ПО ПОДГОТОВКЕ ВЕЛОСИПЕДИСТОВ 12 стр. ПЛАНИРОВАНИЕ УЧЕБНО – ТРЕНИРОВОЧНОГО ПРОЦЕССА 12стр. ПОЯСНИТЕЛЬНАЯ ЗАПИСКА К УЧЕБНОМУ ПЛАНУ 19 стр. УЧЕБНЫЙ ПЛАН 20 стр. НАПОЛНЯЕМОСТЬ ГРУПП И РЕЖИМ УЧЕБНО-ТРЕНИРОВОЧНОЙ РАБОТЫ 21 стр. СООТНОШЕНИЕ СРЕДСТВ ФИЗИЧЕСКОЙ И...»

«Гигиена рук и использование перчаток в ЛПУ Москва 2007 Гигиена рук и использование перчаток в ЛПУ Под ред. академика РАЕН Л. П. Зуевой. — СПб., 2006. Данное модифицированное и дополненное издание разработано по заказу Учебно Консультационного Центра Открытого Института Здоровья в рам ках программы Инфекционная безопасность в ЛПУ для медработников и пациентов в 2007 году. Методические рекомендации подготовили К. Д. Васильев, С. Р. Еремин, А. В. Любимова, И. Г. Техова, Е. С. Трегубова, С. Браун....»

«Министерство образования Республики Мордовия Государственное бюджетное образовательное учреждение Республики Мордовия среднего профессионального образования (среднее специальное учебное заведение) Торбеевский колледж мясной и молочной промышленности ОТЧЕТ о результатах самообследования Государственного бюджетного образовательного учреждения Республики Мордовия среднего профессионального образования (среднее специальное учебное заведение) Торбеевский колледж мясной и молочной промышленности...»

«ПРОГРАММА вступительного испытания по Географии (бакалавриат) Казань 2014 Программа вступительных испытаний по географии Общие указания На экзамене по географии поступающий в высшее учебное заведение должен показать глубокие знания данного предмета, свободно ориентироваться по картам физическим, социально-экономическим и политикоадминистративным; уметь дать характеристику элементов природной среды (рельефа, климата, вод, почв, растительности, животного мира) и показать взаимосвязи, существующие...»

«Федеральное агентство по образованию Уральский государственный технический университет — УПИ СОВРЕМЕННОЕ ОТЕЧЕСТВЕННОЕ И ЗАРУБЕЖНОЕ ИЗДАТЕЛЬСКОЕ ДЕЛО Учебно-методическое пособие к лекционным и практическим занятиям для студентов дневной формы обучения специальности 030901 — Издательское дело и редактирование Екатеринбург УГТУ—УПИ 2008 УДК ББК Составитель доц., канд. физ.-мат. наук А. В. Зарубин Научный редактор проф., д-р филол. наук Т. В. Попова Современное отечественное и зарубежное...»

«Е. Н. КОВТУН Художественный вымысел в литературе ХХ века Учебное пособие Учебное пособие рассматривает фантастическую литературу ХХ в. в контекте развития иных типов художественного вымысла, в совокупности составляющих единую систему взаимосвязанных разновидностей повествования о необычайном. На примере прозы и драматургии российских, европейских и американских авторов в книге реконструируются оригинальные художественные структуры – модели реальности, характерные для фантастики, утопии, притчи,...»

«В. А. Максимов, Ф. Р. Карибуллина РОТОРНЫЕ КОМПРЕССОРЫ Учебное пособие 2005 Федеральное агентство по образованию Государственное образовательное учреждение высшего профессионального образования Казанский государственный технологический университет В. А. Максимов, Ф. Р. Карибуллина РОТОРНЫЕ КОМПРЕССОРЫ Учебное пособие Казань 2005 ББК 31.77 УДК 621.514.6 Роторные компрессоры: Учебное пособие/ В.А. Максимов, Ф.Р. Карибуллина; Казан.гос.технол.ун-т. Казань, 2005. 76с. ISBN 0-0000-0. Учебное пособие...»

«Федеральное агентство по образов анию ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Составитель Т.Н. Жилина ЭКОНОМИЧЕСКАЯ, СОЦИАЛЬНАЯ И ПОЛИТИЧЕСКАЯ ГЕОГРАФИЯ Методические указания для студентов направления 020400 – География Томск 2009 УДК 911.3 (075.8) Рекомендовано на заседании кафедры географии Томского государственного университета Составитель – доцент Жилина Татьяна Николаевна Курс Экономическая, социальная и политическая география изучается студентами-географами Томского государственного...»










 
2014 www.av.disus.ru - «Бесплатная электронная библиотека - Авторефераты, Диссертации, Монографии, Программы»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.