|
From: John B. <jb...@dr...> - 2003-11-10 22:10:18
|
On Monday 10 November 2003 21:54, Ian Bicking wrote:
> And this is just what makes me nervous. What does the Item table look
> like? How does it relate to the rest of the system, and how does it
> grow? Presumably Bill and other classes are keyed off of item_id, but
> how do you know which kind of Item you are working with?
You don't. That's how it starts to become efficient. However a common method
is to add a 'filter' column to your top level table to say what type of
object it is.
> Superclasses shouldn't have to be aware of subclasses, but I don't see
> how that can happen with this system. Also, you get all sorts of
> weirdness in class creation -- essentially Item.__new__ will have to
> return a Bill instance, or some other instance, depending on the ID.
There's no reason why they can't be aware, in the form of a "key" column. But
stop worrying about that, you're writing an object storage system. The person
writing objects to map to a database shouldn't and won't care about all of
this. They shouldn't even have to know SQL, all they care about is using a
system that persists objects.
In a perfect world, the system of storage is irrelevant to the person writing
the code. Files/SQL/ObjectDatabases/SmokeSignals/Pigeons. It doesn't matter,
the magic should be nothing more than a transparent interface to storage and
retrieval, without them having to worry about "not being able to do this
because the mapping tool doesn't support superset mappings".
I realise the world isn't perfect. :)
> What looks like inheritance isn't really inheritance, it's something
> else. I don't know what to call it, but I don't want to create a false
> cognate by phrasing it incorrectly -- especially when its in relation
> to something with the complex semantics of a Python class.
Think OO! Why do we even bother with object structures? We bother to separate
functionality and appropriate variables. You can't just clump it all together
in lots of different tables.
Unless you're writing a noddy system, but once you get complex (unique keys,
mapping Person --* Area), it starts to fall apart.
> I can appreciate this sentiment, but I'm also wary of it. There are
> other Python ORMs that do better at distinguishing between business
> logic and persistence logic, but SQLObject is coming from a bit
> different perspective -- it's mapping tables to Python objects, not
> mapping Python classes to tables. Ultimately I am unconvinced that you
> can get the persistence for free, that you can map arbitrary Python
> onto a DBMS -- at least without making the DBMS pointless. Now, that's
> not to say SQLObject won't move more towards being a "seamless"
> persistency for objects; I have several ideas that could help improve
> this. But I don't even know what "seamless" really means in this
> context -- no seamless persistence *can* exist in Python, because the
> status-quo is non-persistence (which will continue to be a viable
> option for a large number of objects and situations).
>
> But I'm wandering off onto tangents.
No, they are valid points. Seamless is where you want to be. But if you carry
on along the path of "we won't do superset" then your building on foundations
that won't hold very much. Better to think about it now, than have to start
again later.
I've been through all of this with Objectmatter .. :-)
I don't think superset mappings will be easily to implement at this stage, but
it will be even harder 12 months down the line. :) Luckily, I won't be using
Python for anything complex until I do see an object mapping tool going in
this direction. I guess I could have picked something else, but SQLObject can
just about cope with my 'not very complex' case. Yet it's already quite ugly:
# All of our database object definitions
class Area (SQLObject):
_connection = getConnection()
areaId = StringCol()
title = StringCol()
description = StringCol()
# Removing makes for not so nice OO
# contacts = RelatedJoin('Contact', joinColumn='area',
# otherColumn='contact', intermediateTable='AreaContactJoin')
# branches = RelatedJoin('Branch', joinColumn='area',
# otherColumn='branch', intermediateTable='AreaBranchJoin')
# events = RelatedJoin('Event', joinColumn='area',
# otherColumn='event', intermediateTable='EventAreaJoin')
class Ward (Area):
_connection = getConnection()
# Should be in parent class if nice OO
contacts = RelatedJoin('Contact', joinColumn='ward',
otherColumn='contact', intermediateTable='WardContactJoin')
branches = RelatedJoin('Branch', joinColumn='ward',
otherColumn='branch', intermediateTable='WardBranchJoin')
events = RelatedJoin('Event', joinColumn='ward',
otherColumn='event', intermediateTable='WardEventJoin')
class Constituency (Area):
_connection = getConnection()
description = StringCol()
sittingMP = ForeignKey("Contact")
# Should be in parent class if nice OO
contacts = RelatedJoin('Contact', joinColumn='const',
otherColumn='contact', intermediateTable='ConstContactJoin')
branches = RelatedJoin('Branch', joinColumn='const',
otherColumn='branch', intermediateTable='ConstBranchJoin')
events = RelatedJoin('Event', joinColumn='const',
otherColumn='event', intermediateTable='ConstEventJoin
Spot the repeated code. And when you're forced to do that, what you're doing
is wrong. :)
John
--
John Baker,
(m) 07736393822
http://rant.pointful.info
|