Add-on Products Developer Manual

« Return to page index

A guide to best practices for add-on Product development

1. Introduction

Who this documentation is for, and some initial thoughts what makes a high quality product.

Introduction

The Plone core is a beautiful thing.  It does a lot of things, and does a lot of things well.  But much of the power of Plone lies in its large and growing library of add-on products, which extend Plone in ways both large and small.    Many of Plone's core components started life as add-on products, and add-on products are the primary way to share and reuse code in the Plone community.

This guide is intended to help new product developers who wish develop high quality add-on products and contribute those products to the Plone community. It will also be useful to add-on product developers wanting to future-proof their products through the use of best coding practices.


Do you even need to write a product?

Sometimes the best product is one that never gets written because the developer just contributes to something that already exists.  Before you dive into writing a new product from scratch, it's worth taking a bit of time to check out the Products section of Plone.org as well as the Plone Collective (our shared SVN code repository), to see if someone else has already taken a run at solving your problem.  

It's in the long-term interest of the Plone community to have fewer, higher-quality, more generalized products than many products that all solve very similar problems in slightly different ways.   Most Plone add-on product developers are very open to new contributors, and would welcome your help in making an existing product better!

Add-on Product Developers 

A forum/list for developers of add-on products.

 

General Characteristics of High Quality Add-on Products

Add-on products from Plone range from the very simple to the extremely complex, which means that what makes a product "high quality" may vary quite a bit from one product to the next. That said, most high quality products will have the following general qualities.

 

Balancing Extensibility and Simplicity

A good add-on product is designed to be customizable / extensible / adaptable, where appropriate. It should be easy to define different content types which use any custom logic or machinery in your product. It should be easy to subclass any custom content types in your Product.

At the same time, simplicity is a virtue. Good products solve the problem they're trying to solve, without going overboard creating new frameworks or making every single point of the product customizable, using a minimal number of needed methods, etc. "Does one thing, and does it well."


Using Zope 3 Development Techniques

With the advent of Zope 3 technology, the Plone community now places a very high value on good componentization. Complex products should broken into multiple products, libraries, methods and classes, consisting of Zope 3 compoments (interfaces, views, annotations, etc.) that can be re-used by other products.

Good starting points for learning how to apply Zope 3 development techniques in add-on Products include:

 

Using Good Archetypes Development Practices

Archetypes is the framework Plone uses for building its core content objects, and thus many add-on products involve creating new content types with Archetypes.  Using Archetypes correctly will go a long way towards making your add-on products robust, reliable and easy to use. 

A good starting point for learning more about Archetypes is:

However, a custom Archetypes content type might not always be needed. If you only need to extend the schema of an existing Plone content type, you should look into archetypes.schemaextender. This allows you to take advantage of the strengths of ATContentTypes (or other existing Archetypes-based content types) non-invasively without sub-classing. Learn more about Schema Extender:

 

Well Designed User Interface

Plone prides itself on being the most highly usable and accessible content management system around.  Add-on product developers should pay attention to the user interface for their products.  For example,

  • Beginning with Plone 3.0, add-on Products can take advantage of the KSS javascript framework.  Effective use of javascript can help you build a much more responsive and rich user interface.  However, user interfaces should degrade gracefully (with functionality intact) in browsers that lack javascript.
  • Products should use appropriate Archetypes or formlib widgets for editing interfaces.  See:
  • Push end-user configuration options into Plone control panels.  Avoid making users go into the ZMI or the filesystem to configure your add-on products.

 

Security

Thanks to Zope, Plone is a highly secure system, and is generally pretty resistant to the most common types of security problems that plague, say, PHP/MySQL content management systems.  But every add-on product is a potential source of security problems, and thus you should pay clear attention to security as you design your product. 

Useful starting points on security in Plone include:

 

 

Internationalization (i18n)

Plone has users all over the world, and Plone's internationalization framework is one of its strongest features.  But it's not worth much unless add-on Product authors make sure their products are i18n-ready.  (Don't worry, you regrettably monolingual folks, it's really quite easy, and no foreign language skills are needed!).

Good starting points:

 

 

Naming your product

Choosing a good name really helps people understand what your product is and what it does. Unfortunately, the Plone and Zope communities have a history of coining awkward product names. Renaming a product is painful because of migration hassles for later releases, so getting the project name right the first time around will save you work later. Here are some recommendations for choosing a great product name:

  • Choose a name that is unique, memorable, and not too similar to other existing products.
  • A good name describes or suggests what your product does.
  • As the Plone community transitions to eggs for product distribution, it's important to remember that the namespace is not the product
  • Avoid having the word "Plone" in your product name — it's usually obvious from the context that it is a Plone product. If you really feel the need to have Plone in the product name, it's better to call it something like "XYZ for Plone". Plone® is a worldwide registered trademark of the Plone Foundation, and people very often think products that contain the word is the responsibility of the Foundation, which is confusing and unnecessary.
  • Avoid jargony acronyms like "AT" "CMF" "NG" etc. and names based on the underlying technologies of your product.
  • Avoiding prefixing your products with your company name, or the company you are developing it for.
  • Don't lowercase your human-readable product names just because Zope 3 convention is for lowercase names in code.

 

At the risk of courting controversy, here are some "good" product names and some "less good" ones.  (Remember: we love all add-on product developers, even if we don't love all the product names! :)

 

Good
less good
"Wicked" - a wiki product
ATSchemaEditorNG
"Iterate" - product for document staging
Kukit (turned out to be a Norwegian expletive!)
"Quills" - a blogging product
CMFSin
"Bling" - a javascript product
mxmContacts

 



2. Good coding practices

There's a tremendous amount of wisdom in the Plone community about how to write code efficiently and effectively. Here's a summary.

General Best Practices

Joel Burton's tutorial Best Practices for Plone Development is an essential starting point for anyone new to Plone development.  It covers the basics of working with filesystem code, source code management, configuration management, documentation, debugging and testing.  Some parts of it (e.g. configuration management) are getting a bit out of date, but overall, it's the single best starting point for the nitty-gritty of development technique.

In addition, Martin Aspeli's book Professional Plone Development provides a wealth of information on current best practices for Plone 3 development.  It covers all of Plone's current technologies and core development practices.

 

General coding standards

  • Most of the logic in an add-on Product is written in Python. Following good Python coding style guidelines will help make your Product understandable and maintainable.
  • Add-on products should be distributed as eggs. Further, Zope 3-style conventions discourage the use of the "magic" Products directory, although converting existing existing Zope 2-style Products to the packages using the Products.* namespace is encouraged.
  • The Plone community values standards compliance and accessibility, so you should use proper XHTML, TALES, and CSS syntax. We recommend that you check your XHTML, CSS and RSS for compliance with the relevant W3C standards.   Strictly validating your templates for XHTML compliance is more important than ever before, since doing so will allow your products to work with the Chameleon template rendering engine, which provides 25-50% speed improvements over stock Plone 3/4.  It's not required yet, but it's very smart future-proofing, and just plain good coding practice.
  • Avoid using DTML in your Plone add-on Product. Although Zope contains support for the DTML scripting language, DTML has been supplanted by TAL for building page templates and Python for underlying logic.

Think about Compatibility

Plone has traditionally supported the two most recent versions of Zope 2. This is generally a good model for add-ons to inherit: supporting the two most recent (major) versions of Plone; at the time of this writing that would be Plone 3 and Plone 4. It requires a little more work, but makes your contributions available to a much broader audience.

How I Learned To Stop Worrying and Love the API

One of the cool things about Plone is its API. Anything you can do through the web interface, you can do via filesystem code that manipulates the Plone API. Of course, that raises the question of how you discover what API methods to call. The following products can help.

DocFinderTab
DocFinderTab gives you instant, through-the-web access to the API for any object you can get to in the ZMI. In many ways, it's nicer than looking through the source code, since you see all the methods of the base classes, and nicer that looking in the debugger, because you get things arranged by base class. This product is dead simple to install and use. There's no excuse for not trying it out today. This really should get shipped as part of Zope.
Clouseau
Clouseau is an AJAX-based interactive Zope/Python prompt that lets you interact with Zope and Python directly from within Plone. It's very easy to use, has no dependencies, and is extremely handy.
Other products' Install.py files
A great way to see how to configure things is to see how other products do it, of course. Look at the Install.py for your favorite product. For example, to learn how to install new workflows from disk, see how we do this in PloneHelpCenter.

For a great introduction to using the Plone API, see:

Developer Documentation

Testing and DocTests

Plone has a strong culture of test-driven software development. In fact, many folks in the Plone community often judge the quality of add-on products by looking at the tests. Good tests mean that you can prove your product works, and helps you avoid breaking your product as you (and others) develop it on an ongoing basis.

Plone/Zope 3 developer Phillip von Weitershausen (PhiliKON) offers the following advice on testing:

  • The top-level *.txt texts should be unit tests if you're writing a basic Zope 3-style component. Unit tests means you should be using DocTestSuite/DocFileSuite from zope.testing.doctest, not any of the convoluted ZopeTestCase test suites. If your test needs set-up, only load as much as you need. Avoid loading ZCML in a unit test.
  • Tell a story into which you involve the reader using first person plural ("we"). Create the component, walk through its API, explain tough edge cases and why it's necessary to watch out for them (and to test them). I know, this takes time.
  • If you're writing functional tests, talk to the application using the test browser (Products.Five.testbrowser.Browser, docs in zope.testbrowser/README.txt). It's a great way of testing interactive UIs in a doctest, and the result is very readable.

Phillip concludes:

Just because you write doctests doesn't mean you've also written docs. Testing and documenting is hard and doing them at the same time can mean you consolidate effort, but it also means you need think hard. Writing good tests, especially writing good doctests, is much more challenging than the coding itself. Be prepared to spend more time on this than the actual coding."

Lots more great information on testing can be found in Martin Aspeli's tutorial "Testing in Plone."

Also worth a read: Agile Documentation with doctest and epydoc

Useful Documentation Products

The following products can help you generate documentation for your add-on products.

DCWorkflowGraph
DCWorkflowGraph creates graphic diagrams of your workflows.
DCWorkflowDump
DCWorkflowDump exports workflows you've built via the ZMI to Python code for a filesystem based product.
EpyDoc
Epydoc is a smarter and more featureful version of the module that ships with Zope. It builds handsome, indexed API documentation for your product, or even for Zope and Plone itself. It can even generate this as a PDF, which impresses clients and saves you time in creating this kind of documentation. Plus, actually seeing your docstrings typeset is a good incentive to write better one.

3. "Worst Practices", Or Things To Avoid

Relevant bits from Stefan's "Top Twenty Plone Pitfalls" presentation.

At Plone Conference 2006, Stefan Holek ("lurker") presented a well-received talk called "Top Twenty Plone Pitfalls."  You can read his entire presentation or watch it online

A number of his pitfalls were especially revelant to developers of add-on products, and we've adapted them here as a set of "Worst Practices" or things to avoid.

Do not develop your application logic in TALES.

Templates are for presentation, and for presentation only.  You should put all of your application logic into Python code (scripts, tools).   If you find yourself trying to create complex conditional statements in your templates, take a moment and think about how you can push your logic down into a Python script.  Don't start writing increasingly complex TALES python: expressions -- they will make your application hard to maintain, hard to debug and hard for others to understand.

Stefan humorously-but-seriously suggests that you make a small donation to the Plone Foundation every time you use “python:” in a Page Template. ;-)

Do not impose a relational data model on an object database.

Do not expect the ZODB to work like MySQL.  It won’t.  The ZODB is an object database, not a relational database.  Think about how to design your application in an object oriented way, rather than as rows of data in a table.   Conversely, there is nothing wrong with using an RDBMS with Plone, if your data calls for it.  The most common way to do this is to use a database connector and ZSQL methods to read/write data from your RDBMS.

Useful resources on how to do this include:

Do not check for roles, only check for permissions.

  • That’s because objects and methods are protected by permissions, not roles
  • Use portal_membership.checkPermission.

Do not use REQUEST.AUTHENTICATED_USER.

  • AUTHENTICATED_USER is unsafe and was deprecated many winters ago.
  • Use portal_membership.getAuthenticatedMember

Do not use the Authenticated role to model your site’s security.

  • Authenticated is a system-owned role.
  • Add your own custom role(s).

Do not use proxy roles.

  • Proxy roles are similar to SUID scripts in *nix.
  • Be very careful about what your proxied scripts do; you are poking holes into your site’s security.

Do not forget to add security declarations to your methods, the default is public (!).

  • That’s because Item, which is the base class for most Zope2 objects, allows access to unprotected attributes.
  • Be extra careful with tools. Methods may need to be public and perform their own security checks.

Do not call getObject on catalog results.

  • getObject uses restrictedTraverse internally.
  • Add everything you need as catalog metadata.

Do not use contentValues nor objectValues.

  • contentValues/objectValues “wake up” subobjects, i.e. load them from disk into memory.
  • objectIds is OK, incidentally, but not contentIds.
  • In Plone 4 or newer, use folder.keys(), folder.values() and folder.items() instead.

Do not return objects from scripts, return (lists of) dictionaries.

  • Objects cannot be RAM-cached.
  • Objects will be security checked.
  • Python scripts are prime targets for RAM-caching.

Do not compute values at display time.

  • Compute values at edit time and store them.

Do not “touch” objects at display time.

  • Viewing an object must not cause a database write.
  • Easy to accidentally cause a modification; watch the Undo tab.

 

 

 

4. Launch! Product Release and Community Process

How to package up a solid release and engage in the Plone community process to build a network of users, developers and supporters around your product.

Making a good product release is about more than just slapping some code up for download. Before taking the plunge and creating a public release for your product by listing it on plone.org, make sure you're ready to make the commitment! Here's what you should do to help the Plone community find, learn about, get started with and help you improve your products.

Connect With Other Add-on Product Developers

Your fellow developers can be an amazing source of advice, help, enthusiasm and support.  And they hang on on the product-developers list.  Come join us! 

Put Your Code in the Plone Collective

Every publicly released product should have a public SVN repository, preferably the Plone Collective, unless there is a compelling reason to put it elsewhere.  Without a public SVN repository[1], the Plone community won't be able to help test or contribute to your product.  The Collective is the single most "accessible" place for code in the Plone community. Be sure to "tag" all of your releases in the Collective (that is, copy the code (usually the trunk) to the "tags" directory), and never change or delete anything you tag — people might be depending on this form of accessing your code in their buildouts!

Listing Your Product on Plone.org

Each released product should have an entry in plone.org/products with accurate, up-to-date information on current and past releases.  There's no need to make an entry before your first public release, although you are welcome to do so. It's critical that you never remove or rename any releases you make on plone.org, because people may have buildouts that expect to be able to find your code on plone.org.

Plone Software Center (which powers plone.org/products) also offers a few extremely useful features to help you maintain and improve your code.  We strongly recommend that you take advantage of:

  • Issue tracker: Every product should have a public issue tracker, preferably on plone.org/products unless there is a compelling reason to put it elsewhere.  This helps users of your product report bugs and find out when they're fixed.
  • Roadmap: Active products should have a roadmap for future improvements and improvement proposals.

Tip: a lot of people like to see examples of an add-on product in action before deciding to use it.  If it's appropriate and possible, try to include in your product description a couple of URLs that show your add-on product in action.

See http://plone.org/documentation/tutorial/plone-software-center for more tips on making the most of Plone Software Center.

The best way to push your egg packages to Plone.org is with an egg-releasing tool such as jarn.mkrelease.  You should push your packages to both Plone.org and PyPi for maximum exposure both to Plone and the wider Python community.

Documentation

Products that expose functionality to end-users of Plone should have end-user documentation, preferably at plone.org/products, so it is easily accessible to people who do not have filesystem access.

  • Every product should have an INSTALL or README document that clearly describes how to install and uninstall the product, and lists any dependencies on other products or libraries.
  • If appropriate, a product should have documentation for integrators that describes how the product can be customized or extended.
  • Your product should include an open source license (preferably GPL), credits and have an appropriate version number.

  • You should maintain a HISTORY.txt file that lists the important changes with each release. Note that this shouldn't necessarily be a verbatim listing of the subversion log, but should be clearly distilled to a list of known bugs that were fixed, new features, and noteworthy structural improvements.

Engaging the Community

The most powerful part of Plone is its strong, diverse and friendly community of users and developers.  The most successful add-on products for Plone tend to be ones whose authors successfully engage with and participate in the wider Plone community.  Participating in the Plone community will help you become a better Plone developer.  Open source communities are driven by social capital and reputation, and more that people get to know you, the more confidence they'll have in your code, and the more they'll be willing to pitch in to help you extend and maintain your product.

Stewarding a Product

Once you've released a product, be a good steward! This doesn't mean that you need to be the sole developer for future enhancements, but that you take some responsibility to drive development forward and address the needs of users. This means:

  • listing your email address as the product's contact on it's Plone Software Center page
  • responding to bug reports and grooming the bug tracker
  • making point releases when needed
  • finding a new steward if you no longer are up for the job.