[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