    Тестирование 

    14 ГЛАВА 

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

    Тестирование приложения 

    Существуют различные методики тестирования и оценки качества приложений, 
по каждой из которых написано несколько отдельных книг. Хотя я не могу здесь 
уделить этим вопросам должного внимания, однако постараюсь выделить основные 
принципы, которые не зависят от выбранной методики. Вот, например, некоторые 
советы о том, как нужно подходить к оценке пригодности приложения. 
    Q Задайте себе вопрос, соответствует ли приложение сформулированному в 
начале его разработки назначению. Тестирование приложения — это не только и не 
столько поиск ошибок, сколько оценка полноты и правильности выполненной 
работы. На этом этапе нужно установить, имеется ли расхождение между 
требованиями, предъявляемыми к приложению, и тем, что оно делает на самом деле. 
    Q Сравните реализацию основных функций приложения с теми задачами, которые 
были выделены в качестве таких функций на этапе анализа. В данном случае нужно 
оценивать уже не приложение в целом, а отдельные его подсистемы, реализующие 
основные функции приложения. Постарайтесь найти ответы на такие вопросы: 
"Выполняется ли эта функция? Должна ли данная подсистема реализовывать именно 
эту функцию? Можно ли измерить полноту выполнения той или иной функции?" 
Другими словами, при тестировании нужно не только "латать дыры" приложения, но 
и постоянно проверять его соответствие определенным на начальных этапах спецификациям. 
    Если приложение в целом прошло проверку на пригодность к эксплуатации, 
можно переходить к оценке и тестированию его отдельных составляющих. Нужно 
выполнить как внутреннее, так и внешнее тестирование. Внутренее тестирование 
выполняется разработчиками приложения, а внешнее — вашими коллегами, не 
участвовавшими в проекте, пользовательскими группами бета-тестирования и т.п. 
Приведу некоторые советы по выполнению внутреннего тестирования. 
    Q Проверьте, как работают ограничения, налагаемые на базу данных. 
    Q Проверьте объекты сервера — хранимые процедуры и представления, чтобы 
убедиться, что они работают так, как предполагалось. 
    Q Проведите тестирование работы приложения в многопользовательском режиме. 
    О Проверьте, выполняется ли управление доступом в соответствии с правами, 
которые вы назначили пользователям. 

    Глава 14. Тестирование 295 

    Q Постарайтесь воссоздать на компьютерах, где будет проходить 
тестирование, программную и аппаратную конфигурацию, которая была бы как можно 
ближе к конфигурации компьютеров будущих пользователей вашего приложения. 
    А вот некоторые советы по выполнению внешнего тестирования. Q Разработайте 
официальную процедуру сообщения об обнаруженных ошибках и ответа на такое 
сообщение. Q Выберите средство, облегчающее распространение исправленных и 
обновленных версий. 
    Q Создайте для тестирования группу из хорошо подготовленных пользователей, 
не принимавших участия в проекте. 
    Q Создайте небольшую группу бета-тестирования, куда вошли бы типичные 
представители всех групп пользователей вашего приложения. 
    Q Протестируйте, насколько удобно приложение в работе, привлекая для этого 
пользователей с разным уровнем подготовки. 
    Q Помните, что последнее слово в оценке приложения всегда остается за 
пользователем. Взаимодействие с пользователем — это не одна из составных 
частей вашей работы при тестировании. Взаимодействие с пользователем — это и 
есть ваша работа на данном этапе. 
    Как вы понимаете, существует много различных способов применения 
вышеперечисленных советов, особенно по внутреннему тестированию, к приложению 
RENTMAN. По вполне понятным причинам их всестороннее изложение выходит за 
рамки данной книги. 
    Остановимся сначала на первом и самом главном вопросе — соответствует ли 
созданное приложение сформулированному ранее назначению. В главе 8, 
"Проектирование базы данных архитектуры клиент/сервер" говорится: "Система 
RENTMAN обслуживает управление арендой недвижимости". 
    Соответствует ли созданное приложение своему назначению? По крайней мере 
на первый взгляд, можно ответить утвердительно. Окончательный ответ, конечно 
же, может дать только компания-заказчик. 
    Теперь давайте перейдем к основным функциям приложения. Снова вернемся к 
главе 8 и вспомним, как формулировались основные функции, которые должна была 
выполнять создаваемая система. 
    Q Система регистрирует и хранит договоры аренды. 
    Q Система отслеживает выполнение текущих эксплуатационных работ. 
    Q Система генерирует счета для арендаторов. 
    Q Система выдает информацию об аренде каждого объекта недвижимости. 
    И снова, по крайней мере при поверхностном знакомстве, можно сказать, что 
основные функции системы RENTMAN соответствуют сформулированным ранее 
спецификациям. Снова, как и в предыдущем случае, последнее слово остается за заказчиком. 
    Итак, успешно преодолев два главных препятствия, можно приступать к 
собственно тестированию приложения. Давайте разберем приведенные выше советы 
по выполнению внутреннего тестирования и посмотрим, как они применяются к 
приложению RENTMAN. 

    Проверка ограничений базы данных приложения 

    Чтобы быть полностью уверенным в корректности выполнения ограничений 
целостности ссылок и объектов, которые вы реализовали на этапе разработки, 
нужно их протестировать на различных режимах. Например, для приложения RENTMAN 
можно попытаться создать такие ситуации, нарушающие эти ограничения. 
    Q Удалите запись с данными арендатора из таблицы TENANT, у которого 
имеется действующий договор аренды в таблице LEASE. 
    Q Введите значение поля City таблицы PROPERTY, отличное от Richardson, 
Dallas, Piano, Norman, Oklahoma City И Edmond. 
    Q Удалите из таблицы PROPERTY запись об объекте недвижимости, для которого 
в таблице LEASE существуют записи о договорах аренды. 
    Q Пропустите при вводе данных записи таблицы PROPERTY поле Deposit. 
    Q Введите неправильную дату в поле StartDate таблицы WORDER. 
    Q Добавьте в таблицу PROPERTY запись об объекте недвижимости, который 
имеет 6 спален (bedroom). 
    Список можно продолжать, но, думаю, общий подход вам ясен. Основная идея 
заключается в проверке выполнения ограничений путем их преднамеренного нарушения. 

    296 Часть II. Учебный курс 

    Проверка объектов сервера 

    Если в вашем приложении имеются такие объекты сервера базы данных, как 
хранимые процедуры, представления и т.п., их нужно обязательно протестировать. 
Многие разработчики уделяют основное внимание клиентной части приложения, 
забывая о том, что в системах клиент/сервер объекты сервера также имеют 
"большое значение. В конце концов; язык SQL — такой же язык программирования, 
как Object Pascal или C++, и в его процедурах также могут быть ошибки. Вот 
лишь некоторые советы по поводу того, на что нужно обратить внимание. 
    Q Если вы создаете отчеты с помощью хранимых процедур, запустите эти 
процедуры вне среды приложения или системы конструирования отчетов, чтобы 
убедиться, что эти процедуры работают в соответствии с предъявляемыми к ним 
требованиям. Запуск хранимых процедур вне приложения позволяет просматривать 
сообщения сервера и другую информацию, которая часто игнорируется приложением 
или другим программным обеспечением, предоставляющим доступ к базе данных. 
    Q Если при выполнении каких-либо операций в СУБД используются хранимые 
процедуры, попробуйте модифицировать данные способом, который не должен 
допускаться базой данных или самими процедурами. Например, если хранимая 
процедура при добавлении строки к таблице базы данных проверяет передаваемые 
ей в качестве параметров значения, попробуйте указать неверные значения, чтобы 
убедиться, что хранимая процедура выявит эту ситуацию. Если в хранимых 
процедурах используются такие элементы, как команды СУБД, то нужно предпринять 
меры, обеспечивающие их правильное выполнение. Другими словами, не надо 
полагаться на то, что операции и команды СУБД все сделают правильно — лучше 
позаботиться об этом самостоятельно. 

    Тестирование в многопользовательской среде 

    При создании системы, с которой одновременно будет работать много 
пользователей, существуют два самых главных вопроса, на которые нужно обращать 
внимание прежде всего. Во-первых, это совместный доступ к данным. При попытке 
большого количества пользователей получить одновременно доступ к одному 
ресурсу базы данных возникает множество различных проблем, большинство которых 
связано с блокировкой. Пользователь может блокировать доступ других 
пользователей к нужным им ресурсам. Процесс может заблокировать выполнение 
другого процесса. Короче говоря, при совместном доступе к данным может 
произойти очень много событий, которые трудно поддаются планированию и часто 
ускользают от внимания неопытных разработчиков систем клиент/сервер. 
    "Во-вторых, необходимо помнить о требованиях к ресурсам. Система, которая 
обеспечивает хорошую производительность при одновременной работе 10 
пользователей, может резко ухудшить ее при увеличении количества пользователей 
до 20. Часто подключение лишь одного дополнительного пользователя приводит к 
перегрузке системы, даже если он не блокирует ресурсы или линию связи. Дело в 
том, что существуют физические ограничения на объем данных, обрабатываемых 
сервером, пропускную способность сетевых плат и самой сети в целом. Чем больше 
пользователей системы, тем жестче эти ограничения. 
    Самый лучший способ заранее выявить все подобные ситуации заключается в 
реализации при тестировании самого худшего сценария. Например, если вы 
уверены, что количество пользователей, одновременно~работающих с вашей 
системой, никогда не превысит 200 человек, все же постарайтесь протестировать 
ее производительность при одновременной работе 400 человек. Если вы по опыту 
знаете, что к тому или иному объекту никогда не будет обращаться несколько 
пользователей, обязательно проверьте, как поведет себя система, когда это 
событие произойдет. Какой бы маловероятной ни была ситуация, никто не может 
гарантировать, что она никогда не произойдет. 
    Важно также как можно точнее установить границы, при выходе за которые 
производительность системы падает ниже допустимого уровня. Постарайтесь, если 
это возможно, получить количественные характеристики таких граничных параметров. 
    Подводя итог всему вышесказанному, можно сказать, что чем больше 
пользователей у вашей системы, тем больше у вас будет забот. 

    Управление совместным доступом в модели клиент/сервер 

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

    Глава 14. Тестирование 297 

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

    With taLEASE do 
    While not EOF do begin 
       If taLEASEPetDeposit.AsFloatoO then taLEASELawnService.AsBoolean:=False ; 
          Next; 
    end; 

    При работе с локальными таблицами в таком подходе нет ничего плохого. 
Однако применение его к серверу базы данных может повлечь за собой целый ряд 
проблем. Кроме того, данный подход в СУБД клиент/сервер снижает 
производительности системы. Почему? Во-первых, потому, что при каждом 
присвоении значения столбцу LawnService блокируется вся таблица LEASE. Это 
влечет за собой приостановку работы всех остальных пользователей. Кроме того, 
блокировка таблицы сама по себе является достаточно длительной операцией. 
Во-вторых, при превышении определенного количества заблокированных строк 
сервер может распространить блокировку страницы или записи на всю таблицу, что 
заставит всех остальных пользователей ждать окончания выполнения цикла. Как вы 
понимаете, это не самое лучшее решение проблем такого рода. 
    В системах клиент/сервер для обновления большого количества записей нужно 
использовать SQL. Какой бы подход вы не предпочли — хранимые процедуры или 
обычные запросы, в любом случае помните о недопустимости работы с отдельными 
записями. Сервер сделает это за вас и применит те подходы, которые в данной 
СУБД являются оптимальными. Например, следующий запрос SQL выполняет те же 
операции, что и приведенный выше фрагмент. 

    UPDATE LEASE 
    SET LawnService="F" 
    WHERE PetDepositOO AND LawnServiceo'F' 

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

    Транзакции и серверы баз данных 

    Вы, должно быть, помните, что транзакциями называются группы операций по 
изменению базы данных, обрабатываемые как единое целое. При обработке 
транзакций не имеет значения, применяются ли к базе данных внесенные в нее 
изменения или нет. Для управления внесением изменений существуют специальные 
журналы обработки и отмены транзакций, от правильного управления которыми 
зависит надежность и производительность работы системы в целом. Правильная 
установка размера таких журналов, обеспечение их сохранности и невозможности 
случайного удаления, эффективное управление сохранением и откатом транзакций — 
вот лишь малая часть тех задач, которые должен решить разработчик системы клиент/сервер. 
    В приложениях архитектуры клиент/сервер, созданных с помощью Delphi, 
управление транзакциями на сервере осуществляется с помощью компонента 
TDatabase. Для того чтобы начать транзакцию, используется метод 
StartTransaction этого компонента, для ее сохранения в базе данных — метод 
Commit, а для отката — метод Rollback. Вызов данных методов в приложении 
клиент/сервер эквивалентен выдаче соответствующих команд SQL на сервере. 
Например, вызов MeTOAaStartTransaction объекта dbRENTMAN для запуска 
транзакции по базе данных RENTMAN эквивалентен выдаче команды InterBase SET TRANSACTION. 

    Уровни разграничения транзакций 

    Еще одной важной областью управления транзакциями является использование 
уровней разграничения транзакций, с помощью которых обеспечивается 
невозможность потери данных и возникновение конфликтных блокировок. Уровень 
разграничения транзакции (TIL — transaction isolation level) обеспечивает 
доступ транзакции к информации об изменениях, вносимых другими, выполняющимися 
одновременно с данной, транзакциями и наоборот. 

    298 Часть II. Учебный курс 

    Использование TIL обеспечивается через свойство Trans Isolation компонента 
TDatabase. Это свойство может принимать одно из трех значений: tiDirtyRead, 
tiReadCommited И tiRepeatableRead. Когда свойство Translsolation имеет 
значение tiDirtyRead, возвращается информация о всех изменениях строк, которые 
были сделаны как данной транзакцией, так и всеми остальными, причем независимо 
от того, сохранены эти изменения или нет. При установленном значении 
tiReadCommitted возвращаются сведения только о сохраненных изменениях. Если же 
установлено значение tiRepeatableRead, то возвращаются строки в том виде, 
который они имели на момент начала транзакции. В последнем случае содержимое 
строк соответствует их начальному состоянию, даже если какая-то другая 
транзакция сохранила на диске новые значения столбцов этих строк во время 
выполнения текущей транзакции. 
    В зависимости от выбранного уровня T1L, изменяется и вероятность 
возникновения конфликтных блокировок. Как правило, сильнее всего снижают эту 
вероятность уровни tiRepeatableRead и tiReadCommited. Рассмотрим следующий 
пример. Допустим, у нас есть две транзакции — Trani и Тгап2. Если транзакция 
Trani имеет уровень TIL tiReadCommited и доступ для чтения и записи, а 
транзакция Tran2 — уровень tiRepeatableRead с таким же доступом, то они могут 
конфликтовать только при попытке одновременной модификации одной и той же 
строки. Так как вероятность такого события достаточно низка, то в данном 
примере это обеспечивает снижение частоты конфликтных блокировок на сервере и 
повышает безопасности системы с точки зрения потери внесенных изменений. В 
большинстве случаев вам вполне будет достаточно уровня tiReadCommited, который 
используется по умолчанию. 

    На заметку 

    Не все платформы поддерживают три уровня разграничения транзакций. Если 
тот или иной сервер СУБД не поддерживает какой-то из уровней, ВОЕ 
автоматически выбирает ближайший уровень, который по ограничениям является 
более жестким, чем отсутствующий. Более подробная информация приведена в главе 
23, "Совместный доступ к данным". 

    Совет 

    Большинство серверов баз данных позволяют отслеживать блокировки, которые 
они применяют к объектам баз данных. Например, в СУБД Sybase и Microsoft SQL 
Server для этих целей можно воспользоваться хранимой процедурой sp lock, а в 
системе Oracle — обратиться с запросом к таблице V$WAITSTAT. В СУБД InterBase 
получить информацию по блокировкам можно с помощью средства Lock Manager 
Statistics программы InterBase Server Monitor. При длительном наблюдении за 
возникающими конфликтными блокировками можно настроить приложение таким 
образом, чтобы свести их количество к минимуму и тем самым повысить 
производительность системы. 

    СВОЙСТВО UpdateMode 

    С помощью свойства UpdateMode компонентов Table и Query можно изменять тип 
операторов SQL, генерируемых при обновлении записи. Это, с одной стороны, дает 
вам определенные возможности управления совместным доступом к данным, 
используемым в Delphi, а с другой стороны, позволяет настраивать изменять 
показатели производительности и уровня защиты от потери обновленных данных. 
Свойство UpdateMode может принимать одно из трех следующих значений: 
upWhereAll, upWhereChanged и upWhereKeyOnly. В зависимости от выбранного 
значения, изменяется вид операторов, используемых в ключевом слове WHERE для 
поиска обновляемой строки. 
    ТСогда в таблицу или набор данных, возвращаемый запросом, вносятся 
изменения, генерируется оператор SQL UPDATE для выполнения модификации на 
сервере. Если свойство UpdateMode имеет значение upWhereAll, то после 
ключевого слова WHERE оператора UPDATE будут перечислены все столбцы таблицы 
или набора данных запроса. При использовании значения upWhereChanged 
указываются только ключевые поля и поля, в которые вносятся изменения. Если же 
установлено значение upWhereKeyOnly, то в списке указываются только ключевые поля. 
    По умолчанию установлено значение upWhereAll, однако соответствующие 
условия отбора могут во многих ситуациях быть слишком строгими. Для 
большинства случаев вполне достаточно режима upWhereChanged, который является 
одновременно безопасным и более быстрым, чем режим upWhereAll. Без 
предварительной консультации с администратором базы данных режим 
upWhereKeyOnly лучше не использовать. Если вам нужен режим очень быстрого 
обновления таблицы, к которой вы обладаете правом эксклюзивного доступа, то 
режим upWhereKeyOnly подойдет как нельзя лучше. Однако в многопользова

    Глава 14. Тестирование 299 

    тельских приложениях применение этого режима может привести к потере 
обновлений данных, вносимых одновременно несколькими пользователями. Еще раз 
подчеркиваю, что значением upWhereKeyOnly свойства UpdateMode можно 
пользоваться только по согласованию с администратором базы данных. 
    Увидеть, как проявляется значение свойства UpdateMode можно с помощью 
средства Delphi SQL Monitor. Это средство позволяет заглянуть под покров BDE и 
увидеть, как происходит взаимодействие приложения и базы данных. Кроме того, с 
помощью SQL Monitor можно просматривать операторы SQL, которые приложение 
направляет серверу базы данных. 
    Для того чтобы увидеть это в действии, выберите пункт SQL Monitor из меню 
Database Delphi и пометьте пункт Always on Top в подменю Options средства. 
Затем запустите приложение RENTMAN и нажмите <F4>, чтобы открыть форму работы 
с таблицей PROPERTY. Как только форма появится на экране, измените 
какое-нибудь ее значение и щелкните на кнопке Post навигатора. Затем 
прокрутите верхнюю панель окна SQL Monitor, пока не найдете оператора UPDATE, 
и щелкните на нем. Появится весь исходный текст' оператора, который приложение 
направляет серверу для модификации таблицы. Обратите внимание на то, что в 
операторе перечислены все поля таблицы. 
    Теперь закройте SQL Monitor и выйдите из приложения. Откройте форму модуля 
данных dmRENTMAN в окне конструктора форм и измените значение свойства 
UpdateMode компонента taPROPERTY на upWhereChanged. Снова запустите SQL 
Monitor и приложение, внесите изменение в таблицу PROPERTY и найдите в окне 
SQL Monitor сгенерированный оператор UPDATE. Щелкните на этом операторе и вы 
увидите, что количество полей, перечисленных после ключевого слова WHERE 
оператора, существенно уменьшилось. 
    Снова закройте SQL Monitor и приложение и измените значение свойства 
UpdateMode объекта taPROPERTY на upWhereKeyOnly. Сохраните внесенные изменения 
и опять запустите SQL Monitor и приложение. Теперь после внесения изменений в 
таблицу PROPERTY и открытия исходного текста сгенерированного оператора SQL 
UPDATE вы увидите, что количество перечисленных столбцов стало минимальным — 
их ровно столько, сколько абсолютно необходимо для поиска нужной записи. 
Однако будьте осто- " рожны со значением upWhereKeyOnly — скорость достигается 
за счет безопасности. Так как используются только значения ключевых полей, то 
изменения, вносимые одними пользователями, могут перекрыть изменения, вносимые 
другими пользователями. 

    Свойство CachedUpdates 

    Одним из возможных методов понижения уровня конфликтное™ блокировок на 
сервере базы данных является использование кэширования обновлений (cached 
update). Когда свойство CachedUpdates набора данных имеет значение True, то 
все изменения, выполняемые над этим набором, кэшируются, т.е. сохраняются в 
отдельных областях, до тех пор, пока вы не сохраните их с помощью вызова 
метода ApplyUpdates. 
    Давайте ознакомимся на практике с тем, как работает свойство 
CachedUpdates. Откройте форму модуля данных dmRENTMAN в окне конструктора форм 
Delphi. Щелкните на таблице taTENANT и установите ее свойство CachedUpdates 
равным True. Затем откройте форму fmRSYSMANO и щелкните на пункте Tenant 
подменю Tables. Измените оператор 

    fmRTENCGDO.Show; 

    на оператор 

    fmRTENCGDO.ShowModal; 

    Затем добавьте после него оператор 

    dmRENTMAN.taTENANT.ApplyUpdates ; 

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

    Замена запросов хранимыми процедурами и представлениями 

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

    300 Часть II. Учебный курс 

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

    SET TERM л; 
    CREATE PROCEDURE GetWorkDuration (WONum INTEGER) RETURNS (WorkDuration float) 
    AS BEGIN 
    FOR SELECT sum(WORKTYPE.TaskDuration) as WorkDuration 
    FROM WODETAIL, WORKTYPE 
    WHERE WODETAIL.WORK_TYPE_CODE = WORKTYPE.WORK_TYPE_CODE 
    AND WODETAIL.WORK_ORDER_NUMBER=:WONum 
    INTO :WorkDuration DO SUSPEND; 
    END " SET TERM ;•' 

    Определив хранимую процедуру, остается лишь заменить компонент Query 
компонентом StoredProc и соответствующим образом модифицировать исходный текст 
и объекты приложения. В результате не только ускорится работа приложения, но и 
появится возможность использования одних и тех же хранимых процедур из разных приложений. 
    Хорошим примером того, как в приложении RENTMAN можно использовать 
представления, является замена многих комбинаций "таблица-поле выборки" 
представлениями. Так, например, вместо использования в таблице WODETAIL поля 
выборки, которое получает информацию из таблицы WORKTYPE, можно применить 
представление, выполняющее объединение таблиц на сервере. Представление на 
уровне приложения обрабатывается точно так же, как и обычная таблица, однако в 
него можно сразу поместить поля из другой таблицы, например Description и 
TaskDuration из таблицы WORKTYPE, поэтому отпадает необходимость в полях 
выборки. Этот пример хорошо иллюстрирует то, как нужно перестраивать мышление 
при переходе к разработке баз данных архитектуры клиент/сервер с локальных 
СУБД, таких как Paradox и dBASE. 

    Совет 

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

    Проверка пользовательских прав доступа 

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

    Глава 14. Тестирование 301 

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

    Назначение прав с помощью команды GRANT 

    GRANT — это команда SQL, которая применяется для назначения прав 
пользователям. Для удаления тех или иных прав предназначена команда REVOKE. 
Обе команды имеют три параметра: права, которые вы назначаете или удаляете; 
объект, для которого устанавливаются или удаляются права; пользователь, права 
которого изменяются. Например, с помощью следующей команды SQL назначаются 
права доступа к таблице WORKTYPE: 

    GRANT ALL ON WORKTYPE TO PUBLIC 

    Данный оператор открывает все (all) права доступа (SELECT, INSERT, UPDATE, 
DELETE и REFERENCES) к таблице WORKTYPE для всех пользователей. Точно так же, 
с помощью следующего оператора можно удалить эти права: 

    REVOKE ALL ON WORKTYPE FROM PUBLIC 

    Совет 

    При переходе с локальных СУБД к системам клиент/сервер можно сохранить 
немало времени, используя присвоение или удаление прав с помощью групп. Для 
того чтобы дать все права доступа к определенной таблице сразу всем 
пользователям, можно воспользоваться операторами вида GRANT ALL ON имя_таблицы 
то PUBLIC. Затем можно тем или иным образом ограничить права тех 
пользователей, для которых это необходимо. 

    С помощью операторов GRANT и REVOKE можно также назначать и удалять 
какие-то определенные права. Например, можно назначить права с помощью 
оператора GRANT: 

    GRANT SELECT, INSERT, UPDATE ON EMPLOYEE TO PUBLIC 

    Точно так же можно удалить определенные права с помощью оператора REVOKE. 
REVOKE SELECT, INSERT, UPDATE ON EMPLOYEE TO PUBLIC 

    Если нужно, можно заменить имя группы PUBLIC конкретным регистрационным 
именем пользователя. Однако прежде чем это сделать нужно создать 
регистрационные записи пользователей. В отличие от большинства СУБД 
клиент/сервер, система InterBase не поддерживает групп пользователей (за 
исключением стандартной группы PUBLIC, конечно) и, кроме того, в ней, в 
отличие от СУБД Sybase и Microsoft SQL Server, регистрационные имена 
пользователей сервера и пользователей базы данных не отделены друг от друга. 
Таким образом, при создании в СУБД InterBase регистрационного имени 
пользователя, он сразу же получает доступ ко всем базам данных. 
    Для того чтобы настроить доступ к базе данных приложения RENTMAN, создайте 
с помощью средства InterBase Server Manager регистрационные имена 
пользователей. Для этого, запустив программу Server Manager, которая должна 
находиться в папке InterBase, зарегистрируйтесь на сервере с помощью команды 
File^Server Login. После регистрации на сервере, подключитесь к базе данных, 
выбрав команду File^Database Connection. 

    302 Часть II. Учебный курс 

    После подключения к базе данных нужно из меню Task выбрать команду User 
Security. С помощью этой команды можно добавлять регистрационные записи 
пользователей. На экране должно появиться окно InterBase Security. Щелкните на 
кнопке Add User этого окна, чтобы добавить новую регистрационную запись. 
Введите в соответствующих строках имя пользователя и пароль. Обратите внимание 
на то, что все буквы имени пользователя автоматически переводятся в верхний 
регистр. Однако пароль можно вводить как в нижнем, так и в верхнем регистре. 
Поэтому будьте внимательны — одинаковые пароли, введенные в разных регистрах, 
рассматриваются серверами как абсолютно разные. 
    После ввода необходимой информации, щелкните на кнопке ОК и тем самым 
создайте новую регистрационную запись на сервере. Теперь с помощью новых имени 
пользователя и пароля можно подключиться к любой базе данных СУБД InterBase, 
при условии, что пользователь, представленный этим именем, имеет необходимые 
права доступа к объектам той или иной базы данных. Как уже упоминалось выше, 
эти права можно предоставить с помощью команды GRANT. Например, для 
предоставления новому пользователю всех прав доступа к таблице TENANT нужно 
использовать следующую команду: 

    GRANT ALL ON TENANT TO MARY 

    Эту же команду можно применить к любой другой таблице, а также к 
представлениям и хранимым процедурам базы данных. 
    Кроме того, с помощью ключевого выражения WITH GRANT OPTION команды GRANT 
можно распространить права пользователя объекта на другого пользователя. 
Например, с помощью оператора 

    GRANT EXECUTE ON PROCEDURE LISTPROP TO MARY WITH GRANT OPTION 

    пользователю MARY предоставляется право выполнения (execute) хранимой 
процедуры LISTPROP, а также все права, имеющиеся у других пользователей для 
доступа к этой процедуре. 

    Совершенствование приложения 

    Более подробно вопросы совершенствования и подготовки приложения 
рассматриваются в главе 29, "Совершенствование приложения". Здесь я приведу 
лишь некоторые замечания по данной теме. 
    Q Выделите компьютер, который как можно точнее воссоздавал бы среду, в 
которой будет работать приложение, и проверьте, как проходит установка 
приложения на этом компьютере. 
    Q Старайтесь как можно меньше привязываться к программному обеспечению и 
аппаратным средствам компьютера пользователя. Изменяйте только те 
конфигурационные параметры приложения, которые абсолютно необходимы для его 
нормальной работы. 
    Q Исследуйте аппаратные средства и программное обеспечение, работающие у 
вашего заказчика, чтобы определить, какие дополнительные системы и средства 
могут понадобиться для работы вашего приложения. Например, если вы 
рассчитываете, что клиентная часть приложения будет взаимодействовать с 
серверной частью СУБД с использованием протокола TCP/IP, то на 
машинах-клиентах нужно будет установить поддержку этого протокола. В этом вам 
может понадобиться помощь администратора локальной сети. 
    Q Создайте программу установки приложения с помощью утилиты InstallShield 
Express, входящей в комплект поставки Delphi. Подробнее об использовании этой 
утилиты говорится в главе 29. 

    Резюме 

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

    Глава 14. Тестирование 303 

    Что дальше... 

    В главе 15 описываются вопросы, связанные с использованием баз данных 
Microsoft SQL Server. В ней рассказывается о таких особенностях разработки 
приложений для этой СУБД с помощью Delphi, как подключение к базе данных, 
администрирование, настройка запросов и т.п. 

    304 Часть II. Учебный курс 
