Basic Relation API
Specification of a Basic API for a Relation Framework
(this is related to other proposals: AssociationService, RelationshipService, RelationManager that propose semantically richer APIs?)
Status
Author
Helmut Merz (helmutm@cy55.de)
Problem/Proposal
In object-oriented programming you usually don't care explicitly about relations: you just assign an object to an attribute of another object and you have created a relation beween these two objects.
An example: Let's have two classes, Person and City, and we want to store the
fact that a person lives in a certain city. So if clark is an instance
of Person and washington an instance of City we can just say:
clark.city = washington.
This works fine (also when you are dealing with persistent objects in Zope) and is the standard way of establishing a relation in an object-oriented programming language.
But there are scenarios where this is not sufficient and you have to care explicitly about relations.
One would be the requirement to get all inhabitants of Washington: You could of course do this by collecting all persons and check which ones have set it's city attribute to washington. This approach poses (at least) two problems:
- how can I find all instances of the Person class?
- depending on the numbers of persons in my system checking all might take a tremendous long time.
You can easiliy resolve these problems by providing a corresponding attribute
on the City class, something like washington.inhabitants = [clark] and add
a person to this list every time you assign washington to a person's
city attribute.
Of course there are other things to consider, e.g. how to handle deletions of objects.
But for this simple kind of relationships just connecting two objects you could in fact solve all this problems without the need for a special relation management framework. Nevertheless, as this is a common pattern, it would be helpful to have an agreed-upon standard how to handle such cases; this might deal with the automatic housekeeping of redundant assignments as well as with the deletion problem.
Such a standard - and a corresponding relation management framework - is getting really important when we deal with more complex use cases - involving e.g. triadic relations (connecting three objects) like in "kirk is the child of audrey and clark" or if we want the relation to carry additional information, e.g. like in "clark lived in washington from 1999 to 2003".
The Archetypes product for Zope 2 (a standard part of Plone) provides a "reference engine" that provides an implementation compatible to the API described here. In fact, the proposed relation framework API can be easily extended to cover the Archetypes reference engine; thus it would be fairly easy to write code for bridging the gap between Plone/Archetypes/Zope 2 on the basis of this API and its implementations.
Goals
Provide a basic, simple and convient API for handling relations (in the sense as described above) as an accepted standard. It should cover the great majority of use cases dealing with relations.
Note that this API is not intended to express any semantics and does not try to specifiy ways of defining constraints or rules for relations; this would be the task of - possibly domain-specific - higher-level APIs? that can be built on top of the basic one described here.
Note also that this proposal does not deal at all with possible implementations of the API described here; a default implementation will be discussed in a separate proposal.
Proposed Solution
The basic functionality is provided by only two primary interfaces (it makes sense to derive additional interfaces for convenience or in order to handle special cases):
- IRelation: a relation is an object that connects two or more
objects stored in attributes called
first,secondand - optionally -third. In addition the relation object is associated with a predicate that allows to discern different types of relations (also known as relationships) - IRelationRegistry: a relation registry keeps track of a set of relations (that are registered with the registry) and provides a method to search for relations using a relationship or predicate and the objects taking part in relations as the query criteria.
For details see the interfaces.py file from the
cyberconcepts.relation package;
you may check out this package with
svn co svn://svn.cy55.de/Zope3/src/cybertools/trunk/relation.
Risks
Programmers may be seduced to use this API in cases where simple object references would be sufficient and thus produce code that is more complicated and less efficient than necessary; a similar problem could arise with use cases that can't be covered by the standard API or can't be solved by efficient implementations of this API.
