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 |