Javscript : A documentation pattern

documentation in Javascript

Javascript does not provide a built-in documentation tool : When one is searching for informations on how to use a class, a method or a property, he will have to dive into the code to find the relevant comments, which is time-consumming and might lead programmers to read the code rather than the documentation, thus favor implementation for specification and write code only compliant with the current version of the API. Another issue here is that if an API is provided minified, the documentation will be removed.

Another option is to use an online documentation site. Such documentation site can be generated automatically, with YUIDoc for instance. The issue here is that the help is not tied to the code, but rather an independant  web site.

A pattern for functions.

Let me suggest a pattern i found usefull, that allows :

– keep the code and its help together.
– easy to use.
– standard.
– resistant to minification.

This way you can provide help even with a minified version of your API, meaning you share the functionnality but not the code : your secrets are safe ( 🙂 ).
The idea is to take advantage of the lexical scope of a nammed function declaration, and that a function is an object to write.
Help is a string that is defined on the function object prior to its definition. This way you can read it when browsing the code.
But more importantly, you can have a description of the function in the console by typing functionName.help .

One simple example :

printFigures.help=[
'print all the figures in the range ',
' arguments : start : starting figure (integer) ',
' end : ending figure (integer ) ',
' throws : invalidArgument exeception  ' ,
'   if start, end are not ordered integers. ' ].join('\n');

function printFigures(start, end) {
   // check arguments
   if ((start != ( 0 | start ) )
          ||(end != ( 0 | end ) )
             ||( start>end))
   throw ('printFigures invalidArgument : start and end must be two integers with start < end. (start :' + start + ' ; end :' + end + ' ).');
   // print figures
   for (var i=start; i<end; i++) {
       console.log(i);
   }

Now if you type in the console :

printFigures.help();

you’ll get :

 
print all the figures in the range
arguments : start : starting figure (integer)
end : ending figure (integer )
throws : invalidArgument execption if start, end are not ordered integers. 

The documentation pattern applied on Classes

For Classes, the pattern is a bit different : the class and class properties will
be explained in the Class function, and a little (simple) processing is needed to
hook the help on each methods :

Rect.help=[
'Rect. Class. defines a colored rectangle. ',
' constructor arguments : ',
' left, top, width, height : numbers with obvious meaning.',
' color default to white.',
' properties : ',
' left, top, width, height, color : obvious meaning.',
' throws : no check performed.' ].join('\n');

function Rect(left, top, width, height, color) {
  this.left = left ;
  this.top = top;
  this.width = width;
  this.height = height;
  this.color = color || '#FFF' ;
};

var rectPrototype = {
  drawHelp : [ 'draw : draws the rectangle on the provided context.',
               ' arguments : ctx is a valid Contxt2d ' ].join('\n'),
  draw : function (ctx ) { 
            ctx.fillStyle = this.color;
            ctx.fillRect(this.left, this.top, this.width, this.height);
  },
  isWithinHelp : [ 'isWithin : returns wether provided coordinates lies within the rect ',
                   ' arguments : x,y are coordinates of the point to test against' ].join('\n'),
  isWithin : function(x,y) {
               x -= this.left;
               y -= this.top;
               return x >= 0 && x <= this.width && y >= 0 && y <= this.height ;
  }
}

helpMerge(rectPrototype, Rect );

After writing this code, you can type in the console

Rect.help

to get :

Rect. Class. defines a colored rectangle.
constructor arguments :
left, top, width, height : numbers with obvious meaning.
color default to white.
properties :
left, top, width, height, color : obvious meaning.
throws : no check performed.

Just type ClassName.methodName.help to get the method help.
(most consoles (like FireBug) have autocomplete that will give you the list of all
methods)
just type :

Rect.isWithin.help 

to get :

 isWithin : returns wether provided coordinates lies within the rect
arguments : x,y are coordinates of the point to test against

The code to merge a prototype description containing help with a
Class is this one :

 function helpMerge ( sourceObject, destinationClass ) {
    for (var prop in sourceObject) {
         var thisPropValue = sourceObject [prop] ;
         // skip help strings
         if (prop.match("Help$")) continue ; 
         destinationClass.prototype[prop] = sourceObject[prop];
         // method with help ? setup the help on the method, and add the method to the class function
         if ( (typeof (thisPropValue) == 'function') 
                    && (sourceObject[prop + 'Help']) ) {
                  thisPropValue.help = sourceObject[prop + 'Help'];
                  destinationClass[prop] = thisPropValue ;
         }
    }
}

Conclusion

The proposal i make here is still uncomplete : for instance, properties defined on the prototype can’t provide
for any help.
But the main idea seems interesting : with this pattern, accessing the documentation of an API -even if
it was minified- is just as simple as typing in the console ClassName.help or className.method.help. No need to have the code,
no need to browse the code or an online documentation. The programming experience gets closer to the one we can have with
high level languages/editors.

Let me know if it triggers some thoughts, do not hesitate to comment, and happy coding !

Advertisements
This entry was posted in Uncategorized and tagged . Bookmark the permalink.

2 Responses to Javscript : A documentation pattern

  1. Damian says:

    A very smart solution to a problem that has haunted Javascript a long time.

    I will use it in my functions to see how it works.

  2. I think this is actually quite clever!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s