[Web-SIG] Announcing bobo

Jim Fulton jim at zope.com
Thu Jun 18 12:21:26 CEST 2009


(Note that this discussion is getting rather dense. I suggest reading  
my reply all the way through befor responding to individual points. :)

On Jun 17, 2009, at 6:42 PM, Sergey Schetinin wrote:

> On 2009-06-17, Jim Fulton <jim at zope.com> wrote:
>> On Jun 16, 2009, at 11:02 AM, Sergey Schetinin wrote:
>> ...
>>> indeed there are quite a few
>>> frameworks / components that do this thing and I kind of don't get  
>>> why
>>> people want to write their apps that way. I wonder if Jim or anyone
>>> else could explain the rationale behind all these URL routing
>>> libraries. Nobody minds calling functions from other functions --
>>> that's basics of programming, but for some reason URL dispatching is
>>> seen as something different. Why?
>>>
>>> This is not a criticism, I just really would like to understand  
>>> this.
>>>
>>
>>
>> Fair enough.  I'm not sure I understand your question.  You need  
>> some way
>> of mapping URLs onto Python objects that handle them.  You can do  
>> this on a
>> case by case basis by inspecting a URL and doing some sort of ad hoc
>> dispatch in your application. Is that what you mean by "calling  
>> functions
>> from other functions"?  I've found it useful to have a standard  
>> mechanism
>> for this that you can use over and over without reinventing it each  
>> time.
>
> I guess didn't state my question properly, sorry. Let me explain what
> I meant by "calling functions" analogy. My point is that when we
> define a piece of functionality (as a function, class or whatever) we
> don't say where to use it. I mean, we may define functions as "take
> data from a this argument, process and return" and it's up to the
> caller to pass that data into the function, function doesn't say where
> that should come from or where in the rest of code should its body be
> injected or anything like that. So function is a definition of
> functionality and it is being called from somewhere else, the called
> should know as little as possible about the caller and its place
> relative to other calls its caller makes. At least that seems to be
> the advice for good software design.

But software still lives in a namespace.  You usually assign a  
function a name in a module or package. It often depends on other  
functionality being available under specific names.  In web  
applications, we often need to know where other components are in the  
URL space.   OTOH, often a function doesn't depend on it's name and  
you feel that a web application shouldn't care about it's URL. I get  
that. :)

> When considering webapps and what urls they should handle it seems
> like the same should apply -- webapps define contained blocks of
> functionality and the task of placing them somewhere in URL-space
> belongs to the "caller" which in this case would be a configuration or
> serving script or, most often, a parent application.

OK, so you expect there to be a URL mapping, typically accomplished  
via some configuration mechanism outside the code. Most routing  
systems either require or allow this.

> Sure, this
> requires inspecting the URL, or as you said, "ad-hoc dispatching". I
> think that misrepresents this approach because all it boils down to is
> a series of if's, maybe a dictionary lookup and possibly regexp
> matching is some cases (I personally never had to use that for URL
> dispatch though). If we were to look at a similar approach in a
> different context, I don't think it would be fair to call a series of
> if/elifs "ad-hoc logic", so it's the same thing here.

I wasn't trying to represent what you said. I was just guessing at  
what you said.  So you don't mind routing systems that are configured  
through routing tables outside the code. (?)

> But let's go back to bobo, I can see how URL paths derived from file
> and function names are nice and make sense, but I'm not as thrilled
> with declaring the app path in a decorator. When looking at it from
> the perspective of "caller defines when and how the subroutine is
> called" I see that the entire (and very useful) level of abstraction
> is gone -- the application path is defined right where the application
> itself is defined. It's almost like declaring a piece of code and
> saying "just inject this into file X at line Y" -- not pretty.

Again, I get that you want to separate URL from the code, but I don't  
agree with your analogy. This may not matter.

Something to note is that the paths used in bobo are often not  
absolute.  If you use subroutes, http://bobo.digicool.com/index.html#subroutes 
, then the paths used will be relative to a position in a URL tree.   
In the referenced section, the paths in the Document and Folder  
resources are relative to the URLs used to access a document or folder.

An innovation in bobo, I think, is that it combines routes and  
traversal ("URL Dispatch" and traversal in http://docs.repoze.org/bfg/narr/urlmapping.html#differences-between-traversal-and-url-dispatch)


> However, I have to admit, that if taken as an iterative improvement
> over file/function name it looks very reasonable.

I'm not sure what you're referring to here.


>> In the original bobo (aka "python object publisher") that I wrote  
>> in '96, I
>> mapped URLs onto object names in modules.  Later, I extended this  
>> to use
>> object keys and this grew into a traversal model.  There were some
>> difficulties with this approach:
>>
>> - I needed some way to decide which objects should be URL  
>> accessible. This
>> led to some less than optimal rules.
>>
>> - The traversal model mapped well onto an object database, but not  
>> so well
>> onto relational models.
>>
>> Many people have taken the approach of providing an explicit  
>> separate (from
>> code) mechanism of mapping URLs onto their Python objects.   
>> Usually, this
>> involves having a table mapping URL patterns of some sort onto object
>> identifiers. I like explicit. :)
>
> I like explicit too, and I like decoupled as well :) By giving up the
> "manual" dispatching to some libraries people seem to dig themselves a
> hole without even realizing it. There's so little code saved by doing
> this, that I don't get it -- some of very useful features are given up
> and it doesn't look like a tradeoff -- just giving control up without
> a reason. ISTM that the reason is that this "manual dispatch" thing
> seems more complex than it is in reality.

Nothing is given up.  You can still configure paths externally if you  
want. (I'll have more to say on this below.)

> To some extent, various routing libraries make sense because they
> provide some level of extensibility, you know, like generic functions
> vs. series of ifs. But given how they are used -- one global routing
> object usually -- the need for that extensibility wouldn't be there if
> not this initial design.

I don't understand what extensibility you're referring to here or if  
this has anything to do with your objection to specifying paths in the  
code.

Note that bobo doesn't require a global routing object.  Bobo provides  
various ways of knitting URL trees together by having resources invoke  
other resources, as is done in the document-tree example referenced  
above.

> In my view, this kind of routing also has the same flaw as the one I
> see in bobo -- tight coupling. Apps know exactly what arguments they
> want to get

I'm confused. Generally, Python functions know what arguments they  
want to get. What does this have to do with routing?

> and those are directly "plugged" into data output of path
> pattern used in the URL router.

Sorry, I can't parse this. :)

> So basically there's a way to do dispatch with things like URLMap from
> Paste and other similarly minimal dispatch mechanisms that just plug
> one into another any way you wish and effortlessly and they are pretty
> much extensible as it gets -- they can be updated from anywhere in
> code.

Can you explain how you see this as different from:
http://bobo.digicool.com/more.html#configured-routes
?


> This is a very simple alternative to the routing libraries that
> I don't see used much. At the same time the problems with the popular,
> routing approach make people write more and more of those hoping to
> fix the problems that are actually inherent to the design. IMO anyway.

I still don't understand what you perceive these inherent problems to  
be.


On Jun 17, 2009, at 9:55 PM, Sergey Schetinin wrote:

> On 2009-06-18, Aaron Watters <arw1961 at yahoo.com> wrote:
>>
>>
>>
>> --- On Wed, 6/17/09, Sergey Schetinin <maluke at gmail.com> wrote:
>>
>>> When considering webapps and what urls they should handle
>>> it seems
>>> like the same should apply -- webapps define contained
>>> blocks of
>>> functionality and the task of placing them somewhere in
>>> URL-space
>>> belongs to the "caller" which in this case would be a
>>> configuration or
>>> serving script or, most often, a parent application.
>>
>>
>> So you seem to be suggesting that a web component
>> should not be aware of its URL in the same sense
>> that an object is not aware of
>> its variable name in the scope of the application
>> that is using the object.  Is that right?
>>
>> In particular you should be able to assign a
>> component to any URL in the same sense that you
>> can give an object any name.  You should also
>> be able to build relocatable URL trees which can
>> be "mounted" anywhere in the "calling" application
>> suite.  Do I catch your meaning correctly?
>
> Spot on.
>
>> It's not clear to
>> me whether Bobo allows or disallows this

It does.

http://bobo.digicool.com/more.html#configured-routes

> Generally, I think "allowing" it is not enough, I'd prefer it to be
> *expected*, not just supported.

To some degree, this is the approach that Zope 3 took,  It (strongly)  
encourages you to separate application implementation from  
configuration.  This was motivated by a well-intentioned desire for  
the kind of flexibility I think you're advocating.  The result was  
elegant but hard to deal with.  I think it's great to have this  
flexibility when you need it, but in my experience, 99% of web  
applications don't need this sort of flexibility and the methods  
needed to support the flexibility become a tax.

My design for bobo is based on the assumption that most people don't  
need a lot of flexibility while some do, where the former is the  
common case.  It tries to make simple applications very easy to  
create, without making it hard to address more complex requirements.   
I feel good about bobo's ability to deal with simple applications.  
Time will tell if it accommodates more complex applications. :)

This discussion falls into the larger debate of configuration vs  
convention and explicit vs implicit.  I tend to prefer explicit, but  
am wary of systems that require a lot of configuration (having built  
one :).  Most systems try to strike some balance, as does bobo.

Jim

--
Jim Fulton
Zope Corporation




More information about the Web-SIG mailing list