Monday, April 13, 2015

Serving up POD & The five Cs of Good Documentation

I'm a fanatic about documentation.  As a developer that has been involved in creating tools for other developers all my career, I understand the importance of good documentation.  Creating good documentation is not easy, which is why so few people write good documentation.  Here's an easy to remember grading system for your documentation.  Does it meet the five Cs test?

 Is your documentation...

  1. Correct
  2. Complete
  3. Comprehensible
  4. Current
  5. Convenient

I probably don't need to go into too much detail here, but if ain't complete, correct, comprehensible and current it may be worse than no documentation at all.  If it ain't convenient it really doesn't matter how correct, complete, comprehensible or current it is, now does it?  It's not easy meeting all 5 Cs all of the time.  Most likely your documentation will transition through various permutations of those Cs during the software development lifecycle.  So how can we at least make our documentation more convenient and accessible and at least allows us to make an attempt to meet the 5Cs?




APL (A Programming Language)
Years ago I produced several software tools for APL developers.  I spent many hours making sure that my user base could understand how to use the tool.  I did this for two reasons.  First, I was trying to make a living selling the product and wanted the quality of the documentation to match the utility and quality of the tool kit.

Good documentation promotes usage and more sales.  Second, the better the documentation, the less support I had to provide, leaving me more time to develop new tools and bill consulting hours.

Back in those days, convenient meant a printed manual that was not too bulky and would be easy to consume.  I opted for a small 5.5x4.25" manual (which happened to be exactly what you get when you cut an 8.5x11" piece of paper in half and turn it on it's side) with a spiral binding.

It was easy for me to produce in my one-man band operation, small enough to put by your monitor or on your desk, indexed and well organized.  It worked.

Today, convenient means you can access documentation in any browser by visiting a URL.  Being a Perl programmer these days I write a lot of POD, so I need to quickly access my POD in my browser by visiting a URL like http://bedrock.openbedrock.net/bedrock/tag/sqlconnect.

Over the years I've created a few ways to deliver documentation to the browser.  I've embedded the documentation for Bedrock in the various modules that make up the web application framework and have created an Apache handler that extracts the POD from the modules, applies Bedrock's CSS and serves up documentation on all of the tags and many of the Perl modules.

Bedrock's documentation handler is a little more complicated than just extracting POD since it also produces an index of documentation and modules.

It's a fairly uncomplicated process though to provide documentation for your Perl modules or your web applications, so you really have no excuses!  I've found that you can embed POD in almost anything, whether it's Bedrock pages, Perl modules, PHP or HTML pages and deliver them in an easy to use and read format.

Embedding your documentation into your software (ala POD, Javadoc) and allowing your software to serve up that documentation as part of the product offering helps you keep you the documentation in sync and makes it convenient for your users to consume.

Hiding the POD from the Browser


Since I've been using the Bedrock framework to create some RESTful APIs I've been embedding the documentation right inside the Bedrock page in the form of POD.  Most of the web page handlers, like Bedrock's include the ability to enclose portions of the page in directives that either prevent processing or strip the contents or both.  Bedrock implements a <sink></sink> tag that "sinks" all of the content enclosed in the block by default to the ol' bit bucket.  Hence I might document a web page or provide some POD by simply creating a Bedrock page that that might look something like:

<html>
...some web app here...

<sink>
=pod

=head1 NAME
MyWebApp

=head1 DESCRIPTION

... more pod here...

=cut
</sink>
</html>  

Using one of the POD filters like pod2html will then produce an HTML version of the POD and deliver that to a browser.

Revealing the POD


When Bedrock process an application page and delivers the HTML page to the browser, the POD has been removed when it is enclosed in a <sink></sink> block.   So how do we now deliver the POD when someone wants to see the documentation?   As alluded to above, we'll pass the page through the pod2html filter to produce an HTML version of our POD.  We'll use Apache's mod_rewrite module to publish a convenient URL and create a simple CGI that will process the page and create the HTML version of our documentation.

Let's suppose I want to serve up documentation for my Bedrock (.roc) pages that have POD whenever we visit a URL like:

http://mysite.com/docs/foo

First, I create a rewrite rule in Apache's virtual host configuration file for mysite.com that intereprets the URI and redirects (internally) to a CGI that accepts as its parameter the filename (foo).

RewriteRule  ^/docs/([^.]*)$ /cgi-bin/pod.cgi?q=$1

Next, we create a simple CGI that process the page using Pod::Html and delivers the HTML to the browser.

#!/usr/bin/perl

use strict;
use warnings;

use Pod::Html;
use CGI;

my $cgi = CGI->new;

my $file = $cgi->param('q');

my $path;

# look for a Bedrock page...
foreach (qw/roc rock jroc jrock/) {
  if (-s $ENV{DOCUMENT_ROOT} . '/' . $file . '.' . $_) {
     $path = $ENV{DOCUMENT_ROOT} . '/' . $file . '.' . $_;
     last;
  }
}

print "Content-type: text/html\n\n";

if ( $path ) {
  pod2html( "--infile=$path"  );
}
else {
  print <<eot;
<html>
<body>
No documentation available for <b>$file</b>.
</body>
</html>
eot
}

Pretty easy right?  Now you have no excuse not to document your web applications!  I've used this technique to document RESTful APIs for example as well as providing adhoc documentation about web apps.  It would be easy to extend this concept to display documentation for your Perl modules.

RewriteRule  ^/modules/([^.]*)$ /cgi-bin/pod.cgi?q=$1&m=1

...
my $file = $cgi->param('q');
my $module = $cgi->param('m');

my $path;

if ( $module ) {
  $file =~s/::/\//g;

  foreach (@INC) {
    if ( -s $_ . '/' . $file . '.pm' ) {
      $path = $_ . '/' . $file . '.pm';
    }
  }
}
else {
  # look for a Bedrock page...
  foreach (qw/roc rock jroc jrock/) {
    if (-s $ENV{DOCUMENT_ROOT} . '/' . $file . '.' . $_) {
      $path = $ENV{DOCUMENT_ROOT} . '/' . $file . '.' . $_;
      last;
    }
  }
}
...

And of course, you could add your own CSS to prettify your documentation.  Check out the documentation for Pod::HTML for more information and options.

The quick and dirty examples above are not bullet proof and most likely won't handle all of your use cases (for example when you use Apache's Alias directive or have rewritten a URI), however this should give you a feel for a general technique to deliver documentation in HTML format and take care of at least one of the 5 Cs.

Ink is better than the best memory. 
  -- Chinese proverb

No comments:

Post a Comment

Feel free to leave a helpful comment. Nastiness is unbecoming. Spam will be promptly deleted.