Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

José's Guide for creating Perl modules

by cog (Parson)
on Feb 16, 2005 at 19:35 UTC ( [id://431702]=perltutorial: print w/replies, xml ) Need Help??


NAME

José's Guide for creating Perl modules

SYNOPSIS

Follow this guide to create good Perl distributions

DESCRIPTION

From time to time, someone with little experience comes to me and asks: "I'd like to create a module. What do I do?"

In order to answer that question to as many people as possible at the same time, I decided to write this guide.

Before you start

Before creating a module, use CPAN Search to see if it already exists. If you don't find it at first, search for it under different names; search for its functionality, rather than the name you'd be giving it.

You should do this exhaustively so you don't waste your time duplicating effort.

If your search on CPAN doesn't satisfy you, you can also search Google. A lot of times, the right keywords are in the messages people post about the module but not in the documentation.

Just because a namespace exists doesn't mean you should abandon your module. See if it is any good, if it has everything you'd like it to have, and if it's being maintained. A good alternative is to contact the author and ask him what he thinks about it. Maybe he'll give you the namespace or you can also submit patches for the existing module.

If you need help with any of this, you can ask the PAUSE admins at modules@perl.org. They will gladly help you with that, and sometimes they even have different means to contact the person.

Picking a good name for your module

A module needs a good name that's intuitive, something that people search for, and describes the functionality it provides.

If you're having trouble deciding on a name for your module, send an e-mail to module-authors@perl.org and modules@perl.org. The readers can help you figure out a good name.

If you have a name you're not sure about, keep that name in your mind for a couple of days. If you don't think of anything better, it's probably a good name. If the name is really bad, you'll probably think of another one during this time.

Start your module

Sure, you can create your *.pm file, but don't forget the Makefile.PL, decent tests and the MANIFEST, along with META.yml and... wait a minute, you're not actually thinking of doing this all by yourself, are you?

As with several other tasks that people do on a daily basis, starting a module from scratch is a task that has been automated... several times! This means you have a range of module creation tools to help you.

h2xs

A simple execution of h2xs is enough to create a module; here's an example:

  h2xs -XAn My::New::Module

The resulting structure is something like this (depending on your version of h2xs).

. `-- My-New-Module |-- Changes |-- MANIFEST |-- Makefile.PL |-- README |-- lib | `-- My | `-- New | `-- Module.pm `-- t `-- My-New-Module.t

You're left with a directory with the name of your module, containing a Changes, MANIFEST, Makefile.PL, README, lib/ directory for your modules and a t/ directory for your tests. Not bad...

Without the -b switch, h2xs assumes your module requires your current version of Perl. If your module doesn't have any particular needs for that version, change that! I have been a victim of this in the past, with people sending me e-mails saying "Hey, your module requires Perl 5.8.4, but it would run in 5.6.0. Could you please change that?" Save yourselves that trouble and check that.

module-starter

The module-starter script from Module::Starter asks for a few more parameters to start with. Here's an example:

module-starter --module=My::New::Module --author="Me, Myself" \ --email=myself@cpan.org

Here's the resulting structure from this:

`-- My-New-Module |-- Changes |-- MANIFEST |-- Makefile.PL |-- README |-- lib | `-- My | `-- New | `-- Module.pm `-- t |-- 00.load.t |-- pod-coverage.t `-- pod.t

Looks pretty much the same as the result of h2xs, right? But don't let that fool you! Apart from the new files that test your POD documentation, the contents of those files are different from the ones generated with h2xs. Give a try to both systems and check out the differences.

Currently, I use module-starter to start my own modules.

ExtUtils::ModuleMaker

ExtUtils::ModuleMaker is another tool for creating modules. Using the command modulemaker you are taken throught a menu. The resulting structure would be something like this:

`-- My `-- New `-- Module |-- Changes |-- LICENSE |-- MANIFEST |-- Makefile.PL |-- README |-- Todo |-- lib | `-- My | `-- New | `-- Module.pm |-- scripts `-- t `-- 001_load.t

You can see some resemblances to the two other systems, right? Notice the Todo and LICENSE files, as well as the scripts directory.

Step by step: what to do

Document first

Now that you've created the skeleton of your module, you should move on to its guts, to its code, right?

Wrong!

My personal opinion is that you should always start by thinking about what you're doing. This will save time in the long run.

Start with the documentation. My experience tells me that coding gets much easier after you've documented every single one of your functions.

Before actually coding, write down the description of what every function in the module should do. This gives you a chance to figure out what you are doing.

I usually keep a list of modules I'd like to create. Rather than create them when I think about them, I take notes on them from time to time. When the right time comes, I use that list and pick one of the modules with the most notes. Then, I write the documentation.

Create tests

Make tests before your code. I usually make mine at the same time I'm coding. I code a function, write its tests and test it.

Tests find things your eye wouldn't catch. As your module evolves, things you left behind can suddenly break. Tests will warn you about them. You should test as much as you can. No test is a test too many.

Test for basic cases, but you should also test the extreme ones. Don't forget to test your functions with and without parameters, and even with parameters in excess, or wrong ones. You should know what those functions return in each of those cases.

You should also test your documentation, but module-starter will automatically create those tests for that, using Test::Pod::Coverage and Test::Pod.

Use strict

Use strict! "Strictures" can warn you about things that otherwise you'd be unaware of, like uninitialized variables and so on. Just put it at the top of all of your code files.

  use strict;

Use warnings

Warnings are good for your code and your sanity.

  use warnings;

Use warnings and strict at the very beginning of scripts or modules.

But there is a downside to using warnings, though: they're not backwards compatible! If your code uses warnings, it won't work with versions of Perl prior to 5.6. You can, however, use warnings while developing and remove them when releasing.

The latest version of Test::Harness turns on warnings while you test, so you might as well make your code warning free.

Exports

How it works
When you have a module, you probably have functions. When a user uses your module, he has to import your functions into his program.

You're the one who chooses what he's able to import (that is, you can choose not to let a particular function be imported) and how.

Here's an example, to make things easier:

require Exporter; our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( function_make function_remove activate_all deactivate_all ) ], 'action' => [ qw( function_make function_remove ) ], 'manipulation' => [ qw( activate_all deactivate_all ) ], ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( function1 );

Here's a brief explanation of what is going on in that code:

The last instruction (yes, we're starting by the end) states that whoever uses the module will always get function1. The user gets everything in the @EXPORT array automatically.

The %EXPORT_TAGS hash is kind of an 'alias maker'. In the example, the tag action is mapped into function_make and function_remove, manipulation is mapped into activate_all and deactivate_all, and all is mapped in the four functions. When using a module like this:

  use The::Module qw/:action/;

The current package is importing function_make and function_remove.

The @EXPORT_OK is also very important. Things that are not in the @EXPORT variable can only be imported if they are included in @EXPORT_OK.

In this particular example, it's OK to import any of the four functions comprised in the all tag. This means one can do something like this:

  use The::Module qw/:action activate_all/;

He will get function_make, function_remove, activate_all and function1 loaded in his package.

What to export
So now that you have a couple of functions / methods implemented, you should think on what to export...

If your module is purely object oriented, then you probably won't export anything.

However, if you have functions, you might feel a sudden urge to export some of them.

Don't!!!

Do not export functions just because. Instead, make them available to be exported, but let the user select what he wants to use (but don't forget to document the possibilities, of course).

Plus, people HATE changes in the API, so think deeply about it. By not exporting anything, your API will remain the same when you add new functionalities to your module.

So, instead of adding those functions to @EXPORT, try adding them to @EXPORT_OK.

Inside your distribution

Keep the Changes up to date
The Changes file is there for a reason, right? Keep it up to date! It will help users know what you have changed (and therefore choosing whether to download and install the new version or not); it will help you in case something gets broken from one version to the next one (because you'll know what you have changed); plus, you (and everybody else, for that matter) will be able to keep track of your work.
Don't forget the README
The README file is really important. Not everybody reads it, but they should. That's why it is named README; because you're supposed to READ IT!

Anyway, browsing a module on the CPAN, people will often look at the README, and if it isn't much, they will very likely take that as a sign that your module isn't really finished.

Both h2xs and module-starter create a standard README file, which you should change and add sections to as you feel the necessity for. I usually copy the POD documentation of my main module to it.

The MANIFEST
The MANIFEST file contains the list of all files to include in the distribution (and only those get into it).

Whenever you add an extra file, don't forget to include it on the MANIFEST file, or your distribution will be incomplete (and, probably, broken).

Makefile.PL
There is a file called Makefile.PL. By looking at it, you might think that you actually don't need to do anything to it; and that might be true, most of the times.

If you used h2xs, you should check its parameters. Otherwise, you should be fine.

However, there is one situation when you absolutely should update Makefile.PL: when you use other modules. That is, when your module has dependencies.

Just go there and add something like this:

PREREQ_PM => { 'Another::Module' => 0.01, },

That, for instance, states that your module depends on the existence of at least version 0.01 of Another::Module.

This makes life easier for everybody. The user who's downloading and installing your module automatically doesn't have to spend time figuring out the dependencies, for instance; and CPANPLUS will test your module correctly (hopefully).

When testing, Test::Prereq might be a good option to check whether there are any modules you should add to PREREQ_PM (see section "Make tests", down below).

Version numbers
Whenever you release a new version, change the version number in your module... and in the README... and be sure to include it in the Changes file too. It's really depressing when you upload a module and afterwards notice you got the version number wrong... (and it's even more depressing when you release the module again to get rid of that annoyance and you do it again).

Do not go from version 0.01 to 1.00 and then to 2.00, because that really looks bad and you'll be in version 20.00 in no time. Instead, go from 0.01 to 0.02, and from there to 0.03, and so on.

Also, there isn't really the necessity of going to 1.00 just from 0.99; people often change the integer part of the version (if one may call it the integer part, given that it is usually a string) when they do major changes in the design of the system, not when they run out of numbers.

Versions which are still being implemented usually have the current version number with an underscore and a number, like 0.04_01 and are called "developer releases"; the underscore makes it clear that the distribution is not yet ready for the general public. You should follow that practice. You can even upload a developer's release to the CPAN. When people look at your module they will see that version, with a red sign stating it's a developer's release and a link to the last ready-to-take version.

Almost done

Test it yourself
Before uploading your module, you should test it yourself. Use this to make your distribution:

  make dist

Suppose you had forgotten about including something in the MANIFEST, for instance. Just because your module passed all your tests in your specific directory doesn't mean it's working.

  make disttest

That should do it.

Before uploading

Check your distribution before you upload it.
  • Are the tests OK? Are they enough? Do they cover everything? Did I test after I last changed something?
  • Did I get the version number right in three different places?
  • Did I change the default documentation both on the module and on the README?
  • Are all files in the MANIFEST?
  • Did I include all the dependencies in Makefile.PL?

Uploading

The PAUSE is the Perl's Authors Uploading Server. In order to upload something to the CPAN, you need a PAUSE account. Get an account at PAUSE.

If you don't like the PAUSE web interface or you want to automate it, or find it boring or whatever, you can take a look at release and Module::Release, which are tools that automatically upload files to the CPAN and SourceForge.net.

Other good practices

Release early, release often

You don't have to wait until your module is completed to release it. "Release early, release often!" You'll be more motivated to do your work, people will be able to track your progress and might even give you some very important feedback on it.

Good style

In the CPAN, good coding style might be the difference between you receiving patches or not, or even between people actually using your modules or not (because some programmers are too suspicious and feel the urge to understand every little piece of code they use).

Read perlstyle and Perl::Tidy which show very good ways to tidy up your Perl code.

Source control

Keep your code under a source control system, such as CVS, Subversion, or Perforce. You get backups, version control and lots of other advantages. Others who want to help can also access it if you make it public.

Me got Kwalitee

The Kwalitee of your modules is not really Quality, but as close as possible as an automatic Quality-measurer can be.

The Kwalitee project examines distributions on the CPAN for good Perl coding practices, such as the use of strict, existence of tests, and so on. It assigns a score to each distribution, and therefore an average mean to the authors.

Strive for a high Kwalitee score is good for you, your modules, and its users. The higher Kwalitee you get, the bigger your ego becomes, and people consider your modules to be higher quality.

Other things you should know

CPAN Testers
One of the best things about the CPAN is that your releases are actually tested by other people.

As a module author, you don't have to bother about it; you simply upload your modules to the CPAN and wait to see if anything happens.

If your module's tests fail somewhere, you'll receive a report (actually, you're likely to receive quite a few, given that your module will probably fail on other systems too).

Don't take it too hard if you receive an email with a subject starting with "FAIL Your::Module". It's nothing personal! You screwed up, but it's no big deal, because thanks to the CPAN Testers you are now informed of the problem and you can easily (hopefully) correct it and release a new version.

There, no harm done.

Registering modules
Another thing you can do is to register the namespace of your module.

To do that, go to your PAUSE account and use the "Register namespace" option, which is pretty simple to use. You'll have to elaborate on how and why is your module important, but it's not that difficult, really.

When people look at your home node on CPAN Search (http://search.cpan.org/~yourusername), they will see all your modules and a list of the registered ones, along with some information on those.

A registered module was approved by PAUSE admins. Therefore, it's not simply a product of some delusional visionist with headaches and is probably something good, unless, of course, some PAUSE admin that day was a delusional visionist and had an headache.

So I have a module. Now what?

If you're thinking "Time for another one", hold your horses there, pal! Creating module after module really isn't that hard; the hard thing is to maintain them all and keep them useful. Loads of modules on their 0.01 versions that really don't do much and do have a list of "promises" don't do anyone much good, do they? Keep in mind that you should take all your modules to a stable version of them.

There's nothing wrong in having a bunch of modules you haven't completed yet, but there is something wrong in having a bunch of modules you will never complete.

Final words

That said, I hope you now know a bit more than when you started reading this document, and I hope it helps the Kwalitee... er... Quality of the CPAN modules around.

If you still have doubts (or maybe even more than when you started), there are lots of people willing to help (and of course I'm one of them).

Check out the modules@perl.org mailing list.

For anything else, I'm cog at cpan dot org.

SEE ALSO

Books

Links

Modules

Documentation

ACKNOWLEDGEMENTS

This guide was loosely based on brian's Guide to Solving Any Perl Problem (which you should read, too).

Alberto Simões and brian d foy made really good suggestions for sections to add to this document, as well as some changes to the existing ones.

AUTHOR

José Castro, cog at cpan dot org

COPYRIGHT

Copyright 2004, José Castro, Creative Commons license.

Replies are listed 'Best First'.
Re: José's Guide for creating Perl modules
by eyepopslikeamosquito (Archbishop) on Feb 17, 2005 at 07:38 UTC
      eyepopslikeamosquito said:
      Update: I expect TheDamian's upcoming book "Perl Best Practices" will have some sound advice on this subject.
      Indeed, TheDamian's book, or Perl Best Practices (PBP) has a whole chapter on modules (ch17, pg. 397). The first section in that chapter is on interface design.

      Update: There's an article that covers some of this by TheDamian called Ten Essential Development Practices.

      -- Ian Tegebo
Re: José's Guide for creating Perl modules
by Steve_p (Priest) on Feb 16, 2005 at 23:56 UTC
Re: José's Guide for creating Perl modules
by petdance (Parson) on Feb 17, 2005 at 05:48 UTC
    Very nice. Let this be the standard that all new module authors get pointed at.

    xoxo,
    Andy

Re: José's Guide for creating Perl modules
by toolic (Bishop) on Jul 14, 2010 at 17:22 UTC
    Another step I find useful "Before uploading" is to use pod2cpanhtml to get a glimpse of what my POD will look like on CPAN. It is as close as you're going to get to the real thing.

    Update: I noticed this useful piece of information on CPAN Ratings: "It is also possible to preview CPAN HTML using http://search.cpan.org/pod2html service, that allows uploading .pm files."

Re: José's Guide for creating Perl modules
by Anonymous Monk on Dec 02, 2015 at 14:16 UTC

    <quote>Start with the documentation. My experience tells me that coding gets much easier after you've documented every single one of your functions. </quote>

    After 50 years of programming, I could not agree more. Explain, both to yourself and others, what you are trying to achieve and the coding will be so much easier.

    The documentation also controls the writing of tests. You have to test what the code is *intended* to do, not what it actually does. Writing tests from the code only checks that the code does what it does, not what it was intended to do.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perltutorial [id://431702]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2024-03-19 05:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found