100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Writing Your Own Module

Build, structure, document, test, and package a distributable Perl module from scratch, from the initial .pm file to a CPAN-ready distribution.

Modules & OOPIntermediate10 min readJul 10, 2026
Analogies

Anatomy of a Module File

A minimal, well-formed module starts with 'package MyApp::Greeter;' to establish its namespace, followed by 'use strict; use warnings;' to catch common mistakes, a version declaration like 'our $VERSION = "0.01";', the module's actual subroutines or class definition, and a mandatory final '1;' at the end of the file — because 'require'/'use' evaluate the file as an expression and expect a true value to signal successful loading, a module ending in anything falsy (or nothing) will fail to load with a cryptic error. Exporting functions for procedural (non-OO) modules is handled through 'Exporter': 'use Exporter "import"; our @EXPORT_OK = ("greet");' lets a caller write 'use MyApp::Greeter qw(greet);' to selectively pull in just the greet() function rather than polluting their namespace with everything.

🏏

Cricket analogy: A match only counts as officially completed once the umpires sign the final scorecard confirming the result, just as a Perl module only loads successfully once the file ends in a final truthy '1;' confirming successful evaluation.

perl
package MyApp::Greeter;
use strict;
use warnings;
use Exporter 'import';

our $VERSION   = '0.01';
our @EXPORT_OK = ('greet');

sub greet {
    my (%args) = @_;
    my $name = $args{name} // 'World';
    return "Hello, $name!";
}

1;   # mandatory truthy return value

__END__

=head1 NAME

MyApp::Greeter - Simple greeting utility

=head1 SYNOPSIS

    use MyApp::Greeter qw(greet);
    print greet(name => 'Priya'), "\n";

=cut

Documenting with POD

Perl's built-in documentation format, POD (Plain Old Documentation), is embedded directly in the .pm file between markers like '=head1 NAME' and '=cut', and it's what tools like 'perldoc MyApp::Greeter' and CPAN's metacpan.org render into readable documentation pages. Standard sections every published module should include are NAME (module name plus a one-line description), SYNOPSIS (a short, copy-pasteable usage example), DESCRIPTION (a fuller explanation), and a METHODS or FUNCTIONS section documenting each public interface with its parameters and return value. Because POD is plain text interleaved with code, it's common (and good practice) to place it after the '__END__' token so the Perl compiler stops parsing the file as code at that point and treats everything after purely as documentation, keeping runtime parsing fast.

🏏

Cricket analogy: A player's official BCCI profile page listing their stats, playing style, and career summary in one standardized format is like a module's POD sections (NAME, SYNOPSIS, DESCRIPTION) giving a standardized documentation view.

Testing with Test::More

Every serious module ships with a 't/' directory of test scripts written against Test::More, Perl's standard testing library, where each test file typically ends in .t and is run automatically by 'prove -l t/' or 'make test'. A basic test file starts with 'use Test::More;' (or 'use Test::More tests => 3;' to declare an expected count), then uses assertion functions like 'is($got, $expected, "description");', 'ok($condition, "description");', and 'like($string, qr/pattern/, "description");' to verify behavior, finishing with 'done_testing();' if you didn't declare a fixed test count upfront. Writing tests before publishing isn't just good practice — CPAN Testers will actually run your distribution's test suite across dozens of OS/Perl-version combinations after you upload it, and a module with a thin or broken test suite quickly earns a reputation for unreliable releases.

🏏

Cricket analogy: A bowler doing a formal fitness and action assessment before being cleared to play internationally is like running 't/' tests via 'prove -l t/' before a module is cleared for release.

'perl -c MyModule.pm' performs a syntax-only check (compiles but doesn't run the module), which is a fast sanity check to run before invoking the full test suite, especially useful in a pre-commit hook.

Packaging for Distribution

To share a module beyond your own machine, you package it as a CPAN distribution using a build tool like Module::Build, ExtUtils::MakeMaker, or the more modern Dist::Zilla, each of which generates a standard directory layout (lib/, t/, README, Changes, META.json) and a manifest describing dependencies, so 'cpanm .' or 'perl Makefile.PL && make && make test && make install' works the same way for your module as it does for any module you download from CPAN. The META.json (or META.yml) file declares runtime and test dependencies with version requirements, which is what lets cpanm automatically install your module's prerequisites before attempting to build it. Once packaged, uploading to CPAN (via a PAUSE account) makes the module installable worldwide with a single 'cpanm YourNamespace::YourModule' command, and CPAN Testers begins automatically validating it across the Perl ecosystem within hours of upload.

🏏

Cricket analogy: A domestic player getting formally registered with the ICC so any country's franchise can sign them through a standardized process is like uploading a module to CPAN via PAUSE so anyone worldwide can 'cpanm' install it.

Choose your module's namespace carefully before uploading to CPAN — PAUSE permissions are first-come, first-served per top-level namespace, and reclaiming or renaming a published distribution after others depend on it is disruptive; search MetaCPAN first to confirm the name isn't already taken and doesn't collide with an existing well-known distribution.

  • Every module file needs 'package', 'use strict; use warnings;', and a mandatory trailing truthy statement (usually '1;').
  • Exporter with @EXPORT_OK lets consumers selectively import specific functions instead of polluting their namespace.
  • POD documentation (NAME, SYNOPSIS, DESCRIPTION, METHODS) placed after __END__ powers perldoc and MetaCPAN pages.
  • Test::More in a t/ directory, run via 'prove -l t/', is the standard way to verify module behavior before release.
  • 'perl -c Module.pm' gives a fast syntax-only sanity check before running the full test suite.
  • Dist::Zilla, Module::Build, or ExtUtils::MakeMaker package a module into a standard CPAN distribution layout with META.json.
  • Uploading via PAUSE makes a module installable worldwide with 'cpanm Namespace::Module', triggering automatic CPAN Testers validation.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#PerlStudyNotes#WritingYourOwnModule#Writing#Own#Module#Anatomy#StudyNotes#SkillVeris#ExamPrep