Code, document thyself!


In an effort to help others (and ourselves) write cleaner, happier, more eco-friendly code, we have added optional argument count and signature checking to OpenSRF. To make using this facility as simple and unobtrusive as possible there are three implementation levels (well, four if you count “a short note without parameter information”), each one more descriptive than the previous, so developers can choose how much (if any) time they will invest in documenting method signature and use and whether runtime argument checks are appropriate for that method. The other part is the argc setting that can be passed along with the signature. This specifies how many arguments are required, and the code will check their type and class against the actual parameters supplied if the signature gives that much information. Eventually, signature level 3 will allow individual parameters to be marked as required, and it will allow the handling of named (instead of positional) parameter description and validation. I’ll go ahead and lay out the structure of each method signature level here, and wait patiently for my thrashing to ensue.

  • Signature Level 1 — This consists of any notes you’d like to add and a Doxygen style parameter and return listing. This can go in either the signature or notes field (the latter for backward compatability with some of Bill’s inline early documentation) of the methods registration call:
    __PACKAGE__->register_method(
    ...
    argc => 2,
    notes => <<"  TEXT",
    The purpose of this bit of
    text is to show how things are done. send questions to miker@example.com.
    more taking and talking...
    @param authtoken The user
    login session key
    @param patronId The ID of the patron in question
    @param copy The copy object in question
    @return The hold object after we yank out it's beating heart.
    TEXT
    ...
    );
  • Signature Level 2 — This consists of an array of arrays with positional significance applied to each element. This style of signature must be placed in the signature field of register_method:
    __PACKAGE__->register_method(
    ...
    argc => 2,
    signature =>
    #  Description
    [ "This is a very descriptive note...",
    
    #  Params in the format of:
    #    param name,  param description, param type, param class hint (for Fieldmapper based objects)
    [  [ "authtoken", "The login session",  "string" ],
    [ "patronId", "The patron's ID",    "number" ],
    [ "copy", "The copy object needed to do this here thing",    "object", "acp" ],
    [ "profiles", "A list of patron profiles with the third profile removed", "array" ],
    ],
    #  The return description and type
    [ "The hold object attached to this user's blah blah", "object" ],
    ],
    ...
    );
  • Signature Level 3 — This consists of a hash of hashes with describing each part of the method signature. This is what each of the above signature levels are compiled down to internally, and it’s what is reported by an introspection call to the application. This style of signature must be placed in the signature field of register_method:
    __PACKAGE__->register_method(
    ...
    argc => 2,
    signature =>
    {
    desc => <<'      TXT',
    Our method is a very very very fine method which performs
    various tasks
    TXT
    params =>
    [
    { name  => "authtoken",
    desc  => "The login session key",
    type  => "string" },
    { name  => "patronId",
    desc  => "The patron's id",
    type  => "number" },
    { name  => "copy",
    desc  => "The copy object",
    type  => "object",
    class  => "acp" },
    ],
    'return' =>
    { desc  => "the hold object",
    type  => 'object',
    class => 'ahr' }
    },
    ...
    );

We also plan to write a simple script to introspect our OpenSRF applications and generate an API quick reference guide from this data. My personal hope is that such a guide will help trim down the (admittedly significant) learning curve that currently exists by virtue of our lack of API documentation.