Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
PUIS.docx
Скачиваний:
7
Добавлен:
03.12.2018
Размер:
1.01 Mб
Скачать

Функциональные проблемы

Здесь и ниже, употребляя слово таблица (table), автор имеет в виду, что обсуждаемые приемы и решения применимы в равной мере ко всем данным, отличающимся табличным характером: к хранимым процедурам (stored procedures), представлениям (views), а также к (промежуточным) результатам выполнения «традиционных» запросов и хранимых процедур. К сожалению, какой-либо общий термин, который охватывал бы все эти понятия, отсутствует. (Под представлением подразумевается виртуальная таблица (virtual table) — то же толкование принято и в SQL; запросы к обычным и виртуальным таблицам обладают одним и тем же синтаксисом.)

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

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

Рассмотрим вопрос о том, как обеспечить загрузку различных объектов и сохранение их в базе данных. На первый взгляд это не кажется слишком сложной задачей: объект можно снабдить соответствующими методами загрузки (load) и сохранения (save). Именно такой путь целесообразно избрать, например, при использовании решения активная запись (Active Record).

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

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

Типовым решением, имеющим существенное значение для преодоления такого рода проблем, является единица работы (Unit of Work), использование которой позволяет отследить, какие объекты считываются и какие модифицируются, и обслужить операции обновления содержимого базы данных. Автору прикладной программы нет нужды явно вызывать методы сохранения — достаточно сообщить объекту единица работы о необходимости фиксации (commit) результатов в базе данных. Типовое решение единица работы упорядочивает все функции по взаимодействию с базой данных и сосредоточивает в одном месте сложную логику фиксации. Его лучшие качества проявляются именно тогда, когда интерфейс между приложением и базой данных становится особенно запутанным.

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

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

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

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]