218 Часть II. Типовые решения
коллекций рекомендуется привязывать к объектам, а не к таблицам, поскольку объекты,
вообще говоря, не должны "знать" никаких деталей отображения.
Определение количества коллекций крайне затрудняет наследование. Если в базе
данных есть машины, являющиеся производным типом средств передвижения, сколько
нужно создать коллекций — одну общую или по одной на каждое средство передвиже-
ния? Размещение их в разных коллекциях может крайне усложнить полиморфные ссыл-
ки, поскольку каждому средству поиска нужно будет знать обо всех существующих кол-
лекциях. Поэтому я предпочитаю иметь одну общую коллекцию для каждой иерархии
объектов, однако в таком случае ключи объектов должны быть уникальными в пределах
своей иерархии, что весьма затруднительно при использовании наследования с таблицами
для каждого конкретного класса (Concrete Table Inheritance, 313).
Преимуществом использования единой коллекции объектов является то, что при до-
бавлении новых таблиц не требуется добавлять новые коллекции. Впрочем, привязка
коллекций к преобразователям данных (Data Mapper, 187) совсем несложна (см. ниже).
Куда их поместить?
Коллекции объектов нужно поместить туда, где их будет легко найти. Кроме того, они
должны быть привязаны к контексту текущего процесса. Каждый сеанс должен иметь свой
экземпляр коллекции объектов, полностью изолированный от экземпляров других сеансов.
Таким образом, коллекцию объектов следует поместить в объект, специфичный для сеанса.
Прекрасным кандидатом для этого может стать единица работы (Unit of Work, 205), по-
скольку она хранит в себе сведения обо всех объектах, извлеченных, обновленных, создан-
ных и удаленных на протяжении текущего сеанса. Если же вы не используете единицу рабо-
ты, рекомендую поместить коллекцию объектов в реестр, привязанный к сеансу.
Как уже отмечалось, каждому сеансу должна соответствовать своя коллекция объек-
тов; в противном случае придется обеспечить для нее транзакционную защиту, за что не
возьмется ни один здравомыслящий разработчик. Впрочем, существует несколько ис-
ключений. Наиболее значительное из них — это использование объектной базы данных в
качестве кэша транзакций, даже если данные при этом записываются в реляционную ба-
зу данных. Пока что я не встречал никаких независимых исследований на тему произво-
дительности кэша транзакций, однако думаю, что на это стоит обратить внимание. Це-
лый ряд весьма уважаемых мною людей — страстные приверженцы использования кэша
транзакций как способа увеличения производительности.
Вторым исключением является использование объектов, доступных только для чте-
ния. Если объект не может быть изменен, вам нет необходимости беспокоиться о том,
что он будет присутствовать в нескольких сеансах. В очень загруженных системах нали-
чие общей коллекции весьма удобно, поскольку позволяет однократно загрузить все дан-
ные, необходимые только для чтения, и затем использовать их на протяжении всего про-
цесса. В этом случае коллекции объектов, доступных только для чтения, будут использо-
ваться в контексте процесса, а доступных для обновления — в контексте сеанса. Это же
применимо и к объектам, которые изменяются так редко, что их можно безбоязненно
поместить в коллекцию объектов, доступную на протяжении всего процесса, а если изме-
нения все-таки произойдут, то можно обновить коллекцию, отправив соответствующий
запрос серверу.
Даже если вы твердо решили создать только одну коллекцию объектов, ее можно раз-
бить на две части: только для чтения и для обновления. Чтобы клиенты не догадались,