A little documentation goes a long way
The most important change in my working practices in recent months, making your life a little better
Over the past couple of years, we've seen a dramatic shift in the way Plone software (and Zope software, and, really, Python software in general) is packaged. Our code is now broken into dozens of packages, pulled in via a complex set of dependencies, and managed via powerful tools like Buildout.
However, the part of this whole story that excites me the most is the humble README.txt, combined with the practice of turning it into the "long description" in setup.py that appears on PyPI.
I didn't always appreciate this quite so much, but that little bit of documentation is the minimum you must do if you release something. It is not a substitute for more narrative documentation, which helps people learn and understand how the pieces fit together. However, the package README is the first line of defence for reference documentation. Once people have an idea about how your software fits together, they will find the package and expect to be told enough about to use it without having to resort to code archeology.
Let's look at some examples. First, there's the narrative "how does it all fit together" type documentation. This needs to be kept separate, and must be discoverable independently of code structure. A good example of mine is the Dexterity manuals.
Next, a bad example: The README for plone.theme. Ironically, I was trying to remember how to hook a browser layer up to a CMF theme (the raison d'etre of plone.theme) and got rather annoyed by the total lack of information in that README. I then realised who wrote the package. D'oh.
A better example is collective.beaker, a package for using the Beaker session and caching management framework in Zope 2. Notice how you both find out what the package is for, and how it is used. There are installation instructions, too, and hints on things like testing, where this package has some unusual implications.
More recently, I've started doing this very seriously, for example in the as-yet unreleased update to plone.app.registry and the new-and-exciting plone.app.caching. My coding cycle is now to do the interfaces module first, then code and tests in tandem, and then documentation. I normally start writing the README while waiting for test runs to complete. This cycle is then repeated, so that I update and revise the README as I refactor code. Finally, I read the rendered README through once as a sanity check before doing a release to PyPI.
Importantly, the documentation for the packages above has helped make them substantially better. By trying to explain how they worked, I found troubling inconsistencies and omissions that I'd failed to spot in my unit tests or interfaces.
Put differently, if something cannot be documented properly, it's crap. Find out for yourself before you foist it on everyone else, as Chris McDonough would no doubt agree with.
I'll leave you with some practical advice:
- Have a README.txt in your package and make sure it's being included as the long_description in setup.py. The standard ZopeSkel templates takes care of this for you.
- Make sure your README makes sense to someone other than yourself. Start by explaining what the package is for and why it exists. Mention briefly how to install it. Then explain the main use cases and how they are achieved. Even a few bullet points will go a long way. If your package is mostly user-facing, explain where people should expect to find its functionality in the UI. You can reference interfaces or code as necessary, but give people a fighting chance to see the big picture first.
- Your README is not a doctest. You can have doctests too, and if you genuinely believe they are useful to someone trying to understand your package, you can append them too to the long_description after the README. They must be separate files. Doctests are often good for low-level documentation (and sometimes more appropriate for really basic packages that have no end-user or integrator relevance). But they are not by themselves sufficient for documentation, and can be hugely off-putting by tricking the reader into thinking they can figure out how to use the package, when in fact it only shows contrived test cases based on unrealistic test setup. (Yes, I haven't always been of this persuasion, but I've seen it go wrong too many times).
- Make sure your README is valid reStructuredText. I dislike reST, but I've grown to tolerate it, and it's what PyPI renders. In TextMate, the reStructuredText bundle helps a lot, as I can now preview the rendered text with Cmd+Alt+Ctrl+P.
- Have a HISTORY.txt in the long_description too (the standard templates again set this up for you), and maintain a change log once you've released the package. I cannot overstate how important it is to have a clear picture of how a package has changed, and in which versions new features or bug fixes were introduced.