The last few weeks I've put some time into improving the ArchGenXML documentation. (ArchGenXML is a tool that generates Plone products out of UML diagrams).
The big thing: generating always up-to-date information right from the program code. You shouldn't have to keep the documentation and the source code synchronised by hand. In ArchGenXML's case, three areas had gotten royally out of sync: the commandline/configuration options, the UML tagged values and the UML stereotypes. Options -- The commandline options (and the options in the optional config file) were handled by some custom methods. The usage message listing the options was just typed in by hand. They were mostly consistent :-)
Joel Burton had added an OptionParser module a year ago that used python's standard optparse
module. It wasn't integrated into the rest of the program. I added the missing options that had been added during the year, cleaned out old options, removed the --no-someoption
options and changed them into --someoption 0
(or 1
) on/off options, as it was a mess of positively and negatively worded options, depending on the default value. It was pretty easy to add a deprecation message for removed options, so despite the changes, it remained userfriendly.
The good thing about python's optparse
module is that it generates its own usage message out-of-the-box. No more need to do it by hand! Victory number one. Joel had already written a writer for a sample config; I improved on it, helped by the weeding-out of lots of options. Victory two: no more need for hand-maintained sample config files :-)
label
can be used to set the human-visible label for an element. Everytime there was a need for such en extension somewhere in the code, a 'getTaggedValue(my_tgv
)' was added. And in most cases, the tagged value wasn't added to the documentation. The idea to check whether those tagged values were documented (and to raise a warning if not) was floating around for some time.
In the end, I borrowed parts of the ideas in OptionParser and made a registry for tagged values. In that registry I added all tagged values with something like the following:
category = 'tool' tagname = 'toolicon' explanation = """The name of an image file, which must be found in the skins directory of the product. This will be used to represent your tool in the Zope Management Interface.""" tgvRegistry.addTaggedValue(category=category, tagname=tagname, explanation=explanation)
This was done for all options. The only thing that was needed then was to add a registry.is_registered()
function that gives out a stout warning when you're using an undocumented tagged value. After a week of getting emails "I'm getting these warnings", we got all values documented ! Nothing like visible warning to force you to document stuff.
The final stage was writing a documentation()
method that prints out all the options with their category and explanation. Victory three: always up to date tagged value support.
Man, it was needed. It was almost like the ArchGenXML developers behaved like Microsoft: inner knowledge of undocumented options. That's solved now :-)
The only things I needed to add was an extra explanation
parameter to the register function, the explanations themselves (mostly lifted from a recent documentation effort, probably by Martin Aspelli) and again a check "is this stereotype registered?" to the places where stereotypes were being used. And of course a documentation()
method that prints it all out. Copying that output to the plone.org website gives everyone an up-to-date list of stereotypes . Victory four.
The important lesson for me is that it pays off to put such infrastructure in place. I discovered the fun of doing it this way with the optionparser module (that was essentially already there).
On the one hand, you force yourself (as developer) to add documentation and to create a complete list of everything you've put into the system. On the other hand, it allows you to make your code more modular. You specify your stereotypes in one place and use them in another one. Especially nice is way Philipp's stereotype registry (UMLProfile) steers a major part of the processing.
Anyway: make your code generate documenation!
My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):