Ticket #11773 (closed PLIP: fixed)
Ship with Dexterity
|Reported by:||optilude||Owned by:|
Description (last modified by davisagli) (diff)
Proposer: Martin Aspeli Seconder: David Glick
Dexterity is widely considered the 'next generation' content type framework for Plone. It has a few advantages over Archetypes:
- A TTW types story. This is an important feature for many users, and a barrier to the adoption of Plone among non-developers and light integrators - crucially, it is also a feature most of our competitors have.
- Has comprehensive and up-to-date documentation.
- Less boilerplate, and so faster development.
- Uses modern ZTK components like zope.schema, z3c.form, etc.
Dexterity integrates well with existing Zope, CMF and Plone infrastructure, including other Archetypes-based content: the lower common denominator here is the CMF types system and the ZTK.
Dexterity is used in production by many individuals and companies, and usually becomes the preferred framework for those who have used it, fitting more naturally into their workflow. Anecdotal evidence also suggests Dexterity is easier to learn for new users, presumably for the same reasons.
Dexterity fits into various bits of the future Plone roadmap, notably as the core of the Deco layout system, and on its own to provide a way for non-developers and integrators to model their business requirements as types with custom schemata.
Previously, there has been an assumption that Deco, Diazo and Dexterity would all land together in a grand "Plone 5" release, where Plone core would no longer rely on Archetypes for its core types.
However, the amount of interdependencies and level of risk in this vision means it is very difficult to reach, falling into the very "big release" trap we are trying to avoid with the improved PLIP process.
By shipping with Dexterity in Plone 4, we will:
- Give Plone a TTW types story.
- Make it easier for developers to get started with Dexterity, removing the need to install a separate KGS
- Encourage an ecosystem of useful, reusable "behaviours" that give power to integrators and less advanced developers
- Provide a stepping stone towards the "Plone 5" feature set and the basis for further evolution
You can read more about Dexterity's philosophy here: http://code.google.com/p/dexterity/
Proposal & Implementation
- Release Dexterity 1.0 as-is. [DONE!]
- Remove Plone 3 BBB support [DONE!]
- Create plone.autoform, plone.supermodel and plone.directives.form branches that remove the martian dependency for defining form hints in schemata, and refactor plone.app.dexterity to have no dependency on martian or five.grok [DONE!]
- Make the standard "related items" field based on UUIDs (plone.uuid) instead of plone.app.relationfield. This is less powerful, but simpler and does not rely on intids and weak references, making it more robust for content export/import and edge cases not well handled until Plone grows parent pointers. [Update: The existing zc.relation-based related items behavior has been moved to plone.app.relationfield, and plone.app.dexterity no longer depends on zc.relation support.]
- Release 2.0 versions of the various packages [Update: branches for plone.dexterity and plone.app.dexterity now exist.]
- Include these in KGS
- New package releases
- KGS updates
Dexterity is a conglomeration of many packages, most of which are generic and not tied to Dexterity itself. A brief description of each follows.
It should be noted that most of these packages are very small, on the principle of "one package, one function".
These packages were largely created for Dexterity, but are generic, relying only on the ZTK and (in some cases) z3c.form.
- Provides support for dynamic modules. This is used to support TTW schemata.
- A decorator for synchronising access to methods across threads. Used as part of a schema caching optimisation.
- Adds the concept of a "behaviour", which is like a reusable adapter that can be turned on and off per-type or per-instance. Many of the standard features, like locking, versioning, staging, etc are implemented as behaviours, which are enabled per-type in the FTI or TTW editor.
- Marshalling and unmarshalling of objects described by zope.schema to/from an RFC822 representation. This is used in Dexterity's WebDAV support.
- Defines an XML syntax that represents a zope.interface/zope.schema model. This iis the basis for TTW types definitions, and may be used by tools (think ArchGenXML) to allow round-trip editing of schemata. (Already in Plone core as of Plone 4.1)
- Allows z3c.form forms to be configured based on hints stored in tagged values in schemata. The tagged values can be added as directives in the interface 'class' body or in a plone.supermodel schema. (Already in Plone core as of Plone 4.1)
- Support for through-the-web editing of zope.interface/zope.schema schemata. This is used by the TTW types editor.
These are the core of the Dexterity framework.
- The core types system, which depends on CMF only and is theoretically reusable outside Plone. This adds a custom FTI and base classes for folderish and non-folderish content types. The FTI holds a reference to a schema, which can be defined as a zope.interface schema, in a filesystem XML file, or in a TTW XML file.
- Plone integration, including the control panel with the full TTW editor and standard behaviours for Dublin Core and other "standard" fields.
Fields and widgets
These packages provide support for field types beyond zope.schema and widgets beyond z3c.form's standard widgets.
- Blob and non-blob file and image fields.
- File/image upload widget for plone.namedfile
- Date/time widget.
- Rich text field with support for portal_transforms, "safe HTML" and WYSIWYG editors.
These packages provide support for martian-style convention-over-configuration.
- Basic ZCA configuration. Essentially a wrapper around grokcore.component, grokcore.view, grokcore.security, grokcore.viewlet, grokcore.site, grokcore.formlib and grokcore.annotation (also included).
- Convention-over-configuration for plone.autoform and z3c.form views. (Presently also used for plone.autoform schema hints, but this is being divorced from martian and moved into plone.autoform itself).
- Convention-over-configuration and useful base classes for registering new content classes (which are rarely needed in Dexterity) and custom Dexterity add/edit forms.
These provide higher level, Plone-specific integration on an opt-in basis, available in the TTW editor as well as through GenericSetup.
- Allows Archetypes ReferenceFields to reference Dexterity content.
- Support for plone.app.iterate.
- Support for CMFEditions.
This section attempts to provide answers to some of the risks and concerns that have been raised about Dexterity in the past.
Codebase growth and long-term maintenance burden
(aka the "nothing in Plone core uses this yet" argument)
This is to a certain extent an inevitable risk of an evolutionary approach. We feel Dexterity is proven, widely used and stable enough (it's over 3 years old) for the risk of it being a "dead" technology to be low. Furthermore, there is patently a lack of innovation around the Archetypes framework, and little appetite for major refactoring to make it more coherent with other ZTK and Plone technologies.
It is worth nothing that Dexterity contains a lot less code than Archetypes, and is generally well-tested and well-documented. Multiple contributors who have contributed to its maintenance over the past year, beyond the ones responsible for this PLIP.
Users invested in Archetypes will be worried
We need to clearly communicate that Archetypes will remain a viable option for the foreseeable future.
Martian based configuration (aka "Grok-style" configuration) may be confusing
UPDATE: We now have branches that make Grok-style configuration an optional extra.
The Dexterity documentation suggests using convention-over-configuration based on Martian (the same library used by Grok) for tasks such as registering views, forms or event handlers. Some have expressed reservations about this for two reasons: Potential confusion with the Grok framework, and potential confusion given multiple ways to register components.
The first point is best addressed with documentation, although it would be feasible to create a shim around five.grok if desired to hide the "grok" name. (Note that five.grok is largely maintained by the Silva and Grok communities, with some support from the Dexterity developers). However, this must be balanced against the desire to be a good citizen in the Zope world and not reinvent the wheel.
On the second point, this is ultimately a choice that can be left up to developers. At the end of the day, ZCML and Martian-based convention-over-configuration are just two ways to execute zope.configuration actions and manipulate the component registry.
Regardless, we suggest that for the foreseeable future, Plone core (including plone.app.dexterity) uses only ZCML configuration, leaving martian configuration-over-convention as an integrator choice. It follows that plone.directives.form, plone.directives.dexterity and five.grok should be included in the KGS.
Note: Presently, martian is used in the configuration of form schema hints, which are the primary way to do things like make fields in forms permission-dependent or change widgets. However, there is a branch that removes this dependency, making martian-based configuration entirely optional and focused mainly on views, forms and other component concepts. The intention is to complete and merge this as part of the implementation of this PLIP.
zc.relation and five.intid
UPDATE: Dexterity no longer includes plone.app.relationfield or a relation-based related items field by default.
The "related items" behaviour in plone.app.dexterity and the standard way to do relation fields (plone.app.relationfield) is based on zc.relation, which in turn relies on zope.intid via five.intid. This is a powerful reference abstraction, made easy to use through a sensible API in z3c.relationfield/plone.app.relationfield.
However, the Zope 2 integration is somewhat brittle and will probably remain so until we have parent pointers for all content, as it relies on paths and traversal to re-establish an acquisition chain. Furthermore, relying on intids makes it harder to move content between sites or databases.
To address this, we propose to ship with a simple referenceable behaviour based only on plone.uuid and portal_catalog. The related items behavior and field would still be available by installing plone.app.relationfield, but not included by default.
Lack of feature parity with Archetypes
The current list of missing features can be found in the Dexterity issue tracker ( http://code.google.com/p/dexterity/issues/list). The most important ones are:
- No support for multi-lingual content. The current plan is to make LinguaPlone more Archetypes-agnostic and implement optional Dexterity support for this.
- No support for Link Integrity. A blueprint exists for a behaviour adding support for this, but it has not been built yet.
Note that there are behaviours for staging and versioning, which we would propose to include in the KGS, though they may need some more testing and could be made optional/future inclusions if not ready.
- Martin Aspeli
- David Glick
- Laurence Rowe
- Steve McMahon (particularly docs)
- Dexterity 1.0 is released.
- Dexterity trunk has been cleaned up to remove Plone 3 support.
- Dexterity trunk no longer depends on plone.app.relationfield and the various packages needed to support zc.relation-style relations.
- Dexterity trunk no longer requires including five.grok and martian (there is an optional extra to do so if desired).