Table of Contents

Creating a Good Persistent Hierarchy

Using Objects as Objects

Why you ask, would people not want to use objects as objects? Many of us have received extensive exposure to relational database systems and as a result have become used to the machinations required to store objects away in relational database tables and then reconstitute them as objects at a later stage. Facets does not serialize or flatten objects prior to saving them, they are saved as they are. What this means in real terms is that your design should only consider the requirements of creating a good hierarchy and one that solves your business problem, rather than having to take into account the limitations of the storage mechanism. Consider the following example: when designing a hierarchy that will be stored in a relational environment, it is often a necessity for each object that will be stored in a collection to have a key that marks it as belonging to the collection, or belonging to the containing object. This is not required in Facets, since collections in Facets automatically know which objects they contain.

In Facets there are no limitations in terms of how objects are stored and we do not have to consider such issues as whether we implement inheritence by means of multiple tables or shared tables, or normalized tables. Additionally creating a very bushy hierarchy or a very deep one, does not have any impact on the performance of the database, Facets will perform as well no matter what the type of your hierarchy. This is quite unlike relational storage mechanisms, where the joins required to glue objects together in a very complex hierarchy can totally destroy the performance of your application.

Using objects as objects means that you are liberated from having to constrain your hierarchy design by the limitations of the database. In this case the database (i.e. Facets) works with you, rather than against you.

Sequential Access and Random Access

There are some consequences to the way that Facets stores objects, in that sequentially iterating through each and every object contained in a vast collection can force Facets to read a large number of pages from the repository. The net effect of this can be a condition which is known as "cache pressure" since the Facets shared page cache can be strained by the real time requirements of your applications, and the need to load and unload a large number of pages. Relational databases are optimized to store data in a sequential and linear manner wheras Facets is optimized to access data in an object oriented way, which typically means object graph traversal. The caching mechanism that Facets uses favours accessing graphs of objects, since the likelihood of Facets having already loaded the next object in a tree of objects by virtue of having loaded the current objects page, is extremely high. However, accessing a collection of objects sequentially can be less efficient since over time the objects contained in the collection will become spread out over a large number of pages, and this will force Facets to have to load and discard an increasing number of pages.

For these reasons, it is worthwhile taking some time to analyze and classify the mechanisms that your applications will use to access objects, and construct appropriate structures for enabling this access in an efficient manner. If your application will often sequentially process very large collections of objects, then either using indexes (which Facets does support) or regularly rewriting the collections so that there is a high page co-location factor will improve your applications performance.

Remember also that even if an object is referenced in a number of collections, there is still only one instance of that object, and the overhead associated with storing an object in a collection is small. This means that it can often be highly beneficial to reference an object from multiple collections in such a way that the collections partition the object set by some characteristic. A practical example of this would be a system that has a large number of Customer objects, say an online bookstore similar to Amazon.com. Sometimes the customers need to be looked up by name, other times by credit card number, and in some cases by interest. In this scenario we would create three separate CuHashMaps, one that is keyed by customer name, one keyed by credit card number and another keyed by interest. Because Facets only stores a reference to the customer in the collection, we incur very little overhead, but significantly speed up access.

Deciding on Persistence

While an ODBMS can transparently store any object, it is important to decide which objects are going to be made persistent and which not. It does not make sense to take objects whose primary purpose is to provide a service and make them persistent, it only makes sense to persist objects whose state is of value. Certainly one of the great values of object orientation is the ability to encapsulate both state and behavior, but in some cases objects have more value in terms of their behavior and their state. A good example of this is the MVC pattern.

It may often make sense to make the Model of the MVC persistent, because it will probably have state that is important, however, persisting the View or the Controller, just does not make any sense. since they can be recreated at any point without loss of state. What, you ask about the case where you wish to make certain parameters associated with the View or the Controller persistent, such as the state of the GUI the last time the user used it, or the position of the window when the application was closed. Well in this case, another pattern comes to the rescue and that is the Memento pattern, and this is used to encapsulate the internal state of the View or/and the Controller and then persist this for later re-use. It is often useful to consider a binary classification for objects when deciding on whether to persist them or not. Objects whose state is valuable over the long term, and which contribute to solving the problem at hand should be considered candidates for persistence, whereas other objects whose nature tends to be more transitory (such the the object that converts incoming web services calls into calls on underlying domain objects, CORBA implementation objects or Controllers as in MVC) should not be considered candidates for persistence.

©2005 GemStone Systems, Inc.