[Zope-dev] Michel's Reply
Chris Withers
chrisw@nipltd.com
Fri, 20 Oct 2000 12:54:19 +0100
>From: Michel Pelletier <michel@digicool.com>
>
>Jim Fulton wrote:
>>
>> Michel,
>>
>> You have advocated that methods should always be bound to the objects they
>> are accessed in. You argue that there should be no choice in the matter.
>
>I advocate more points than that, like being able to document python
>with python, no XML mixed in with a language, Py Meths working like
>other methods do, but yes that is one of them.
>
>My argument should be more flexible in regard to choice, a willing
>compromize is to switch the default binding of context and container,
>making 'self' the default for context and something else the default for
>container.
>
>> I have to disagree strongly. I'll try to explain why.
>>
>> In Python, methods are bound to instances. Methods are part
>> of an instance's core behavior. They are specific to the kind
>> of thing the instance is. In my words, methods are part of
>> the genetic makeup of an object.
>
>Python methods are meant for through the web usability and programming
>ala the existing Zope model. 90% of your audience just scratched their
>heads.
>
>> In Zope, we allow some methods to be bound to their context.
>> This is done in a number of ways and is sometimes very useful.
>> We have methods, like standard_html_header, which are designed
>> to be used in different contexts.
>
>this is how I feel python methods should be designed to be used.
>
>> We have other methods, like manage_edit that are designed to
>> work on specific instances. It would be an egregious error
>> if this method was acquired and applied to it's context.
>
>I think this is a weak argument, none of the built in Zope methods mean
>anything to the average user, they can't find them, click on them, edit
>them, or copy them to their own method to change and experiment with.
>
>> We have some methods that are designed to bound to an instance
>> (container, in your terminology)
>
>Python Method terminology
>
>> but that, because they are written in
>> DTML, can be bound to other objects. This can cause significant problems.
>> For example, methods defined in ZClasses almost always want to be
>> bound to ZClass instances, not to other arbitrary objects.
>>
>> <aside>There's a bonus problem with DTML Methods. When
>> a DTML Method is invoked from another DTML Method, it
>> is bound to neither the object it was accessed in or
>> to the object it came from. It is bound to the calling
>> namespace. It turns out that this is a useful behavior
>> if the DTML Method is designed to be used as a "subtemplate".
> > </aside>
>
>This is because DTML binding is implicit, not because it's backward.
>This problem doesn't effect python methods because you allways bind a
>method in python when you call it. The question is how the initial
>method gets bound.
>
>> There is no one "right" way to bind a method. There are good
>> reasons to sometimes bind a method to it's context and
>> sometimes bind a method to it's container (ie instance).
>> There are even sometimes reasons to bind a method to a
>> calling namespace.
>>
>> The principle of least surprise doesn't help here, because
>> methods defined in Python classes don't behave the way
>> methods defined through the web do currently.
>>
>> We *need* control over binding, as well as reasonable defaults.
>>
>> If we can agree that we need binding control, the question
>> arises as to some details and default names.
>
>I agree there must be control over binding, although your arguments
>above have not convinced me that Python Methods are doing it the right
>way, actually, it's convinced more than my argument, compromisingly of
>course, is more right.
>
>> Should it be possible to do more than one binding at a time,
> > using multiple names? If not, then I'd agree that the name
>> 'self' should be used for either the context or container binding.
>
>I'm with you so far with that.
>
>> If both bindings are allowed at the same time, then 'self' should
>> refer to container binding to be consistent with standard Python
>> usage and some name like 'context' should be used (by default)
>> for contextual binding.
>
>That's what I disagree with. I don't think you've given a strong
>corollary to standard python usage. The only strong argument you've
>given so far is the ZClass one, but 10 gives you 1 that's not the
>primary use case (it may be the one in Fburg). People are going to be
>defining these methods in Zope to make their lives easier, probably bad
>design and mad hacks and no structure, but that's how 90% of the world
>gets their work done and easing that burden is the usability task. You
>have not convinced me that:
>
>1. Something called a Python Method should not resemble a method
>definition in python.
>
>2. Something called a Method in Zope should not behave like the other
>Methods (meaning through the web objects) in Zope
>
>3. Common, *documented* well understood URL manipulations (context) are
>less important than (the less common) containment oriented design and
>ZClasses.
>
>Consider the following passage in the documentation:
>
> For example suppose you want to call a method named *viewFolder*
>on
> one of your folders. Perhaps you have many different *viewFolder*
> methods in different locations. Zope figures out which one you
>want
> by first looking in the folder that you are calling the method on.
>If
> it can't find the method there it goes up one level and looks in
>the
> folder's containing folder. If the method can't be found there it
> goes up another level. This process continues until Zope finds the
> method or gets to the root folder. If Zope can't find the method
>in
> the root it gives up and raises and exception.
>
>and:
>
> Zope breaks the parts of the path up and walks along the object
> hierarchy looking for each part. This process is called *URL
> traversal*. For example, when you give Zope the URL
> *Zoo/LargeAnimals/hippo/feed'*. It starts at the root folder and
> looks for an object named *Zoo*. It then moves to the *Zoo*
> folder and looks for an object named *LargeAnimals*. It moves to
> the *LargeObjects* folder and looks for an object named
> *hippo*. It moves to the *hippo* object and looks for an object
> named *feed*. The *feed* method is found in the *Zoo* folder by
> a process called *acquisition*. Now Zope has reached the end of
> the URL. It calls the last object found, *feed*, on the second
> to last object found, the *hippo* object. This is how the *feed*
> method is bound to the *hippo* object.
>
>And further on:
>
> Suppose 'feedHippo.py' is a Python Method. How could you call the
> 'Diet/feed' method on the 'LargAnimals/Hippo' object from your
> Python Method. Here's how::
>
> self.Zoo.Diet.LargeAnimals.hippo.feed()
>
> In other words you simply access the object using the same
> acquisition path as you would use if calling it from the
> web. Likewise in Perl you could say::
>
> $self.Zoo.Diet.LargAnimals.hippo->feed();
>
> Using methods from other methods is very similar to calling
> methods from the web. The semantics differ slightly but the same
> acquisition rules apply.
>
>These paragraphs are just exceperts from two whole sections that try to,
>quite sucessfully acording to the feedback we've gotten, explain the
>method binding pattern in Zope. We give a real world application and
>justification in both sections on why this is useful and explain the
>concept in simple terms. Now, this needs to be re-explained, rewritten,
>and made overly complicated for what I feels are not very important
>reasons. Where are the applications and design patterns documented for
>your argument? Perhaps those could convince me if they justified it
>from the perspective of the beginner. I suggest you read over Chapter 7
>and weigh these descision from the eyes of a newbie.
>
>-Michel