Re: [SQLObject] Using SQLObjects as Abstract Classes
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Ian B. <ia...@co...> - 2003-07-25 18:18:41
|
On Fri, 2003-07-25 at 12:27, Brad Bollenbach wrote: > > If you have that class layout, you are supposing that there will be > > other subclasses of Monitor. However, each of these subclasses must be > > a separate table, or great confusion will ensue. > > There will only be a single monitor table. Monitors store a common set > of properties. The only thing that's different is how they behave when > you say "do your monitor check". Then make that into a multiple-class object, Checker. Like: class Checker(object): def __init__(self, monitor): self.monitor = monitor def check(self): assert 0, "Subclass responsibility" class HTTPChecker(Checker): def check(self): ... class MD5HTTPChecker(HTTPChecker): def check(self): ... checkers = {'http': HTTPChecker, 'md5': MD5HTTPChecker} class Monitor(SQLObject): monitorType = StringCol(length=10) def _get_checker(self): return checkers[self.monitorType](self) Voila! Composition beats inheritance! > > Python inheritance simply doesn't map to RDBMS tables. There are things > > that can be called inheritance among RDBMS tables, but they aren't the > > same thing. So SQLObject just takes a one-class-one-table approach. > > You can still use inheritance, and a class can be abstract so long as > > you don't use it, but it's still one-class-one-table. It's improper to > > use _table = 'monitor' in each class, because that breaks that rule. If > > you have one table you shouldn't have more than one class that you use > > with that table. > > Hrmph. > > I can see where you're coming from, but perhaps some thought could be > spent on figuring out how to make that "one class" (per table) be an > abstract class (so, I kind of really only do have class per table, > because StatusMonitor, KeywordMonitor, etc are just there to specify > differences in behaviour, not in attributes. That "one class" is my > abstract base.) It just wouldn't work. What are you going to do, fetch a generic Monitor instance, check its type, then refetch a specific instance? Or do a direct query to find the type, then instantiate the object with the correct class? It just doesn't make sense. It also is going to cause all sorts of weird structural problems when you do need more tables. With the above technique you can add tables fairly easily. Say you want to create a md5_checker table (to store the MD5 hash). class MD5Checker(HTTPChecker, SQLObject): def setMonitor(self, monitor): HTTPChecker.__init__(self, monitor) md5 = StringCol(length=128) function md5CheckerGetter(self, monitor): inst = MD5Checker.selectBy(monitor=monitor)[0] inst.setMonitor(monitor) return inst checkers['md5'] = md5CheckerGetter You don't have to create tables for every checker, just the one that needs it. You don't have to fiddle with inheritance of the Monitor class. Someon, who I can't remember, and who's link I've lost, gave a link to a good article on inheritance and how to map them. The stuff I've written above follows one of them (one table for each class, including abstract classes), while standard inheritance in SQLObject is one table per concrete class. Implementing the former directly in SQLObject is, IMHO, a lot of work for nothing, since multiple classes is superior in Python just like multiple tables are superior in the database (IMNSHO). It may not seem easier to implement (though I don't think it's any harder), but I think it will be much easier to maintain, and result in more readable code. Ian |