[Zope-dev] RFC: RelationAware class for relations between objects

Shane Hathaway shane@zope.com
Tue, 29 Apr 2003 10:19:33 -0400


roche@upfrontsystems.co.za wrote:
> * Shane Hathaway <shane@zope.com> [2003-04-28 17:09]:
>>- Descriptors elegantly provide custom views on relations.  In the 
>>example, "zope3.developers" looks like a set of Developer objects.
> 
> 
> I haven't worked with descriptors before and forgot what they do. I
> reread AMK's, "What's new in Python 2.2" to help me understand what it
> is that Jeremy was doing. I must say that this is the kind of feature
> that makes me a jubilant python developer.

Descriptors are like the ExtensionClass computed attribute feature. 
Like ExtensionClass, a descriptor determines what happens when you get a 
particular attribute.  Unlike ExtensionClass, a descriptor also 
determines what happens when you set an attribute.  It's a nice enhancement.

>>I also feel that 
>>having a many2many function might be oversimplifying, since I came up 
>>with the need for a "many2many2many" function over the weekend.  That 
>>would be wrong!
> 
> 
> Won't this just be a chain of relations? You have to explain what you
> came up with.

Well, I started writing a student registration system.  First I wrote it 
something like this (shortened for simplicity):

class Student:
     courses = Relation()

class Course:
     students = Relation()

rel = many2many(Student.courses, Course.students)


Then I decided that registrations are really only temporary: a student 
should be assigned to a particular course only in a particular term (a 
term is a quarter or a semester), not all terms.  I tried something like 
the following.  As you can probably guess, I got lost. ;-)


class Term:
     courses = Relation()
     students = Relation()

class Student:
     current_courses = Relation()
     course_history = Relation()

class Course:
     current_students = Relation()
     student_history = Relation()

rel1 = many2many(Student.course_history, Course.student_history)
rel2 = many2many(Student.current_courses, Course.current_students,
                  Term.courses, Term.students)


rel1 makes sense, but I don't really know what the statement that 
constructs rel2 does.  For example, what kind of structure does it 
create?  How will it know that "Term.students" should return Student 
objects?  And what if I want to ask in which terms is a certain course 
available?  I'd like to just ask "Course.terms", but it's hard to guess 
how to spell that.

I'm going to suggest a solution in my reply to Jeremy.

>>We need to make sure the interface fits an existing, 
>>well-researched model for relationships.  I only know about relational 
>>tables, topic maps, and RDF.
> 
> 
> I'd also like to know what models exist. I am not absolutely clear on
> what the problem statement is. It seems that the problem lies with the
> underlying persistence framework and not with relationships between
> objects. The reason I say this is because we already know a natural way
> to "relate" objects in pure python.

I would state the problem this way: ZODB needs a reusable model for 
maintaining complex relationships between database objects.  It also 
needs a basic implementation of that model.

>>Max M: your example is useful and probably more manageable than 
>>ZCatalogs.  But I think it would be more useful if it provided an easy 
>>way to create relations in the code itself.  You only have a comment 
>>that says the relation already exists.  Jeremy's example creates the 
>>relation if it doesn't already exist, although it's only a basic 
>>relation.  You example would also be enhanced by the use of descriptors.
>>
>>Roche: your example is purely implementation, although the ideas look 
>>interesting.  Try writing something similar to Jeremy's example to 
>>evaluate the simplicity of your approach.
> 
> 
> I have one requirement though and that is that it should work with Zope
> 2 (not require it). Zope 2 apps are my bread and butter at the moment
> but for now I am going to assume that Zope 2 works fine with python 2.2
> and that a descriptor based solution is the way to go.

The descriptors are icing on the cake, IMHO.  You could still use 
ZODB-based relations without descriptors.

> I just have this itch and will bet on it that proper handling of
> relationships will save tons of code.

+1

Relations will also make ZODB usable for more applications.  Currently, 
a lot of people reject object-oriented databases as a way to build 
applications because of the difficulty of expressing complex relationships.

Shane