diff options
author | Kirrily Robert <skud@infotrope.net> | 2001-10-16 18:47:23 -0400 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2001-10-17 02:16:11 +0000 |
commit | f67486beba48c3146946f5320d63fa647944efb5 (patch) | |
tree | c1fc0c41c54c06412b01e77a7ffb3bf2ea50dfa5 /pod/perlmodstyle.pod | |
parent | f8e3975a62e432ae902df647b4ab74674d9b8f46 (diff) | |
download | perl-f67486beba48c3146946f5320d63fa647944efb5.tar.gz |
perlmodstyle as a patch
Message-ID: <20011016224723.A20673@infotrope.net>
p4raw-id: //depot/perl@12468
Diffstat (limited to 'pod/perlmodstyle.pod')
-rw-r--r-- | pod/perlmodstyle.pod | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/pod/perlmodstyle.pod b/pod/perlmodstyle.pod new file mode 100644 index 0000000000..4da7311f7a --- /dev/null +++ b/pod/perlmodstyle.pod @@ -0,0 +1,731 @@ +=head1 NAME + +perlmodstyle - Perl module style guide + +=head1 INTRODUCTION + +This document attempts to describe the Perl Community's "best practice" +for writing Perl modules. It extends the recommendations found in +L<perlstyle> , which should be considered required reading +before reading this document. + +While this document is intended to be useful to all module authors, it is +particularly aimed at authors who wish to publish their modules on CPAN. + +The focus is on elements of style which are visible to the users of a +module, rather than those parts which are only seen by the module's +developers. However, many of the guidelines presented in this document +can be extrapolated and applied successfully to a module's internals. + +This document differs from L<perlnewmod> in that it is a style guide +rather than a tutorial on creating CPAN modules. It provides a +checklist against which modules can be compared to determine whether +they conform to best practice, without necessarily describing in detail +how to achieve this. + +All the advice contained in this document has been gleaned from +extensive conversations with experienced CPAN authors and users. Every +piece of advice given here is the result of previous mistakes. This +information is here to help you avoid the same mistakes and the extra +work that would inevitably be required to fix them. + +The first section of this document provides an itemized checklist; +subsequent sections provide a more detailed discussion of the items on +the list. The final section, "Common Pitfalls", describes some of the +most popular mistakes made by CPAN authors. + +=head1 QUICK CHECKLIST + +For more detail on each item in this checklist, see below. + +=head2 Before you start + +=over 4 + +=item * + +Don't re-invent the wheel + +=item * + +Patch, extend or subclass an existing module where possible + +=item * + +Do one thing and do it well + +=item * + +Choose an appropriate name + +=back + +=head2 The API + +=over 4 + +=item * + +API should be understandable by the average programmer + +=item * + +Simple methods for simple tasks + +=item * + +Separate functionality from output + +=item * + +Consistent naming of subroutines or methods + +=item * + +Use named parameters (a hash or hashref) when there are more than two +parameters + +=back + +=head2 Stability + +=over 4 + +=item * + +Ensure your module works under C<use strict> and C<-w> + +=item * + +Stable modules should maintain backwards compatibility + +=back + +=head2 Documentation + +=over 4 + +=item * + +Write documentation in POD + +=item * + +Document purpose, scope and target applications + +=item * + +Document each publically accessible method or subroutine, including params and return values + +=item * + +Give examples of use in your documentation + +=item * + +Provide a README file and perhaps also release notes, changelog, etc + +=item * + +Provide links to further information (URL, email) + +=back + +=head2 Release considerations + +=over 4 + +=item * + +Specify pre-requisites in Makefile.PL + +=item * + +Specify Perl version requirements with C<use> + +=item * + +Include tests with your module + +=item * + +Choose a sensible and consistent version numbering scheme (X.YY is the common Perl module numbering scheme) + +=item * + +Increment the version number for every change, no matter how small + +=item * + +Package the module using "make dist" + +=item * + +Choose an appropriate license (GPL/Artistic is a good default) + +=back + +=head1 BEFORE YOU START WRITING A MODULE + +Try not to launch headlong into developing your module without spending +some time thinking first. A little forethought may save you a vast +amount of effort later on. + +=head2 Has it been done before? + +You may not even need to write the module. Check whether it's already +been done in Perl, and avoid re-inventing the wheel unless you have a +good reason. + +If an existing module B<almost> does what you want, consider writing a +patch, writing a subclass, or otherwise extending the existing module +rather than rewriting it. + +=head2 Do one thing and do it well + +At the risk of stating the obvious, modules are intended to be modular. +A Perl developer should be able to use modules to put together the +building blocks of their application. However, it's important that the +blocks are the right shape, and that the developer shouldn't have to use +a big block when all they need is a small one. + +Your module should have a clearly defined scope which is no longer than +a single sentence. Can your module be broken down into a family of +related modules? + +Bad example: + +"FooBar.pm provides an implementation of the FOO protocol and the +related BAR standard." + +Good example: + +"Foo.pm provides an implementation of the FOO protocol. Bar.pm +implements the related BAR protocol." + +This means that if a developer only needs a module for the BAR standard, +they should not be forced to install libraries for FOO as well. + +=head2 What's in a name? + +Make sure you choose an appropriate name for your module early on. This +will help people find and remember your module, and make programming +with your module more intuitive. + +When naming your module, consider the following: + +=over 4 + +=item * + +Be descriptive (i.e. accurately describes the purpose of the module). + +=item * + +Be consistent with existing modules. + +=item * + +Reflect the functionality of the module, not the implementation. + +=item * + +Avoid starting a new top-level hierarchy, especially if a suitable +hierarchy already exists under which you could place your module. + +=back + +You should contact modules@perl.org to ask them about your module name +before publishing your module. You should also try to ask people who +are already familiar with the module's application domain and the CPAN +naming system. Authors of similar modules, or modules with similar +names, may be a good place to start. + +=head1 DESIGNING AND WRITING YOUR MODULE + +Considerations for module design and coding: + +=head2 To OO or not to OO? + +Your module may be object oriented (OO) or not, or it may have both kinds +of interfaces available. There are pros and cons of each technique, which +should be considered when you design your API. + +According to Damian Conway, you should consider using OO: + +=over 4 + +=item * + +When the system is large or likely to become so + +=item * + +When the data is aggregated in obvious structures that will become objects + +=item * + +When the types of data form a natural hierarchy that can make use of inheritance + +=item * + +When operations on data vary according to data type (making +polymorphic invocation of methods feasible) + +=item * + +When it is likely that new data types may be later introduced +into the system, and will need to be handled by existing code + +=item * + +When interactions between data are best represented by +overloaded operators + +=item * + +When the implementation of system components is likely to +change over time (and hence should be encapsulated) + +=item * + +When the system design is itself object-oriented + +=item * + +When large amounts of client code will use the software (and +should be insulated from changes in its implementation) + +=item * + +When many separate operations will need to be applied to the +same set of data + +=back + +Think carefully about whether OO is appropriate for your module. +Gratuitous object orientation results in complex APIs which are +difficult for the average module user to understand or use. + +=head2 Designing your API + +Your interfaces should be understandable by an average Perl programmer. +The following guidelines may help you judge whether your API is +sufficiently straightforward: + +=over 4 + +=item Write simple routines to do simple things. + +It's better to have numerous simple routines than a few monolithic ones. +If your routine changes its behaviour significantly based on its +arguments, it's a sign that you should have two (or more) separate +routines. + +=item Separate functionality from output. + +Return your results in the most generic form possible and allow the user +to choose how to use them. The most generic form possible is usually a +Perl data structure which can then be used to generate a text report, +HTML, XML, a database query, or whatever else your users require. + +If your routine iterates through some kind of list (such as a list of +files, or records in a database) you may consider providing a callback +so that users can manipulate each element of the list in turn. +File::Find provides an example of this with its +C<find(\&wanted, $dir)> syntax. + +=item Provide sensible shortcuts and defaults. + +Don't require every module user to jump through the same hoops to achieve a +simple result. You can always include optional parameters or routines for +more complex or non-standard behaviour. If most of your users have to +type a few almost identical lines of code when they start using your +module, it's a sign that you should have made that behaviour a default. +Another good indicator that you should use defaults is if most of your +users call your routines with the same arguments. + +=item Naming conventions + +Your naming should be consistent. For instance, it's better to have: + + display_day(); + display_week(); + display_year(); + +than + + display_day(); + week_display(); + show_year(); + +This applies equally to method names, parameter names, and anything else +which is visible to the user (and most things that aren't!) + +=item Parameter passing + +Use named parameters. It's easier to use a hash like this: + + $obj->do_something( + name => "wibble", + type => "text", + size => 1024, + ); + +... than to have a long list of unnamed parameters like this: + + $obj->do_something("wibble", "text", 1024); + +While the list of arguments might work fine for one, two or even three +arguments, any more arguments become hard for the module user to +remember, and hard for the module author to manage. If you want to add +a new parameter you will have to add it to the end of the list for +backward compatibility, and this will probably make your list order +unintuitive. Also, if many elements may be undefined you may see the +following unattractive method calls: + + $obj->do_something(undef, undef, undef, undef, undef, undef, 1024); + +Provide sensible defaults for parameters which have them. Don't make +your users specify parameters which will almost always be the same. + +The issue of whether to pass the arguments in a hash or a hashref is +largely a matter of personal style. + +The use of hash keys starting with a hyphen (C<-name>) or entirely in +upper case (C<NAME>) is a relic of older versions of Perl in which +ordinary lower case strings were not handled correctly by the C<=E<gt>> +operator. While some modules retain uppercase or hyphenated argument +keys for historical reasons or as a matter of personal style, most new +modules should use simple lower case keys. Whatever you choose, be +consistent! + +=back + +=head2 Strictness and warnings + +Your module should run successfully under the strict pragma and should +run without generating any warnings. Your module should also handle +taint-checking where appropriate, though this can cause difficulties in +many cases. + +=head2 Backwards compatibility + +Modules which are "stable" should not break backwards compatibility +without at least a long transition phase and a major change in version +number. + +=head2 Error handling and messages + +When your module encounters an error it should do one or more of: + +=over 4 + +=item * + +Return an undefined value. + +=item * + +set C<$Module::errstr> or similar (C<errstr> is a common name used by +DBI and other popular modules; if you choose something else, be sure to +document it clearly). + +=item * + +C<warn()> or C<carp()> a message to STDERR. + +=item * + +C<croak()> only when your module absolutely cannot figure out what to +do. (C<croak()> is a better version of C<die()> for use within +modules, which reports its errors from the perspective of the caller. +See L<Carp> for details of C<croak()>, C<carp()> and other useful +routines.) + +=item * + +As an alternative to the above, you may prefer to throw exceptions using +the Error module. + +=back + +Configurable error handling can be very useful to your users. Consider +offering a choice of levels for warning and debug messages, an option to +send messages to a separate file, a way to specify an error-handling +routine, or other such features. Be sure to default all these options +to the commonest use. + +=head1 DOCUMENTING YOUR MODULE + +=head2 POD + +Your module should include documentation aimed at Perl developers. +You should use Perl's "plain old documentation" (POD) for your general +technical documentation, though you may wish to write additional +documentation (white papers, tutorials, etc) in some other format. +You need to cover the following subjects: + +=over 4 + +=item * + +A synopsis of the common uses of the module + +=item * + +The purpose, scope and target applications of your module + +=item * + +Use of each publically accessible method or subroutine, including +parameters and return values + +=item * + +Examples of use + +=item * + +Sources of further information + +=item * + +A contact email address for the author/maintainer + +=back + +The level of detail in Perl module documentation generally goes from +less detailed to more detailed. Your SYNOPSIS section should contain a +minimal example of use (perhaps as little as one line of code; skip the +unusual use cases or or anything not needed by most users); the +DESCRIPTION should describe your module in broad terms, generally in +just a few paragraphs; more detail of the module's routines or methods, +lengthy code examples, or other in-depth material should be given in +subsequent sections. + +Ideally, someone who's slightly familiar with your module should be able +to refresh their memory without hitting "page down". As your reader +continues through the document, they should receive a progressively +greater amount of knowledge. + +The recommended order of sections in Perl module documentation is: + +=over 4 + +=item * + +NAME + +=item * + +SYNOPSIS + +=item * + +DESCRIPTION + +=item * + +One or more sections or subsections giving greater detail of available +methods and routines and any other relevant information. + +=item * + +BUGS/CAVEATS/etc + +=item * + +AUTHOR + +=item * + +SEE ALSO + +=item * + +COPYRIGHT and LICENSE + +=back + +Keep your documentation near the code it documents ("inline" +documentation). Include POD for a given method right above that +method's subroutine. This makes it easier to keep the documentation up +to date, and avoids having to document each piece of code twice (once in +POD and once in comments). + +=head2 README, INSTALL, release notes, changelogs + +Your module should also include a README file describing the module and +giving pointers to further information (website, author email). + +An INSTALL file should be included, and should contain simple installation +instructions (usually "perl Makefile.PL; make; make install"). + +Release notes or changelogs should be produced for each release of your +software describing user-visible changes to your module, in terms +relevant to the user. + +=head1 RELEASE CONSIDERATIONS + +=head2 Version numbering + +Version numbers should indicate at least major and minor releases, and +possibly sub-minor releases. A major release is one in which most of +the functionality has changed, or in which major new functionality is +added. A minor release is one in which a small amount of functionality +has been added or changed. Sub-minor version numbers are usually used +for changes which do not affect functionality, such as documentation +patches. + +The most common CPAN version numbering scheme looks like this: + + 1.00, 1.10, 1.11, 1.20, 1.30, 1.31, 1.32 + +A correct CPAN version number is a floating point number with at least +2 digits after the decimal. You can test whether it conforms to CPAN by +using + + perl -MExtUtils::MakeMaker -le 'print MM->parse_version(shift)' 'Foo.pm' + +If you want to release a 'beta' or 'alpha' version of a module but don't +want CPAN.pm to list it as most recent use an '_' after the regular +version number followed by at least 2 digits, eg. 1.20_01 + +Never release anything (even a one-word documentation patch) without +incrementing the number. Even a one-word documentation patch should +result in a change in version at the sub-minor level. + +=head2 Pre-requisites + +Module authors should carefully consider whether to rely on other +modules, and which modules to rely on. + +Most importantly, choose modules which are as stable as possible. In +order of preference: + +=over 4 + +=item * + +Core Perl modules + +=item * + +Stable CPAN modules + +=item * + +Unstable CPAN modules + +=item * + +Modules not available from CPAN + +=back + +Specify version requirements for other Perl modules in the +pre-requisites in your Makefile.PL. + +Be sure to specify Perl version requirements both in Makefile.PL and +with C<require 5.6.1> or similar. + +=head2 Testing + +All modules should be tested before distribution (using "make disttest", +and the tests should also be available to people installing the modules +(using "make test"). + +The importance of these tests is proportional to the alleged stability of a +module -- a module which purports to be stable or which hopes to achieve wide +use should adhere to as strict a testing regime as possible. + +Useful modules to help you write tests (with minimum impact on your +development process or your time) include Test::Simple, Carp::Assert +and Test::Inline. + +=head2 Packaging + +Modules should be packaged using the standard MakeMaker tools, allowing +them to be installed in a consistent manner. Use "make dist" to create +your package. + +Tools exist to help you build your module in a MakeMaker-friendly style. +These include ExtUtils::ModuleMaker and h2xs. See also L<perlnewmod>. + +=head2 Licensing + +Make sure that your module has a license, and that the full text of it +is included in the distribution (unless it's a common one and the terms +of the license don't require you to include it). + +If you don't know what license to use, dual licensing under the GPL +and Artistic licenses (the same as Perl itself) is a good idea. + +=head1 COMMON PITFALLS + +=head2 Reinventing the wheel + +There are certain application spaces which are already very, very well +served by CPAN. One example is templating systems, another is date and +time modules, and there are many more. While it is a rite of passage to +write your own version of these things, please consider carefully +whether the Perl world really needs you to publish it. + +=head2 Trying to do too much + +Your module will be part of a developer's toolkit. It will not, in +itself, form the B<entire> toolkit. It's tempting to add extra features +until your code is a monolithic system rather than a set of modular +building blocks. + +=head2 Inappropriate documentation + +Don't fall into the trap of writing for the wrong audience. Your +primary audience is a reasonably experienced developer with at least +a moderate understanding of your module's application domain, who's just +downloaded your module and wants to start using it as quickly as possible. + +Tutorials, end-user documentation, research papers, FAQs etc are not +appropriate in a module's main documentation. If you really want to +write these, include them as sub-documents such as C<My::Module::Tutorial> or +C<My::Module::FAQ> and provide a link in the SEE ALSO section of the +main documentation. + +=head1 SEE ALSO + +=over 4 + +=item L<perlstyle> + +General Perl style guide + +=item L<perlnewmod> + +How to create a new module + +=item L<perlpod> + +POD documentation + +=item L<podchecker> + +Verifies your POD's correctness + +=item Testing tools + +L<Test::Simple>, L<Test::Inline>, L<Carp::Assert> + +=item http://pause.perl.org/ + +Perl Authors Upload Server. Contains links to information for module +authors. + +=item Any good book on software engineering + +=back + +=head1 AUTHOR + +Kirrily "Skud" Robert <skud@cpan.org> + |