Saturday, January 11, 2003
Thursday, January 9, 2003
Aggregation versus Inheritance
EuroPython had an interview with Jim Fulton (I can't determine the date, but I'm guessing some time within the past year), in which he gives a good summary of Zope 3's differences over Zope 2 (I've been looking for such a summary):
Zope 3 moves Zope from an inheritance-based framework to a component-based framework. Complexity is managed by splitting responsabilities among many cooperating components, rather than many cooperating mix-in classes. Components are connected using interfaces, which also provide component specification and documentation.
Some other big ideas:
I could go on, but I won't.
- It should be possible to use existing Python objects in Zope with little or no change.
- Applications can be customized by adding, changing, or removing components.
- Site configuration is done by site-managers or deployment specialists without modifying code.
- Many CMF technologies will be part of the core.
- Acquisition and namespace lookup is wildly more explicit.
"Cooperating components instead of cooperating classes" could still be seen as an ambiguous phrase. I think developers who are steeped in component models and aggregation would understand it. But what about those who are used to the static overbearing inheritance model?
I guess it could be summed up as "Zope 2 excepts you (you being an object in the Zope system) to provide it lots of information and functionality all by yourself. Zope 3 looks for people to help you".
In Zope 2, if you got annoyed that a particular didn't implement the obscure little method to display sizing information in the ZMI, there wasn't much you could do about it without monkey patching.
In Zope 3, you write an adapter for that object that implements the ISized interface, register the adapter, and voila! One little object helping another.
By developing services to query for adapters (saying "I've got Frank here, can anyone tell me how tall he is?") instead of expecting behavior directly from an object, new doors to interoperability and speciality open up. Susie pops over and says "Why I can tell you, I've got measuring tape right here! He's 5 feet, 11 inches tall." Of course, Frank can say "I can tell you" and report his tallness himself, but he's a busy man and knowing his height at all times just might not be something he needs to do on a daily basis.
Of course, if Susie can be replaced with a robot or some other machine or person that can perform the same job (measure how tall people are), she can be replaced without bringing down the system. Frank's genetic algorithm can't be replaced (easily), so if he's suddenly unable to report his height correctly, he's useless in this situation without someone to help him adapt.
Saturday, January 4, 2003
Zope 3 reStructuredText Document 0.1
With Zope 3X alpha 1 out, I decided it was time to jump in again and see how it would be to write a new content object for it with associated components (adapters, views). I've tried to include comments in the files and README to document what I was doing as I was going along.
It can be downloaded here, and requires a fairly recent docutils and of course Zope 3X Alpha 1.
The current release is intended to focus more on documenting how to write a new content component for Zope 3 than on being a smart reStructuredText client. That functionality may come later.
I have some other thoughts about the process posted on ZopeZen.
Friday, January 3, 2003
Big Alpha Releases for Zope and Python
Two big alpha releases were made for the new year: Python 2.3a1 and Zope 3X a1.
Python 2.3 doesn't make any major changes to the language (unlike previous Python 2 series releases, which brought things like list comprehensions, generators, nested scopes, iterators, etc). Andrew Kuchling, as always, covers the changes extensively. Of interest are - ability to import from .zip files, universal newline support!, a new logging package, a new Set datatype and default Boolean datatype.
Zope 3X (x for "experimental" - a final Zope 3 release without the 'X' is expected to have some Zope 2 migration features) is a completely different beast from its ancestors. Its primary focus is still the Object Publishing mission that's been in place since the days of Bobo, but beneath the covers it is shockingly different from Zope's 1 and 2 before it.
Zope 3 is also dubbed the component architecture project. Its design focuses on many interacting components with well-defined interfaces. It's an aggregation heavy design, as opposed to the inheritance heavy design of Zope 2. Adapters exist to take the burden off of objects for out-of-scope elements such as text indexing or sorting-by-size. As the author of a particular object, you can implement those interfaces (ISearchableText, ISized) on the class itself, or as separate classes. Code that requires searchable text or sizing information asks for an ISearchableText implementation for your class, and since that's the only interface that it's expecting to use, it doesn't matter if it gets an adapter or your class - it only matters that the ISearchableText interface is implemented correctly. Design by Contract finally makes a strong appearance in the Zope world.
Zope 3 should also score big on the packaging and deployment front. Zope 3 uses a new configuration language called ZCML. ZCML is used to register new components at load time, and to load in still further components. It wrests control away from Python's import statements and need for special functions in __init__.py such as the common Zope 2 initialize(context). As such, it can be not only more expressive, but allows control over the order in which items get initialized. Under the mantra of explicit is better than implicit, all new components have to be explicitly added (usually in the products.zcml file). A side effect of this is that heavily customized Zope distributions can be made. Some such distributions exist now with Plone installers and BizarShop. Zope 3's customization and configuration capabilities should allow similar distributions to be made that don't look like Zope at all, while still tying in to all of the available features of Zope.
The combination of heavy Interface use combined with rich configuration options should mean that any part of the system could be kicked out in place of a new one, as long as the expected interfaces are implemented. This is a fundamental feature of component systems, and Zope 3 looks like it will live up to this feature.
Another big feature of Zope 3 is the proliferation of View Components. Views can be individual ZPT pages, attached to a particular content interface via ZCML. But they can also be full-on components in their own right, usually as Python classes. And they're not limited to HTML. Other views may be written to correspond with the other publishing channels (ftp, xml-rpc, and others in the future). I wrote a post back in September about my early experiments augmenting other Zope 3 components, in which I include some example code making an XML-RPC view onto a Job Board component written by someone else. My final paragraph in that post reads:
And finally, Zope 3 should yield a usable scalable means of adapting the works of other developers into new solutions by providing better control of product/service/view configuration and overrides, such as adding a new XML-RPC API to someone elses bug tracking system without having to alter that bug tracking system, or use secret Python hacks to alter behaviour.
A few other positive notes about Zope 3X a1. The "grand renaming" went into effect during the final weeks of the beta. This involved cleaning up the Python package hierarchy. It also involved case-normalization of package and module names. They are now all lowercase, like most other well-written Python packages/frameworks (distutils, docutils, etc), which makes it easy to distinguish classes and other module exports from the modules themselves. Zope 3 also uses Python 2.2 "new-style-classes" and gets rid of ExtensionClasses, since now you can write new extension types for Python in C and subclass them (which was the big point of ExtensionClasses). Zope 3 also (finally) makes use of other long-standing Python technologies such as distutils.
Now for the negative aspects. Since this is an alpha of the Zope 3 "experimental" line, it's not surprising that there is little or no documentation. The code structure is significantly different from that of Zope 2. It takes some time to find ones way around the code layout. Most things are pretty clear though (a benefit of having Interfaces) when you do find them, but there's so much new technology and terminology here that even when you grasp the terminology, it's not obvious to an outsider how to put it all to work.
Zope 3 is heavily reliant on Services, which is a good thing. Services are like Tools in the CMF - well known objects that provide a service to a global or local region. Examples of services are Event Channels (yay! Events!), or something like the Error Log that showed up in Zope 2.6. Other examples of Services are Database Adapters. In Zope 2, most service objects existed in the same namespace as all other objects. Zope 3 manages them in special namespaces. This allows content objects to be managed separately from service objects while still retaining placefulness. There are numerous upsides to a service based architecture. What's the downside? The downside is there's significant "what the...?!" effect when first encountering Services and Configuration objects. I'm sure it will all make more sense as future Zope 3X development releases are made, but right now it's a proverbial kick in the head.
There are some other aspects of Zope 3 that I'm likewarm to right now, mostly because they're difficult to fully comprehend how/when/where to use at the moment. Zope 3 allows for automatic user interface generation to occur. This was a feature of OS/2 (2.0+), and the defining motive of Naked Objects. Zope 2 has a subset of this feature in its use of properties. What Zope 3 seems to have done is to marry Interfaces (software, not user) and Formulator together. In essence, this allows easy edit forms to be generated off of the objects interface description. From the 'src/zope/app/browser/content/configure.zcml' file, here's an example of how an editform is configured for a ZPT Page:
label="Edit a ZPT page"
And from the IZPTPage interface:
source = zope.schema.Text(
description=u"""The source of the page template.""",
expand = zope.schema.Bool(
Whew! That's about all I can cover for right now. If I have time this weekend, I intend to write a new Content Component (probably a reStructuredText Document) to see how different it really is from developing a similar product for Zope 2 or the CMF. I have no promises right now that it will get done this weekend, but it is something I've been wanting to do. Now that Zope 3X is at alpha1 stage, the fundamental structure should be fairly stable.
Saturday, December 28, 2002
More Fiddling with Project Management
It should come as no surprise that I'm still fiddling with project management solutions via Zope. I've started down a new path, but before I explain it, I want to explain the current situation.
We're a very small organization (two people, with loose associations to other very small organizations). As such, we're constantly busy (thankfully) and don't have too much overhead to worry about in regards to project management. But having a to-do list of any sort is always helpful, and having a place to dump notes and flesh out ideas is always good too. Plus, we're decentralized - we work as much from home as we do from the office, and are often working from multiple machines in either location. Sometimes we need to communicate progress with each other, sometimes it's nice just to have a list for our own uses.
Ideally, content (which could be proposals, notes, software configuration requirements, etc) and issues should be managed by the same system - or at the very least be close to each other. And projects need to be easy to add in to the system by either main user, from wherever they may be. And most of all - it should offer only just-enough project content management features.
What we've used
Last year, we experimented with a couple of home-grown systems. One was a Zope based SQL backed project / task / contact tracking system. Data went derelict rather quickly. I was working on a much more thorough CMF based system with detailed workflows, nested tasks, role assignment, and more. There were a few key features that were difficult to do to meet our requirements, particularly in the non-containment object relation area, an area where Zope has typically struggled (but should be dealt with in Zope 3).
We gave the Roundup (0.4.2) issue tracker a try. While fast, it was still a young product. Too much command line work was involved to set up a Roundup instance, and while there is a Zope-Roundup Gateway available, it didn't integrate too well with Zope based content. I really like Roundup and think it has a lot of potential, but it didn't satisfy our requirements.
Ultimately, we landed in the ZWiki 0.7 + Tracker situation. Each project was their own folder or wiki, and usually had a tracker in it. This approach succeeded on the simplicity category and has been used for almost half a year. But it suffers from a couple of problems. The first is that Tracker is an aging old beast. It's generally pretty thorough, but has some rough edges. It's no longer supported, and I've heard claims that it doesn't work with the latest Zope release family (2.6.x).
The second problem is that I'm no big fan of Wiki's. I never have been. They've been useful, but we don't need whatever supposed collaborative effects Wikis are supposed to have. I don't like Wiki names - they either end up looking funny (with words like OneDotOh or ZoPe) or kick in when you don't want them to. Now that I've done some work with reStructuredText, I've come to loath working with Zope's normal StructuredText. It just doesn't work well with TextAreas. If you're used to Zope's StructuredText and have a good editor on your side, it's not too bad. But StructuredText and DTML (outside of SQL methods and occasional small non-HTML uses) are two Zope technologies I'm happy to leave to the past. Finally, we needed a stronger content management system than a pool of individual wiki's provided.
We did (briefly) try out ZWiki 0.12 with setting up the ZWiki based Issue Tracker, but it was a beast to set up and configure (loosing out on the 'easy-to-add-new-project' requirement) and too dependant on DTML for me to debug and make work for us on short notice. I liked the integration of Issue Tracking with the Wiki (gaining points on the keeping-issues-close-to-content) but there was too much pain involved, and too much inolvement with the technologies I wanted to leave behind.
And I know Wiki's really really work well for some, but I've never really been able to get comfortable with the Wiki way (ask anyone that I used to work with). I've been able to get by, but that's about it.
The new attempt
Facing the problem of trying to support the Trackers onto post-Zope 2.5.1 software, and facing other issues that stemmed from the basic folder/wiki layout of the site (no intra-project search abilities, poor navigation), it was time to look for something new. That new thing is Plone - a realized content management system built upon Zope's CMF (Content Management Framework). With my knowledge of the CMF (I used to be on the content management team at Zope Corp), I was able to start tweaking the system where I needed to - I made a Project Folder content type to distinguish Projects from other content types without putting too much expectations on the content type. It can contain anything, like documents, links, events, and a CMF Collector (a weaker but still fairly usable descendant of the Tracker). I later designed a quick workflow for Projects so that their status would be more meaningful to allow distinction between active, pending, suspended, completed, and cancelled projects. The workflow has a few simple rules, but nothing distracting.
CMFCollector is decent. It has some of its own rough edges, and is missing out on some of the nicer features of Tracker (mainly intra-issue explicit linking). But it has some nice new features, like the ability to automatically assign/accept a new issue. Its interface is a bit more streamlined, particularly in the Plone skin. It uses a very simple plain text markup language it calls WebText. It basically takes plain text, marks up URL's and citations/literal blocks (lines beginning with '>' or white space).
A downside to Plone is that it - for better or worse - just builds upon CMFDefault. And CMFDefault has very basic content objects, particularly the default Document, which is very monolithic. I partly blame myself for the design - I could have proposed a better solution back when I was on the team. In my vaporware compound document project, FDoc, not only are the parts of a document componentized, but so are the text handlers. A separate Handler Registry contains handler objects, which take a chunk of text and turn it into an HTML content body. This could be HTML (taking the content between the BODY tags), Structured Text, Plain Text, etc.
So today, wanting reStructuredText support, I tried to think of how to deal with this. I had a couple of options: either take the existing FDoc work, which is half baked (the most complete work is in a customer specific project and hasn't been backported yet due to time constraints) and add a reStructuredText handler (and also make a Plone friendly user interface), or make a subclass of CMFDefault's Document class, add in the ability to manage reStructuredText somehow and make it a new Content Type or replace the Document document type (this too would involve some Plone UI work, but it would only be a tweak of the Document's edit form).
Neither situation was quite what I wanted - there were too many existing dependencies on the default CMF Document behavior, and I haven't had the time to really learn how to make my own Plone UI pages work. So, I decided to do a hybrid of my original ideas. I made some new FDoc handlers that handled Zope's StructuredText and the reStructuredText formats. Then I made a subclass of the CMFDefault Document and started wiring in knowledge of the handlers and handler registry (based on the FDoc Text Part component, but made to match the default Document's interface). Then, out of some act of devilry, I decided to monkey-patch document by doing some good old fashioned Pythonic class __dict__ comparisons and substitutions. After a few tweaks to the document edit form to list the available text formats dynamically instead of statically, I had it working (aside from one infinite recursion bug my __dict__ tweaking introduced).
So now, it's mostly working. We have a decent looking project site that's navigation friendly. It's easy to add new content and to decide its form and format with very little restriction. And I'm finally away from StructuredText (although it still exists as an option). With other CMF and Plone options available from the likes of the CMF Collective, there's a lot of potential expansion if required.
Tuesday, December 10, 2002
Quicklinks Zope Product
Peter Bengtsson has a really cool Zope product, QuickLinks. His product effectively adds a shortcut toolbar for creating new Zope objects. It populates the same line of the ZMI as the "Add List" with icons representing different meta types. Clicking on one of them goes to the add form for that object. If you spend most of your time in the ZMI mousing through the add list to add the same set of objects (ie - folders, python scripts, SQL methods, and page templates) this is a great product. Configuration is done with a new Control Panel object.
State of the desktop?
The theme of today's conference was decentralization....
The theme of today's conference was decentralization. The first time the term appeared in DaveNet was in the first piece of 2001. That's another DaveNet tradition, like the Thanksgiving essays. I try to make the first essay of each year somehow express the most important idea of the year-ahead. It's always a guess. Some years I nailed it, desktop websites were the big idea of 2001, as we prepared Radio 8 for the market (it shipped in January 2002). And Werbach was right to pick it as the theme for the future in software-based technology. There's so much power on the desktops, both in the machine CPU and the human CPU, that isn't being well used in the centralized Internet architecture. [Scripting News]
Pfeh to the desktops. There's a lot of power in them, but I'm positive I'm not the only one using three machines throughout the day. There's nothing worse than realizing that the data you need is held hostage at home or at work - wherever you're not. There are plenty of times when I don't mind the separation - work's work, home's home. But there are certainly things that go in between.
I've been a fairly happy subscriber to Apple's .mac services, using my iDisk to ferry a few common documents and preferences (standardizing the subscriptions on all my instances of NetNewsWire Lite, Chimera bookmarks, etc). I'm using Apple's iSync Beta to keep two desktops, a laptop, and an iPod all synced up with the same address book and calendar data (I have a palm too, but I seldom use it any more).
Microsoft's "Active Desktop" vision wasn't entirely wrong. The implementation wasn't quite right, and definitely premature. But the lines between the desktop, the local network, and the global network, are fading away. Rendezvous makes local networking absolutely unbelievable in Mac OS X (well, it's believable to those who used the old AppleTalk, but it's remarkable in the internet age).
I don't know. The desktop web site idea isn't too bad (I'm using Radio right now), but I'll always prefer the Zope "Everything is done through the web" model. It's the comfort of knowing that fixes, updates, etc, can happen from anywhere, with pretty damn good security.
Monday, December 2, 2002
JTracker - Another Zope Issue Tracker
The always pragmatic Jens Vagelpohl has released JTracker, a simplified issue tracker based on the classic Zope Tracker and CMF Collector, but python based and simplified. It's what I've been meaning to write but have never made the time to do it.
As soon as I can make time to play with it, I'll post my thoughts.