RSS Feed

Peter Goodman's blog about PHP, Parsing Theory, C++, Functional Programming, Applications,

Pythonesque PHP: Self-Documenting Code

One amazing feature about Python is that it is self-documenting. All classes and functions can have documentation strings and they all have access to them using the __doc__ property. Most Python doc strings follow the conventions in PEP 257 and so when printed out they are usually quite nice.

I decided that I wanted a feature like Python's help() function in PINQ and so I made one using PHP's Reflection API. If you remember (and read my articles) I wrote an earlier blog post about manually rebuilding classes using the Reflector classes.

First, here's an example of the output from my help() function on the Dictionary class in PINQ:

class Dictionary
 |  An array-like class for mapping keys to values.
 |  
 |  Author: Peter Goodman
 |  
 |  Constructor:
 |  
 |      Dictionary([array $default_values]) <==> dict($default_values)
 |  
 |  Public Methods:
 |  
 |      offsetExists(...)
 |          $d->offsetExists($key) <==> isset($d[$key])
 |          
 |          Check if an entry in this dictionary exists for a given key.
 |  
 |      offsetGet(...)
 |          $d->offsetGet($key) <==> $d[$key]
 |          
 |          Get the value (entry) for a specific key in the dictionary. If the key
 |          does not exist in the dictionary then this function will return NULL.
 |  
 |      offsetSet(...)
 |          $d->offsetSet($key, $val) <==> $d[$key] = $val
 |          $d->offsetSet(NULL, array $val) <==> $d[] = $val
 |          
 |          Map a key in the dictionary to a specific value.
 |          
 |          Note: When specifying the key as NULL, val must be an array.
 |  
 |      offsetUnset(...)
 |          $d->offsetUnset($key) <==> unset($d[$key])
 |          
 |          Remove a (key,value) entry in the dictionary.
 |  
 |      toArray(...)
 |          $d->toArray(void) -> array
 |          
 |          Return the (key,value) pairs in the dictionary as an array mapping keys
 |          to values.
 |  
 |  Class Descendants:
 |  
 |      InnerRecord
 |      Loader
 |          ConfigLoader
 |          PackageLoader
 |      ModelDictionary
 |      PinqRouteParser
 |      ReadOnlyDictionary
 |      StackOfDictionaries
 |      View
 |          PinqView

As you can see, it gets the PHP Doc Block comments for classes and methods and displays them nicely. It also shows the class constants. I decided not to show class properties because I usually don't do doc-block style commenting on them and so I didn't need them. Another thing this class does is function the extending/implementing classes for an interface/class and shows it as a tree of class descendants. This follows nicely from the idea of self-documenting code as it allows the programmer to discover new and important classes.

I'm currently in the process of re-documenting PINQ's source code to be more Pythonesque as I rather like the format and it suits the help() function well. This, of course, does not mean that my help() function (and its associated functions) do not work for non-PINQ classes because they do.

You can check out/download the code from PINQ's Google Code project repository at http://code.google.com/p/pinq-php/source/browse/trunk/system/functions/reflection.php. The help function works for classes, objects, functions, and class/object methods (using two arguments instead of one).


Comments


Comment