su13@pochta.ru

| Первый | Второй | Третий | Четвёртый | Пятый | Шестой | Седьмой |


Часть II.

Программирование баз данных

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

Глава №8.

Архитектуры приложений для работы с базами данных

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

Архитектура клиент/сервер

В упрощенном виде архитектура клиент/сервер предполагает разделение происходящей в приложении обработки на две или более логически различные части. До сих пор в этой книге мы обсуждали базы данных так, будто они существуют в некоем безвоздушном пространстве. Однако они выполняют свое предназначение только тогда, когда используются какими-либо приложениями. Упрощая, можно сказать, Что база данных составляет одну часть архитектуры клиент/сервер. База данных является «сервером», а всякое использующее ее приложение является «клиентом». Часто клиент и сервер расположены на разных машинах; в большинстве случаев приложение клиента является дружественным интерфейсом к базе данных. На рис. 8-1 графически представлена простая система клиент/сервер.

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

Рис. 8-1. Архитектура клиент/сервер

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

Внешний вид этих API для доступа к базам данных различен и зависит от языка программирования, а во многих случаях - и от самой базы данных. Поскольку API для MySQL намеренно разрабатывались так, чтобы иметь сходство с mSQL, у всех API, которые вы найдете в этой книге, различия минимальны.

Обработка данных

В части I «Введение в MySQL и mSQL» мы дали понятия управления транзакциями и результирующего набора. Приложение для работы с базой данных — всего лишь инструмент для управления транзакциями и обработки результирующих наборов. Например, если ваше приложение является адресной книгой, то обработка результирующих наборов заключается в том, чтобы извлечь из таблицы все строки и показать их пользователю. Управление транзакциями просто сводится к тому, чтобы изменения в таблицах address и person производились как единое целое.

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

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

«Уборка за собой» включает в себя правильную обработку ошибок. Хорошие языки программирования затрудняют пропуск обработчиков исключительных ситуаций (отказ сети, повторяющиеся ключи при добавлении, ошибки синтаксиса SQL и т. д.). Но независимо от того, какой язык вы избрали, вы обязаны знать, какие исключительные ситуации могут возникать при данном вызове API, и в каждой исключительной ситуации действовать надлежащим образом. С-библиотеки для MySQL и mSQL основываются на представлении базы данных в виде наборов строк. Мы хотим этим сказать, что библиотеки С позволяют непосредственно обращаться с данными в том виде, в каком они в принципе существуют в базе данных. Глава 13 «С и C++», раскрывает практические детали программирования в этой модели с использованием С API для MySQL и mSQL.

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

Объектное/реляционное моделирование

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

Практические правила для объектно-реляционного моделирования

  • У каждого сохраняемого класса в базе данных есть своя таблица.
  • Поля объектов с простыми типами данных (целые, символы, строки и т. д.) сопоставлены колонкам в соответствующей таблице базы данных.
  • Каждая строка таблицы базы данных cоответствует экземпляру соответствующего хранимого класса.
  • Каждая связь между объектами типа «многие-ко-многим» требует таблицы-связки, так же как это требуется для объектов базы данных типа «многие-ко-многим».
  • Наследование моделируется с помощью отношения «один-к-одному» между таблицами, соответствующими классу и подклассу.

Вспомните адресную книгу, о которой мы говорили ранее. Допустим, она имеет таблицы address и person, как на рис. 8-2.

Рис. 8-2. Модель данных простого приложения адресной книги

Есть весьма неочевидная проблема, с которой сталкиваются программисты. Основная задача объектно-ориентированного подхода к реляционным данным - это, получив эти данные, немедленно создать экземпляр объекта. Приложение должно работать с данными только через объекты. Большинство традиционных методов программирования, включая разработку на С, PowerBuilder и VisualBasic, требует, чтобы разработчик извлек из базы данные, а затем их обработал. Главное отличие состоит в том, что в объектно-ориентированном программировании баз данных вы имеете дело с объектами, а не данными.

Рис. 8-3 показывает объектную модель, соответствующую модели данных на рис. 8-2. Каждая строка базы данных преобразуется в программный объект. Таким образом, ваше приложение принимает результирующий набор и для каждой возвращаемой строки создает новый экземпляр Address или Person. Труднее всего справиться с проблемой, о которой уже говорилось: как в приложении установить связь между человеком и его адресом? Объект Person, конечно, имеет ссылку на объект Address, относящийся к этому человеку, но сохранить объект Address внутри таблицы person реляционной базы нельзя. Модель данных предполагает хранение связей между объектами с помощью внешних ключей, для чего в таблицу person заносится address_id.

Рис. 8-3. Объектная модель, поддерживающая простое приложение адресной книги

Самое незначительное усложнение объектной модели может вызвать бездну проблем при установлении соответствия наших объектов и модели данных. Допустим, что Person является потомком Entity и класс Company тоже является потомком Entity. Как отделить Entity от Person или Company? Приведенное выше правило фактически является скорее рекомендацией. В некоторых случаях базовый класс является чисто абстрактным и, следовательно, не имеет в базе связанных с ним данных. В таком случае для этого класса в базе данных не будет объекта.

Трехзвенная архитектура

До сих пор мы обсуждали самую простую архитектуру для работы с WWW и простыми бизнес-приложениями - клиент/сервер. Однако эту архитектуру не так-то просто нарастить по мере роста и изменения ваших приложений. В ней также трудно использовать преимущества объектно-ориентированного программирования. Первая проблема недавно нашла отражение в дискуссиях относительно «тонких клиентов». Потребность в тонких клиентах происходит из беспокоящей тенденции в передаче клиенту все больших объемов обработки. Эта проблема проявилась в PowerBuilder и VisualBasic - инструментах, которые прямо вытаскивают данные из базы в GUI, а затем все операции над этими данными проводят в GUI.

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

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

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

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

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

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

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

Рис. 8-4. Трехзвенная архитектура

Оглавление

GNU OCXE GNU LINUX
Сайт управляется системой uCoz