Приглашаем посетить
Чулков (chulkov.lit-info.ru)

Documentation

Previous
Table of Contents
Next

Documentation

Documentation is inherently important in writing quality code. Although well-written code is largely self-documenting, a programmer must still read the code in order to understand its function. In my company, code produced for clients is not considered complete until its entire external application programming interface (API) and any internal idiosyncrasies are fully documented.

Documentation can be broken down into two major categories:

  • Inline comments that explain the logic flow of the code, aimed principally at people modifying, enhancing, or debugging the code.

  • API documentation for users who want to use the function or class without reading the code itself.

The following sections describe these two types of documentation.

Inline Comments

For inline code comments, PHP supports three syntaxes:

  • C-style comments With this type of comment, everything between /* and */ is considered a comment. Here's an example of a C-style comment:

    /* This is a c-style comment
    * (continued)
    */
    

  • C++-style comments With this type of comment, everything on a line following // is considered a comment. Here's an example of a C++-style comment:

    // This is a c++-style comment
    

  • Shell/Perl-style comments With this type of comment, the pound sign (#) is the comment delimiter. Here's an example of a Shell/Perl-style comment:

    # This is a shell-style comment
    

In practice, I avoid using Shell/Perl-style comments entirely. I use C-style comments for large comment blocks and C++-style comments for single-line comments.

Comments should always be used to clarify code. This is a classic example of a worthless comment:

// increment i
i++;

This comment simply reiterates what the operator does (which should be obvious to anyone reading the code) without lending any useful insight into why it is being performed. Vacuous comments only clutter the code.

In the following example, the comment adds value:

// Use the bitwise "AND" operator to see if the first bit in $i is set
// to  determine if $i is odd/even
if($i & 1) {
  return true;
}

It explains that we are checking to see whether the first bit is set because if it is, the number is odd.

API Documentation

Documenting an API for external users is different from documenting code inline. In API documentation, the goal is to ensure that developers don't have to look at the code at all to understand how it is to be used. API documentation is essential for PHP libraries that are shipped as part of a product and is extremely useful for documenting libraries that are internal to an engineering team as well.

These are the basic goals of API documentation:

  • It should provide an introduction to the package or library so that end users can quickly decide whether it is relevant to their tasks.

  • It should provide a complete listing of all public classes and functions, and it should describe both input and output parameters.

  • It should provide a tutorial or usage examples to demonstrate explicitly how the code should be used.

In addition, it is often useful to provide the following to end users:

  • Documentation of protected methods

  • Examples of how to extend a class to add functionality

Finally, an API documentation system should provide the following features to a developer who is writing the code that is being documented:

  • Documentation should be inline with code. This is useful for keeping documentation up-to-date, and it ensures that the documentation is always present.

  • The documentation system should have an easy and convenient syntax. Writing documentation is seldom fun, so making it as easy as possible helps ensure that it gets done.

  • There should be a system for generating beautified documentation. This means that the documentation should be easily rendered in a professional and easy-to-read format.

You could opt to build your own system for managing API documentation, or you could use an existing package. A central theme throughout this book is learning to make good decisions regarding when it's a good idea to reinvent the wheel. In the case of inline documentation, the phpDocumentor project has done an excellent job of creating a tool that satisfies all our requirements, so there is little reason to look elsewhere. phpDocumentor is heavily inspired by JavaDoc, the automatic documentation system for Java.

Using phpDocumentor

phpDocumentor works by parsing special comments in code. The comment blocks all take this form:

/**
 * Short Description
 *
 * Long Description
 * @tags
 */

Short Description is a short (one-line) summary of the item described by the block. Long Description is an arbitrarily verbose text block. Long Description allows for HTML in the comments for specific formatting. tags is a list of phpDocumentor tags. The following are some important phpDocumentor tags:

Tag Description

 

@package [package name]

The package name

@author [author name]

The author information

@var [type]

The type for the var statement following the comment

@param [type [description]]

The type for the input parameters for the function following the block

@return [type [description]]

The type for the output of the function


You start the documentation by creating a header block for the file:

/**
 * This is an example page summary block
 *
 * This is a longer description where we can
 * list information in more detail.
 * @package Primes
 * @author George Schlossnagle
 */

This block should explain what the file is being used for, and it should set @package for the file. Unless @package is overridden in an individual class or function, it will be inherited by any other phpDocumentor blocks in the file.

Next, you write some documentation for a function. phpDocumentor tries its best to be smart, but it needs some help. A function's or class's documentation comment must immediately precede its declaration; otherwise, it will be applied to the intervening code instead. Note that the following example specifies @param for the one input parameter for the function, as well as @return to detail what the function returns:

/**
 * Determines whether a number is prime (stupidly)
 *
 * Determines whether a number is prime or not in
 * about the slowest way possible.
 * <code>
 * for($i=0; $i<100; $i++) {
 *   if(is_prime($i)) {
 *     print "$i is prime\n";
 *   }
 * }
 * </code>
 * @param integer
 * @return boolean true if prime, false elsewise
 */
function is_prime($num)
{
 for($i=2; $i<= (int)sqrt($num); $i++) {
   if($num % $i == 0) {
     return false;
   }
  }
  return true;
}
?>

This seems like a lot of work. Let's see what it has bought us. You can run phpDocumentor at this point, as follows:

phpdoc -f Primes.php -o HTML:frames:phpedit -t /Users/george/docs

Figure 1.3 shows the result of running this command.

Figure 1.3. phpdoc output for primes.php.

Documentation


For a slightly more complicated example, look at this basic Employee class:

<?php
/**
 * A simple class describing employees
 *
 * @package Employee
 * @author George Schlossnagle
 */

/**
 * An example of documenting a class
 */
class Employee
{
  /**
   * @var string
   */
  var $name;
  /**
   * The employees annual salary
   * @var number
   */
  var $salary;
  /**
   * @var number
   */
  var $employee_id;

  /**
   * The class constructor
   * @param number
   */
  function Employee($employee_id = false)
  {
    if($employee_id)  {
      $this->employee_id = $employee_id;
      $this->_fetchInfo();
    }
  }

  /**
   * Fetches info for employee
   *
   * @access private
   */
  function _fetchInfo()
  {
    $query = "SELECT name,
                     salary
              FROM employees
              WHERE employee_id = $this->employee_id";
    $result = mysql_query($query);
    list($this->name, $this->department_id) = mysql_fetch_row($result);
  }

  /**
   * Returns the monthly salary for the employee
   * @returns number Monthly salary in dollars
   */
  function monthlySalary()
  {
    return $this->salary/12;
  }
}
?>

Note that _fetchInfo is @access private, which means that it will not be rendered by phpdoc.

Figure 1.4 demonstrates that with just a bit of effort, it's easy to generate extremely professional documentation.

Figure 1.4. The phpdoc rendering for Employee.

Documentation



Previous
Table of Contents
Next