[Grok-dev] Re: sprint mini-report 2
Martijn Faassen
faassen at startifact.com
Fri May 2 04:55:45 EDT 2008
Hey Brandon,
I'm going to vigorously argue against you here. That's not to say the
arguments don't have any merit by themselves - you make good points
about ORM mapping which I will take to heart. I just don't see them as
relevant as points against the 'grok.traverse' directive.
Brandon Craig Rhodes wrote:
> Martijn Faassen <faassen at startifact.com> writes:
>
>> * A spin-off discussion from the megrok.rdb discussion resulted in
>> our inventing a grok.traversable directive and we now have a team
>> that works on its implementation.
>
> Their time might be better spent on turning megrok.trails into
> something worthy of a first release.
I disagree. megrok.trails is a major philosophical change, while this
codifies a pattern we've seen in current Grok applications.
That's not to say megrok.trails isn't a worthwhile effort, but the
ability to tell a class which attributes are traversable fits Grok's
current traversal paradigm without requiring a major shift.
> In general, RDB applications
> should seek to have simple, orthogonal URLs like:
>
> /app/person/brandon_rhodes
> /app/person/martijn_faasen
>
> /app/account/br38
> /app/account/expiretest
> /app/account/faasen
>
> Because, in general, one courts disaster by trying to think of
> relational objects as being "beneath" each other, as a traversable()
> directive would (if I understand the concept correctly) encourage:
>
> /app/person/brandon_rhodes/accounts/br38
> /app/person/brandon_rhodes/accounts/expiretest
> /app/person/martijn_faasen/accounts/faasen
>
> Among many other problems (for example, uniqueness; in general,
> allowing traversal of attributes in an ORM will give you many URLs for
> a single object), URLs that traverse from one object to another
> destroy the properties of identity and uniqueness that RDBs are famous
> for. For example, moving the "expiretest" account to someone else in
> the above example will result in its URL changing (!), which is a deep
> violation of the idea that a URL should be a permanent name for
> something.
That's an interesting argument. I'd argue that if you set up your
traversal namespace in the second way you sketch out, the things in the
individual accounts/sections should have been modeled as *being* unique
per 'person' section, or, alternatively, your application should be able
to deal with this information being in multiple places (possibly
zc.shortcut would be interesting here).
The point that moving these to another person would break the URL is a
good argument, but there is no reason to assume that all models of this
kind will allow moving in the first place. While I agree that modeling
things this way with an ORM may frequently be less desirable, I'd also
argue that there are cases where such structures *are* useful.
Anyway, it doesn't matter: grok.traverse is useful to build your first
structure as well:
class PersonContainer(grok.Container):
pass
class Person(grok.Model):
pass
class AccountContainer(grok.Container):
pass
class Account(grok.Container):
pass
class App(grok.Model):
grok.traverse('person')
grok.traverse('account')
def __init__(self):
self.person = PersonContainer()
self.account = AccountContainer()
Any arguments against the grok.traverse() directive connected to the
properties of ORMs won't work anyway, as we see grok.traverse as
independent of whether an ORM is used at all. It just came up in the ORM
discussion. We noticed a pattern common in Grok applications: use of the
'traverse()' method to do this, or misuse of containers to contain
heterogeneous objects. This we want to get rid of.
> I will gently suggest that ideas like "traversable()" are the result
> of long experince with the ZODB ruining people's minds. :-) How? By
> convincing them that a URL should not be a unique name for something,
> but rather should simply be an impermanent description of how to find
> something at this moment. When people use the ZODB too much, they get
> used to the idea that moving an object from one folder to another
> should change its name - they get used, in other words, to separating
> the URL from an object's identity.
Again, arguing for a major philosophical shift of how applications are
built is all very well, but that doesn't take away that this is how
applications are frequently built with Zope. There are drawbacks to
traversal, but there are also benefits (I'll go into some of what I see
as benefits at the bottom).
> In every Grok application that I have written so far atop RDBs, it
> simply turns out to be a small disaster (and, yes, I've tried it!) to
> put objects "under" other objects.
I didn't have to deal with such a disaster yet in my little application,
but you have more experience. :)
> That's why I wrote megrok.trails;
> I realized that things only becomes simple when the URLs for one kind
> of object are orthogonal from the URLs for all others:
>
> class MyTrails(trails.TrailHead):
> grok.context(MyApp)
> trails = [
> Trail('/person/:shortname', Person),
> Trail('/account/:username', Account),
> ]
What happens if you go to /person or /account directly? Are there models
and views for that?
I'd argue that if you have a URL called /a/b you typically want /a to at
least not return a 404 error. My feeling is that modeling this with
traversal as I did above encourages the filling out of the URL space,
with a PersonContainer and AccountContainer.
There are other benefits to using traversal:
The structure of a traversal-based URL space is not centrally defined,
but near the objects itself. This allows an easier composition of larger
applications from disparate parts which don't know about each other (a
major strength of Zope in general). If you *do* model things using
nested names, there are other potential benefits: locally defined
permissions and roles are inherited.
To conclude:
* grok.traverse is actually neutral in this whole discussion: you can
use it to model things either way.
* grok.traverse is not connected to ORMs, but useful for generally
mapping out URL namespaces.
* a traversal based approach has benefits, not only drawbacks. Since
they also have a history in our community, I'd rather explore these
benefits further and see whether we can turn this into a unique
strength, not a weakness.
Regards,
Martijn
More information about the Grok-dev
mailing list