Documentation
Every program describes how to accomplish some task in the language of mathematics and logic. While high level languages help us to express programming concepts easily and clearly, they are often not the best way to explain the abstract concepts involved. This is where programming documentation comes to the rescue. Documentation in the form of program comments interspersed in the source code are a means to explain in plain English the expected workings of a program and the high level concepts involved. They are a way to include information that is not obvious or clear in the programming statements themselves.
In this site we will use a standard block of comments at the beginning of each file to explain the purpose of the program in the file. We will include the program author, the date that the program was written and any updates that were made. This last use of comments to document the update history is one that should only be used for programs that are not under source code control. For complex multi-file programs a [[source code control system]] will be a necessity and will perform the task of managing the update history of files.
Basic comments are written on a single line. Such single-line comments begin with a hash symbol (#) and continue to the end of the current line. They can start at the beginning of the line or anywhere in the middle of a line. The following are examples of comments.
# This is a comment
Each program file, class or function/method should have a comment preceding it that describes the purpose and typical usage of the item being documented. Comments should document the high-level behavior and not get involved in the specifics of the current implementation. Implementation details can change but the interface described by the comment should rarely change. It also helps to know how the program, class or function/method is intended to perform when the code itself is found to have a bug. The following is an example of what a program file comment might look like.
###################################################################### # This program computes ... # # Copyright © 2023 Richard Lesh. All rights reserved. ######################################################################
Modern Perl Documentation
Modern Perl documentation has two layers:
- Human-facing guides: README, tutorials, architecture notes, examples
- API/reference docs: generated from source using POD-style documentation
What Should Be Documented
Modern Perl documentation should describe:
- the purpose of a package, module, subroutine, method, or constant
- object lifecycle expectations
- preconditions and postconditions
- error behavior
- context behavior when relevant (scalar, list, or void context)
- performance or complexity when relevant
- examples of use
This aligns better with how modern Perl libraries are read and maintained. Perl commonly uses a built-in documentation format called POD (Plain Old Documentation). POD is written directly in Perl source files and can be converted into HTML, man pages, text, and other formats automatically.
POD Documentation
POD uses directives such as =head1, =head2, =item, and =cut rather than Javadoc-style tags like @param and @return.
For example, documentation for a subroutine might look like this:
=head2 circle_area
Computes the area of a circle.
Uses the standard formula pi * r^2.
=over 4
=item * C<$radius> - radius of the circle in meters; must be non-negative
=item * Returns the area in square meters
=item * Dies with an exception if C<$radius> is negative
=back
=cut
sub circle_area {
my ($radius) = @_;
die "radius must be non-negative" if $radius < 0;
return 3.141592653589793 * $radius * $radius;
}
This is a typical POD documentation block. Unlike ordinary Perl comments beginning with #, POD is meant to be parsed by documentation tools and included in generated documentation output.
The documentation is typically placed immediately before the subroutine or package it describes so that readers can easily associate the prose with the code.
The heading line provides a short summary anchor for the documented subroutine.
Most documentation systems display this information in:
- subroutine lists
- section summaries
- quick navigation views
The summary should explain what the subroutine does, not how it works internally.
After the summary, you can include additional explanatory text.
This section may describe:
- the algorithm used
- important assumptions
- behavior that may not be obvious
POD treats this as the detailed description of the subroutine.
Because POD does not have a built-in @param tag, parameter documentation is usually written as a list or under a heading such as Arguments, Parameters, or Returns.
Good parameter documentation usually explains:
- the meaning of the parameter
- valid value ranges
- units of measurement (if relevant)
- any constraints or requirements
Each parameter should normally be documented clearly, especially in public modules and reusable libraries.
Return value documentation should explain what value the subroutine returns.
It should describe:
- what the returned value represents
- the units of the result if applicable
- whether the result differs in scalar versus list context
- any special values that might be returned
Even if the returned value seems obvious from the code, describing its meaning is helpful for readers.
Error behavior should document whether the subroutine:
- dies with an exception
- returns
undefon failure - sets
$@,$!, or other error indicators
This helps programmers understand the error conditions that must be handled when calling the subroutine.
Structured documentation like this serves several purposes:
- Readable source code documentation
- Automatically generated API reference manuals
- Improved IDE and editor assistance
- Clear documentation of interface contracts
Tools such as perldoc, pod2html, and Pod::Simple can scan POD and generate documentation directly from the source code.
Packages, modules, methods, constants, and even entire scripts can also have POD documentation. For example:
Package Example
package Account;
=head1 NAME
Account - Represents a bank account with a running balance
=head1 DESCRIPTION
Instances of this class are not thread-safe.
=cut
sub new {
my ($class) = @_;
return bless { balance => 0 }, $class;
}
=head2 deposit
Deposits money into the account.
=over 4
=item * C<$amount> - amount to deposit; must be positive
=back
=cut
sub deposit {
my ($self, $amount) = @_;
$self->{balance} += $amount;
}
=head2 balance
Returns the current balance.
=over 4
=item * Returns the current balance in dollars
=back
=cut
sub balance {
my ($self) = @_;
return $self->{balance};
}
Constant Example
use constant {
TASK_PENDING => 'pending',
TASK_RUNNING => 'running',
TASK_COMPLETE => 'complete',
TASK_FAILED => 'failed',
};
=head1 CONSTANTS
=over 4
=item * C<TASK_PENDING> - task has not started yet
=item * C<TASK_RUNNING> - task is currently executing
=item * C<TASK_COMPLETE> - task finished successfully
=item * C<TASK_FAILED> - task ended with an error
=back
=cut
Type-Like Data Structure Example
=head2 max_value
Returns the larger of two values.
=over 4
=item * C<$a> - first value
=item * C<$b> - second value
=item * Returns the larger of C<$a> and C<$b>
=back
=cut
sub max_value {
my ($a, $b) = @_;
return $a >= $b ? $a : $b;
}
Perl does not have generics in the same sense as Java, so documentation usually describes the expected kinds of values in prose rather than with generic type parameters.
POD also supports documenting entire modules using standard sections such as NAME, SYNOPSIS, DESCRIPTION, METHODS, FUNCTIONS, AUTHOR, and LICENSE.
Module Example
=head1 NAME
Math::Utils - Utility functions for common mathematical operations
=head1 SYNOPSIS
use Math::Utils qw(circle_area);
my $area = circle_area(10);
=head1 DESCRIPTION
This module provides simple mathematical helper functions.
=cut
Object Method Example
=head2 area
Computes the area of the shape.
=over 4
=item * Returns the area of the shape
=back
=cut
sub area {
my ($self) = @_;
...
}
Modern docs are much easier to learn from when each API item includes a short usage example.
=head2 to_upper
Converts a string to uppercase.
Example:
my $s = to_upper("Hello");
# $s eq "HELLO"
=over 4
=item * C<$text> - input text
=item * Returns an uppercase copy of the input text
=back
=cut
sub to_upper {
my ($text) = @_;
return uc($text);
}
In POD, indented text is typically rendered as preformatted text.
This makes it useful for showing code examples while preserving spacing and indentation.
Inline code fragments are usually written with C<...>, which renders the enclosed text in a code-style font.
Combined, these techniques make it safer and cleaner for showing program code in documentation.
Generating Documentation with POD
Once your Perl code contains POD documentation, you can automatically generate browsable or readable documentation in several formats.
View Documentation with perldoc
If Perl is installed, the perldoc tool is usually available.
Linux and
Raspberry Pi
macOS
Windows
This displays the documentation in a terminal-friendly format.
Generate HTML Documentation
You can also generate HTML documentation from POD.
Linux and
Raspberry Pi
macOS
Windows
This converts the POD in the Perl source file into an HTML page.
Document Installed Modules
You can also view documentation for installed Perl modules by module name. For example:
This tells perldoc to find and display the documentation for the installed module.
View the Generated Documentation
If you generated HTML output, open the resulting HTML file in a web browser to browse your module’s API documentation.
References
- [[Perl Language Reference]]
- [[Comprehensive Perl Archive Network (CPAN)]]
- [[Beginning Perl]], Simon Cozens
- [[Perl Monks Tutorials]]
Pure Programmer

