Re: [Grok-dev] Grok-dev Digest, Vol 86, Issue 1

9 views
Skip to first unread message

Paul Sephton

unread,
Aug 19, 2014, 6:46:53 AM8/19/14
to Grok Development
Hi, Christopher,

I cannot claim to be certain of what you are getting at, but to the best of my understanding you are proposing two things:
a) A change to the traverser method for the IContainer and IContext interfaces
b) Some default javascript/jquery added which automates AJAX queries for URL's containing '#'.

Did I get this part right?

You mentioned that you are unsure as to why IContainer and IContext have ContainerTraverser and ContextTraverser as two separate classes.  Well, how I understand it, is that the component architecture is the big differentiator here.  A grok.Component, and classes inheriting from it implement an IContainer, and because of the ContainerTraverser implementing an ITraverser for an IContainer, we "magically" get the ContainerTraverser implementation for grok.Container instances.

I do not believe you would need to change the grok source to override the traverser behaviour.  You can simply derive a new interface from IContainer or IContext and implement an adapter for it.  (If I am wrong here, can someone correct me?)

Of course, you can also just implement a class inheriting grok.Traverser with a grok.context(your model or container), but you probably already know about this and it's not what you are after, right?

My personal feeling about frameworks with "built-in" javascript is that it gets ugly pretty quickly.  I like the fact that if I need to use Javascript or AJAX the framework itself does not implement any of that.  For example, since JQueryMobile already uses '#' in URL's to handle AJAX pages, your use of '#' as well would clash.  It's actually a rather horrible approach to identifying AJAX views IMO.

It's not actually all that hard to implement AJAX specific areas of your site, and I don't like being prescribed by a framework as to the method I must use to figure out which parts of the site are AJAX loadable.  Personally, I add an 'AjaxLoad' class to divs which must be populated, and add a 'ref' attribute containing a view reference.  My JQuery runs through the page looking for div.classname and sets up event handlers for the AJAX areas.

Have fun,
Paul


On Wed, Aug 13, 2014 at 12:00 PM, <grok-dev...@zope.org> wrote:
Send Grok-dev mailing list submissions to
        grok...@zope.org

To subscribe or unsubscribe via the World Wide Web, visit
        https://mail.zope.org/mailman/listinfo/grok-dev
or, via email, send a message with subject or body 'help' to
        grok-dev...@zope.org

You can reach the person managing the list at
        grok-de...@zope.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Grok-dev digest..."

Today's Topics:

   1. Grok.traverser Code Documentation Feedback and proposal.
      (Christopher Lozinski)


---------- Forwarded message ----------
From: Christopher Lozinski <lozi...@freerecruiting.com>
To: grok...@zope.org
Cc: 
Date: Tue, 12 Aug 2014 20:15:38 +0300
Subject: [Grok-dev] Grok.traverser Code Documentation Feedback and proposal.

I put up three web pages about grokcore.traverser.


Here is my page documenting the source code.

http://zopache.com/Grokcore.traverserCodeDocumentation


Here are my comments about the source code from a Human Factors point of view.

http://zopache.com/HumanFactors


And here is my proposal as to what should be done to improve the code.

http://zopache.com/GrokCoreTraverserProposal



Why am I writing this? Well I am just implementing parental acquisition for Zopache, and so I need

to modify the default traversal software.


I find that documenting software helps me to understand it better. Describing it, crystallizes my


concepts. And other people care, and so they read carefully, and correct any mistakes.

And finally these mailing lists are so quiet, I am sure that many people are happy that something


new, albeit controversial, is happening.


So I invite you to go ahead and read the documentation I wrote, and the comments.


But before you begin, let me say I am just amazed at the brilliance of the People who wrote Grok. I


could never have even imagined this framework, let alone written such high quality bug-free code.


Thank you enormously for those who did it.



And of course if anyone wants to talk to me about what I am doing for Parental Acquisition during


traversal, I am happy to chat privately off of this mailing list.






_______________________________________________
Grok-dev mailing list
Grok...@zope.org
https://mail.zope.org/mailman/listinfo/grok-dev


Paul Sephton

unread,
Aug 19, 2014, 6:52:41 AM8/19/14
to Grok Development
Sorry, I just read what I wrote and it makes no sense to me- never mind anyone else:


"A grok.Component, and classes inheriting from it implement an IContainer, and because of the ContainerTraverser implementing an ITraverser for an IContainer, we "magically" get the ContainerTraverser implementation for grok.Container instances."

That should be:

- A grok.Container, and derived classes, implement IContainer
- ContainerTraverser is an adapter which provides an ITraverser interface for IContainer instances
- So when we need to traverse a container, we find the traverser by asking the component architecture for an ITraverser(context) where the context is a container instance.

To override the behaviour, we can create our own adapter:

class MyTraverser(grok.Adapter):
  grok.context(IContainer)
  grok.implements(ITraverser)
  ....

which effectively replaces the original traverser for containers.  Although I query your need for doing so.

Disclaimer
Please note: I am not an expert here and it is entirely possible that I have the wrong end of the stick.



Christopher Lozinski

unread,
Aug 20, 2014, 4:42:51 AM8/20/14
to Paul Sephton, Grok Development
1. Introduction
2. Grok Traversal Documentation
3. GrokCore Traverser Issues
4. My Application
5. Zopache Traversal
6. Anchors
7. Obviel Traversal
8. JQueryMobile Traversal
9. Conclusion: GrokCore.Traverser Proposal


1.INTRODUCTION

Thank you for your email, and for challenging my ideas. It really forces
me to think more clearly about what I am dong. It is a lonely business
being a grok developer nowadays. Particularly TTW.
Lots to talk about. You can skip tot he part that interests you using
the headings above.

2. GROK TRAVERSAL DOCUMENTATION

So it turns out that grokcore.traverser is just a tiny part of the
traversal code in grok. There is way way more in zope.publisher, grokcore.view.publisher and even zope.app.publisher. It is documented here:
http://zopache.com/TraverserGrokcoreCodeDocumentation
http://zopache.com/TraverserZopePublisherSourceCodeDocumenation
http://zopache.com/TraverserZopeAppPublicationDocumentation

3. GROKCORE TRAVERSER ISSUES

On 8/19/14, 1:52 PM, Paul Sephton wrote:
> it makes no sense to me-

It is not you. This stuff is just way too complicated. We can make it
simpler.

In grokcore.traverer there are three classes. The base class and two subclasses, one for traversing iContext, and the other for traversing IContainer. I needed to change a method in the base class, and then adapt the two subclasses. That means creating a base class adaptor, and two subclass adaptors. Too complicated, I just turned grokcore.traverser into a develop egg, made the base class change and was done.

Actually I think the original authors did the right thing. The focused on performance. But if the market claim of grok is
that it is the best way to reuse components, then we need to make that component reuse easy. I propose that grokcore.traverser be a single class that tests if something is an IContext or IContainer. That makes is much easier to understand, and in my case much easier to adapt. Those who need better performance can then register more specific subclasses. While this is technically a small change. It is conceptually a hugely different approach. Simplify it for new users. Adapt it for more complex requirements.

I will come back to this proposal in section 9.Conclusion.


4. MY APPLICATION

For those doing a simple application using parental acquisition, a typical structure might be as follows.

/index
/Content
/ContactInfo/Content
/SubmitResume/Content
/PostJob/Content
/Resumes/Content
/Jobs/Content
/Home

so when one goes to the home page privacv.com we find the /index template, look up /content and display it.

When we go to privav.com/ContactInfo we look up the index page in the root folder, it asks for the Content in the Contactnfo folder and displays it. Simple. This is the basic use pattern for parental acquisition. ContactInfo is the context for that view. Index is the template for that view.

5.ZOPACHE TRAVERSAL

From this you can see why I need a custom traverser. I look up the index template using parental acquisition. The template has a view. The view that grok calls now has a context, a request and a template.

6. ANCHORS

First for those like me who did not know how the jquerymobile library handles anchors I quote:

"One HTML document can contain more than one "page" element, and thus
more than one screenful of content. This way it is only necessary to
load one file which includes multiple pages of content. One page can
link to another page within the same file by referencing the page's id
attribute (e.g. href="#second")."

So that sounds like a great idea. Kind of like the obviel idea, you get your anchorr text from somewhere. Obviel from the server, JqueryMobile caches it in the html file.

So both Obviel and JQuryMobile use anchors to display a particular "page". Without arguing over whether that is a good idea or not, let us look at how to support it in Grok.

Stating the obvious. The goal is that the same thing should be displayed for a given url, whether the user clicks on it, or sends it to someone else.

7. OBVIEL TRAVERSAL

Let us start with the simpler obviel case, and move to the more complex and interesting JQueryMobile case.

There are two ways to think of the anchor
Either display the whole page, or just load the content.

When someone navigates to
privaCV.com/#ContactInfo
They are really trying to display /ContactInfo/Content
using the root (whole page) index method.

But if they try to just click on the link, they want to load the content using the url

privacv.com/#ContactInfo

In this case, Grok needs to travese to
ContentInfo/Content

So Obviel requires two different traversals based on the referer URL.
Fortunately this is all doable. There is a method called defaultBrowser, really it should be defaultView that allows us to add some steps to the end of the traversal path.


8. JQUERY MOBILE TRAVERSAL
Actually I now prefer the jquerymobile approach. Given a URL,
put the first content page first in the downloaded file, and while the user is reading it, download the other "pages" in the background.
That leads to much better user response time.
That requires the obviel traverser, plus an extra step of downloading the extra data.


9.CONCLUSION: GROKCORE.TRAVERSER PROPOSAL

I think that it important to take small steps and keep the big picture in mind. The big picture is that Grok is brilliant software, I think that it is the future of software engineering, but it is sadly too complex. With your permission, I can take a small step to simplify it.

May I upgrade grokcore/traverser/components.py to only be a single class? One that checks if the context is an IContainer, or an IContext. That will be much easier for new developers to grok. It will be much easier for more experienced developers like me to adapt. I can move the two subclasses ContextTraverser and ContainerTraverser into separate files that those who care about performance can register, and that the rest of us can ignore.

And while I am at it I can move some of my source code documentation onto github.

What do you think?

Christopher Lozinski

unread,
Aug 20, 2014, 10:18:27 AM8/20/14
to Paul Sephton, Grok Development
I took the liberty of attaching your reply to the end of this email.

>I think what you are completely missing is the power of marker interfaces;

Oh I think marker interfaces are brilliant, just what is needed for larger projects, particularly for mult-developer projects.  But they add way too much complexity for the simple projects.  Much like page templates are brilliant if you are working with graphics designers, but again too much complexity for the stand alone developer.

So you are right that my overly long response was a bit confusing.  Thanks for the feedback, that is why I write.  So here is what I did not say.  The Zopache computatinoal model is different from the Grok computational model.  No marker interfaces.  Very little python.  Mostly a ZMI where you add
objects and fill in some fields.  And some python based templating languages, right now mint. 
Later Jinja2 and Page Templates.  I may do the tree of objects representing a person, on the file system in python.  Or maybe in ZClasses.I will see.

I have already put up about 10 model classes in grok.  As well as custom traverser and parental acquisition.  So I do understand it.  Did you see how much code you had to write for all those Content objects. And then adding them all to the application?   In Zopache, just use a GUI the ZMI, add a folder, add an HTML object, and type up the content.  Or use some other kind of template for the content, like a mark up object.  (Which I do not yet have, but guess will need to add soon).  Way way easier for simple projects.  And so many projects start off small and then grow. 

It is not just beginners.  Even for the seasoned developer we have way too much complexity overload.
Whatever can be done to simplify our computational models of the world, helps the seasoned developer as much as the novice developer.  Maybe more.  

Thanks for the dialogue.  It hugely helps me understand what I am doing.  It is strange, here I am working by myself, but with so much information up on the web for everyone to see.

Chris

.







On 8/20/14, 3:32 PM, Paul Sephton wrote:
Hi, Christopher,

Thanks for the lengthy reply.  Although I cannot yet say that I fully understand what you are trying to say, I think I understand enough for a response.

When I said "...it makes no sense to me..." this was in response to something I had written which in retrospect looked senseless.  It tends to happen to me more often with age.

In regard to your case for "Parental Acquisition", I think it's really a lot simpler to implement than you imagine.

You definitely don't want to modify the framework to get what you want.  I would typically implement each discrete model in it's own Python source file.

I think what you are completely missing is the power of marker interfaces; naturally since large site layouts are not really addressed properly in the tutorials.

Let's see:


/index
/Content
/ContactInfo/Content
/SubmitResume/Content
/PostJob/Content
/Resumes/Content
/Jobs/Content
/Home


import grok
from zope.component import Interface

class IContent(Interface):
    """ Marker Interface for Content """

class ContentIndex(grok.View):
    """ Things that implement IContent will get this view """
    grok.context(IContent)
    grok.name('index')
   
    def render(self):
        """ Renders content from the current context, which we are assured
            implements the model for an IContent.
        """
   
class ISite(Interface):
    """ Marker Interface for main site index """

class Index(grok.View):
    """ This view is available for all models which implement ISite """
    grok.context(ISite)
    def render(self):
        """ Renders the site index with all the pretty common bits.  Also
            includes a <div content="context/Content/@@index" /> to render
            the content for the appropriate section.
           
            We could also build our site here using viewlets which is a great
            way to go.
        """

class ContentModel(grok.Model):
    """ Implements a content model """
    grok.implements(IContent)

class ContactInfo(grok.Model):
    grok.implements(ISite)
    Content = ContentModel()
    grok.traversable('Content')
   
class SubmitResume(grok.Model):
    grok.implements(ISite)
    Content = ContentModel()
    grok.traversable('Content')

class PostJob(grok.Model):
    grok.implements(ISite)
    Content = ContentModel()
    grok.traversable('Content')

class Resumes(grok.Model):
    grok.implements(ISite)
    Content = ContentModel()
    grok.traversable('Content')

class Jobs(grok.Model):
    grok.implements(ISite)
    Content = ContentModel()
    grok.traversable('Content')


class Home(grok.Model):
    grok.implements(ISite)

class MainApp(grok.Container):
    grok.implements(ISite)
   
    def __init__(self):
        super(MainApp, self).__init__()
        self["Content"] = ContentModel()
        self["ContactInfo"] = ContactInfo()
        self["SubmitResume"] = SubmitResume()
        self["PostJob"] = PostJob()
        self["Resumes"] = Resumes()
        self["Jobs"] = Jobs()
        self["Home"] = Home()



Hope that helps,
Paul

Paul Sephton

unread,
Aug 21, 2014, 4:08:52 AM8/21/14
to Grok Development
Dear Christopher,

From the comments on your site it would seem what you are trying to accomplish is something similar to Zope-2 but based upon Grok and Zope toolkit?  That would explain your need for enabling an acquisition mechanism.  I assume you are aware of the historic debate about acquisition, and the conclusion that the idea left much to be desired?  Personally I never had much of a problem with it, but then again I never did anything beyond the trivial with Zope-2.

I actually used Zope-2 for some really trivial stuff many moons ago. 

Comments interspersed:

On Wed, Aug 20, 2014 at 4:18 PM, Christopher Lozinski <lozi...@freerecruiting.com> wrote:
I took the liberty of attaching your reply to the end of this email.

>I think what you are completely missing is the power of marker interfaces;

Oh I think marker interfaces are brilliant, just what is needed for larger projects, particularly for mult-developer projects.  But they add way too much complexity for the simple projects.  Much like page templates are brilliant if you are working with graphics designers, but again too much complexity for the stand alone developer.

...and here I was thinking that page templates and marker interfaces were the simplest possible constructs!

In software design, flexibility and power quite often has a cost in complexity.  The component oriented approach to design is actually a way of reducing complexity while at the same time providing a flexible framework.

In the ZCA, the idea is to provide all the pluggability that one might achieve through abstract base classes and inheritence, but without actually having to use inheritence.
 

<snip>...  The Zopache computatinoal model is different from the Grok computational model.  No marker interfaces.  Very little python.  Mostly a ZMI where you add objects and fill in some fields.<snip>...

Pyramid also has this idea that the ZCA is best hidden from the developer who clearly has insufficient grey matter to grasp the idea of a component architecture and put it to good use.  They wrap the ZCA behind yet another API layer to try to present a simpler and more palatable view while trying to retain the power of the ZCA. 

From my perspective, wrapping an API in another API achieves little other than there now being two API's to learn rather than just the original one.

Perhaps Pyramid is the right approach; I cannot really say.  It certainly is winning the popularity contest.  OTOH, PostgreSQL has been miles ahead of MySQL ITO database design for over a decade and is only now starting to see an increase in popularity.  Not because it is better, but because of politics.

For TTW development, Zope-2 remains an option, but has a strong competitor in Web2Py.  Are you sure there's a need for  another TTW Python framework?

<snip>...  Did you see how much code you had to write for all those Content objects. And then adding them all to the application?  

Including all the comments, 70 lines of completely unoptimised code, produced entirely for demonstration purposes, much of which was cut & paste.  Really no big effort.

You stated that you needed to use acquisition to accomplish the rendering of the index in the root of your site map, and I knocked together my example in about 10 minutes to demonstrate that you did not need acquisition to do so.
 
In Zopache, just use a GUI the ZMI, add a folder, add an HTML object, and type up the content.  Or use some other kind of template for the content, like a mark up object.

This is one way to do things, but not the only way. When apps developed TTW like this start getting more beefy, the visual design approach starts breaking down.  I spent whole months looking at the implementation of Plone-3 on Zope-2, and the complexity left me feeling battered and inadequate.

 
  <snip>...  And so many projects start off small and then grow. 

True enough.  OTOH, my experience is to discard the POC once it has proven viability, and immediately re-architect for scalability and extensibility.  In other words, projects which start small and grow are seldom future-proof.
 

It is not just beginners.  Even for the seasoned developer we have way too much complexity overload.
Whatever can be done to simplify our computational models of the world, helps the seasoned developer as much as the novice developer.  Maybe more.

I agree with your sentiment.  I suspect however that what you see as a simplification, and what I see as simplification may not be wholly in agreement.  I see the use of marker interfaces to be an unbelievably simple way to specify what should be rendered for a model.  Your opinion is apparently that this approach involves too much typing.

Handling complexity is the bane of large projects.  Component architectures are one approach to managing complexity.  If these happen to be visual components (as with Zope 2, or what you envisage) or non-visual components (as in Grok), the result may be, in my opinion, quite similar.

My own preference is to handle the organisation of complex large projects through modularisation, and handling interfaces between components by using the ZCA.  I am obviously willing to entertain the idea that in principle my preferences are not universally shared.
 

Thanks for the dialogue. 
Always good,

Paul

Reply all
Reply to author
Forward
0 new messages