I’m not a big fan of the Zope 3 Component Architecture.  A couple packages came out recently that made it clearer to me why.

The packages in question are repoze.bfg.httprequest  and r­epoze.bfg.restrequest­.  restrequest is easier to understand because it is more concrete: basically it adds marker interfaces to your request object for the request method, and you can add request_type=IGetRequest to your view declarations, hence declaring that a view is only applicable to that request method.  You can do this with a decorator like:

@bfg_view(request_type=IGETRequest, for_=models.IMyModel)
def my_view_get(context, request):
    return Response("GETn")

Right now repoze.bfg (a web framework) uses interfaces to do it’s dispatch to views, so this adds the ability to dispatch on request method.  The existence of these packages bothers me a great deal, and it took a while to figure out why.  These are entirely packages, with docs, tests, etc., that express something trivial.  If repoze.bfg supported conditionals on views — functions that would indicate if the view was applicable to a request — then you could express this like:

@bfg_view(for_requests=lambda req: req.method=='GET', for_=models.IMyModel)
def my_view_get(context, request):
    return Response("GETn")­

This is basically what Routes has done, though it additionally added request-method-dispatch as a primitive (just a keyword like method=’GET’).  I think this is a much nicer construct, and no extra packages are required.  More importantly, it doesn’t just read well (arguably IGETRequest reads a bit better), but it is easy to understand the mechanism and to extend or adjust that mechanism.  If you want to dispatch based on the Accept header, you just use for_requests=lambda req: ‘application/xml’ in req.accept.  If you don’t want to write lambdas, you can just abstract this in the obvious way in a separate function or a class with a __call__ attribute.

OK, so that’s simple enough: repoze.bfg should support this construct, and it’s just an unfortunately and hopefully temporary awkwardness that caused these libraries to be written.  In theory anyone could, right now, write an alternative implementation of @bfg_view that accepts this.  Of course, anyone could spend an hour or two and write a new framework from scratch, which makes this a less compelling argument: if someone decides to use repoze.bfg instead of writing their own framework or using a different framework, it’s not because they want to write or maintain their own infrastructure, or be in the situation where they’d ask “can you help me, but oh by the way I’m not actually using your stuff”?

The other reason for this, I think, is ZCML.  Here’s another way of expressing method-based dispatch:

<bfg:view for=".models.IMyModel"
      request_type="repoze.bfg.restrequest.interfaces.IGETRequest"
      view=".views.my_view_get"
      />

There’s no place to put functions into ZCML, but there is room for interfaces.  And more generally, interfaces are the tool that comes to mind most commonly when using the Component Architecture.  I think it leads to this kind of anti-pattern all too often, the use of marker interfaces and the accompanying indirection when a simple function would do.  There’s a claim that interfaces allow for more flexibility, but this is simply false: functions are completely general and ameniable to any kind of abstraction you want.  Interfaces add indirection, and sometimes that’s useful, but in many cases like this the indirection is added before there’s any need for it, and when there might never be a need for it.

It can be hard for me sometimes to articulate what bothers me about Zope 3-style architectures, because it’s hard to point to what exactly the alternative would be.  Usually the alternative is: a few lines of code.  Code is a powerful and extremely general abstraction, and especially in a dynamic language like Python the amount of abstraction you can add is substantial.  And you don’t need to add the abstraction until you need it.  So usually the alternative I see to the Component Architecture is simply a few lines of code, written for the specific case that is at hand.

Filed October 20th, 2008 under programming

We’ve been using Xinha at TOPP for a while, and with two of us now core developers, I thought it would be worthwhile to try to hash out what we’re hoping to get out of our investment in Xinha.  Here, as a first step, is a discussion of Xinha-related goals and strategies that Doug, Nick B-­S, Sonali, Ian and I all agree on.

 

Goals

This section will address the goals which inform and are served by our commitment to Xinha.

1. Promote a document model of the web for easy human-readability, machine-readability and interoperability in a broader network of applications and services.

2. Build best-of-breed tools which can be repurposed for a variety­ of uses and in a variety of contexts, and which are good enough to attract business and financing on their own, whether as standalone products or as candidates for integration into other products.

3. Develop real communities of users and developers to collectively steer and own the software that we are involved with, with TOPP’s role in each limited to that of an initial catalyst if necessary, and to that of one equal user, producer and beneficiary among many.

4. Provide a solid base of tools to enable more and richer creation, editing and remixing of documents on the web to enable a more free and active exchange of communications, ideas and culture.

5. Help as many people as possible through our work, whether their rel­ationship to that work is casual or committed, technical or non-technical.

 

Strategies

This section will address the strategic directions we have set for our involvement with Xinha to further our broad goals.

1. An essential c­omponent of the strategy is developing and promoting useful and easy tools for web document creation and editing.­

  • To promote wide adoption, we must provide end-user value up front and allow our own value to naturally emerge from the user’s intentional actions.  To that end, our tools must push HTML and CSS down to the level of implementation details for the casual end user, and the casual user’s preferred actions should epiphenominally contribute to a document-driven web.
  • To promote deep adoption, we must instruct interested end users in the philosophy and practice of the document model.  To that end, our tools must provide tiered layers of value which simultaneously steer end users toward a deeper understanding of the underlying technologies and reward curious end users for their hard-won knowledge with increased functionality or flexibility — but without sacrificing the immediate value of a casual user’s interactions with the tools: upfront investment not required, and learning curves remaining smooth.

 

2. A WYSIWYG text editor is a very promising candidate to add to our portfolios of tools and expertise; it has broad applicability and appeal.  Because of the nature of a WYSIWYG editor, it is not likely to be a direct source of funding or work; rather, its value will mainly come from reusing it as a component of increasingly many projects.  Its presence in our portfolio increases the value of our portfolio as a whole.

  • To ensure reusability for a variety of uses, the software must provide flexible functionality and user interface.  To that end, the software should provide a sensible (and, ideally, requiring no deep technical knowledge) configuration layer, enable plugin development and skinning capabiities, and should provide tools to minimize the effort and overhead of reconfiguration.
  • To ensure reusability in a variety of contexts, the software must be easy to install, decoupled from any particular broader environment, and integratable into any number of broader environments.  To that end, the software must rely upon and promote general standards and best practices for intercommunication and integration of application components.
  • To build a best-of-breed WYSIWYG editor, the software must implement powerful functionality solidly and must present an extremely appealing interface to users.  To that end, we need to identify that functionality and interface by iterative use and user feedback.

 

3. Xinha has a history of community activity and has a commitment to real collective code ownership; it is rightly billed as “the community-built open source online HTML editor.”

  • To ensure that Xinha remains owned by its community and not by TOPP or any other organization, we must be careful not to put anything into the core repository which narrowly serves TOPP’s needs or does not have the support of the community.
  • To encourage an active and dedicated community to steer the project, we should pursue initiatives to increase Xinha’s visibility and to build interest and enthusiasm, and we should be prepared to offer any necessary organizational resources toward infrastructure for an open source community.

 

5. In addition to building a great WYSIWYG editor, we should actively share the domain-specific knowledge we gain in the process of building it.

Filed October 11th, 2008 under xinha

At ploneconf, Kapil gave an interesting talk on a project called contentmirror (http://code.google.com/p/contentmirror/). It allows you to serialize your plone content into a relational database, in a pretty transparent way. It does this by hooking into the zope3 lifecycle events, and pushes the data out to the database synchronously in the same thread.


Although I haven’t tried it myself, the process looked easy, simple, and straightforward. Kapil made a conscious effort to keep it simple, and work for the most common use cases. Other scenarios will require using custom adapters.


It is a one way sync however. Any writes back to the relational database will not be reflected in the plone site. And, by default it will only catch archetypes. If you have other content types, you’d have to write custom adapters to get it working.


Using contentmirror can be useful for plone sites where you’d like to share the data with other applications. This opens up some exciting possibilities, like being able to use the django admin to look at the plone data. Anything that works with sql should be workable. It’s fairly new, but it’ll be interesting to see what people do with it.

Filed October 10th, 2008 under ploneconf