diff options
Diffstat (limited to 'upstream/mageia-cauldron/man1/perlmodstyle.1')
-rw-r--r-- | upstream/mageia-cauldron/man1/perlmodstyle.1 | 668 |
1 files changed, 668 insertions, 0 deletions
diff --git a/upstream/mageia-cauldron/man1/perlmodstyle.1 b/upstream/mageia-cauldron/man1/perlmodstyle.1 new file mode 100644 index 00000000..15616787 --- /dev/null +++ b/upstream/mageia-cauldron/man1/perlmodstyle.1 @@ -0,0 +1,668 @@ +.\" -*- mode: troff; coding: utf-8 -*- +.\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. +.ie n \{\ +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is >0, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{\ +. if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{\ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" ======================================================================== +.\" +.IX Title "PERLMODSTYLE 1" +.TH PERLMODSTYLE 1 2023-11-28 "perl v5.38.2" "Perl Programmers Reference Guide" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH NAME +perlmodstyle \- Perl module style guide +.SH INTRODUCTION +.IX Header "INTRODUCTION" +This document attempts to describe the Perl Community's "best practice" +for writing Perl modules. It extends the recommendations found in +perlstyle , which should be considered required reading +before reading this document. +.PP +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. +.PP +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. +.PP +This document differs from 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. +.PP +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. +.PP +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. +.SH "QUICK CHECKLIST" +.IX Header "QUICK CHECKLIST" +For more detail on each item in this checklist, see below. +.SS "Before you start" +.IX Subsection "Before you start" +.IP \(bu 4 +Don't re-invent the wheel +.IP \(bu 4 +Patch, extend or subclass an existing module where possible +.IP \(bu 4 +Do one thing and do it well +.IP \(bu 4 +Choose an appropriate name +.IP \(bu 4 +Get feedback before publishing +.SS "The API" +.IX Subsection "The API" +.IP \(bu 4 +API should be understandable by the average programmer +.IP \(bu 4 +Simple methods for simple tasks +.IP \(bu 4 +Separate functionality from output +.IP \(bu 4 +Consistent naming of subroutines or methods +.IP \(bu 4 +Use named parameters (a hash or hashref) when there are more than two +parameters +.SS Stability +.IX Subsection "Stability" +.IP \(bu 4 +Ensure your module works under \f(CW\*(C`use strict\*(C'\fR and \f(CW\*(C`\-w\*(C'\fR +.IP \(bu 4 +Stable modules should maintain backwards compatibility +.SS Documentation +.IX Subsection "Documentation" +.IP \(bu 4 +Write documentation in POD +.IP \(bu 4 +Document purpose, scope and target applications +.IP \(bu 4 +Document each publicly accessible method or subroutine, including params and return values +.IP \(bu 4 +Give examples of use in your documentation +.IP \(bu 4 +Provide a README file and perhaps also release notes, changelog, etc +.IP \(bu 4 +Provide links to further information (URL, email) +.SS "Release considerations" +.IX Subsection "Release considerations" +.IP \(bu 4 +Specify pre-requisites in Makefile.PL or Build.PL +.IP \(bu 4 +Specify Perl version requirements with \f(CW\*(C`use\*(C'\fR +.IP \(bu 4 +Include tests with your module +.IP \(bu 4 +Choose a sensible and consistent version numbering scheme (X.YY is the common Perl module numbering scheme) +.IP \(bu 4 +Increment the version number for every change, no matter how small +.IP \(bu 4 +Package the module using "make dist" +.IP \(bu 4 +Choose an appropriate license (GPL/Artistic is a good default) +.SH "BEFORE YOU START WRITING A MODULE" +.IX Header "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. +.SS "Has it been done before?" +.IX Subsection "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. +.PP +Good places to look for pre-existing modules include +MetaCPAN <https://metacpan.org> and asking on \f(CW\*(C`module\-authors@perl.org\*(C'\fR +(<https://lists.perl.org/list/module\-authors.html>). +.PP +If an existing module \fBalmost\fR does what you want, consider writing a +patch, writing a subclass, or otherwise extending the existing module +rather than rewriting it. +.SS "Do one thing and do it well" +.IX Subsection "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. +.PP +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? +.PP +Bad example: +.PP +"FooBar.pm provides an implementation of the FOO protocol and the +related BAR standard." +.PP +Good example: +.PP +"Foo.pm provides an implementation of the FOO protocol. Bar.pm +implements the related BAR protocol." +.PP +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. +.SS "What's in a name?" +.IX Subsection "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. +.PP +When naming your module, consider the following: +.IP \(bu 4 +Be descriptive (i.e. accurately describes the purpose of the module). +.IP \(bu 4 +Be consistent with existing modules. +.IP \(bu 4 +Reflect the functionality of the module, not the implementation. +.IP \(bu 4 +Avoid starting a new top-level hierarchy, especially if a suitable +hierarchy already exists under which you could place your module. +.SS "Get feedback before publishing" +.IX Subsection "Get feedback before publishing" +If you have never uploaded a module to CPAN before (and even if you have), +you are strongly encouraged to get feedback from 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, as are community sites like +Perl Monks <https://www.perlmonks.org>. +.SH "DESIGNING AND WRITING YOUR MODULE" +.IX Header "DESIGNING AND WRITING YOUR MODULE" +Considerations for module design and coding: +.SS "To OO or not to OO?" +.IX Subsection "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. +.PP +In \fIPerl Best Practices\fR (copyright 2004, Published by O'Reilly Media, Inc.), +Damian Conway provides a list of criteria to use when deciding if OO is the +right fit for your problem: +.IP \(bu 4 +The system being designed is large, or is likely to become large. +.IP \(bu 4 +The data can be aggregated into obvious structures, especially if +there's a large amount of data in each aggregate. +.IP \(bu 4 +The various types of data aggregate form a natural hierarchy that +facilitates the use of inheritance and polymorphism. +.IP \(bu 4 +You have a piece of data on which many different operations are +applied. +.IP \(bu 4 +You need to perform the same general operations on related types of +data, but with slight variations depending on the specific type of data +the operations are applied to. +.IP \(bu 4 +It's likely you'll have to add new data types later. +.IP \(bu 4 +The typical interactions between pieces of data are best represented by +operators. +.IP \(bu 4 +The implementation of individual components of the system is likely to +change over time. +.IP \(bu 4 +The system design is already object-oriented. +.IP \(bu 4 +Large numbers of other programmers will be using your code modules. +.PP +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. +.SS "Designing your API" +.IX Subsection "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: +.IP "Write simple routines to do simple things." 4 +.IX 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. +.IP "Separate functionality from output." 4 +.IX 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. +.Sp +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 +\&\f(CW\*(C`find(\e&wanted, $dir)\*(C'\fR syntax. +.IP "Provide sensible shortcuts and defaults." 4 +.IX 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. +.IP "Naming conventions" 4 +.IX Item "Naming conventions" +Your naming should be consistent. For instance, it's better to have: +.Sp +.Vb 3 +\& display_day(); +\& display_week(); +\& display_year(); +.Ve +.Sp +than +.Sp +.Vb 3 +\& display_day(); +\& week_display(); +\& show_year(); +.Ve +.Sp +This applies equally to method names, parameter names, and anything else +which is visible to the user (and most things that aren't!) +.IP "Parameter passing" 4 +.IX Item "Parameter passing" +Use named parameters. It's easier to use a hash like this: +.Sp +.Vb 5 +\& $obj\->do_something( +\& name => "wibble", +\& type => "text", +\& size => 1024, +\& ); +.Ve +.Sp +\&... than to have a long list of unnamed parameters like this: +.Sp +.Vb 1 +\& $obj\->do_something("wibble", "text", 1024); +.Ve +.Sp +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: +.Sp +.Vb 1 +\& $obj\->do_something(undef, undef, undef, undef, undef, 1024); +.Ve +.Sp +Provide sensible defaults for parameters which have them. Don't make +your users specify parameters which will almost always be the same. +.Sp +The issue of whether to pass the arguments in a hash or a hashref is +largely a matter of personal style. +.Sp +The use of hash keys starting with a hyphen (\f(CW\*(C`\-name\*(C'\fR) or entirely in +upper case (\f(CW\*(C`NAME\*(C'\fR) is a relic of older versions of Perl in which +ordinary lower case strings were not handled correctly by the \f(CW\*(C`=>\*(C'\fR +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! +.SS "Strictness and warnings" +.IX Subsection "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. +.SS "Backwards compatibility" +.IX Subsection "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. +.SS "Error handling and messages" +.IX Subsection "Error handling and messages" +When your module encounters an error it should do one or more of: +.IP \(bu 4 +Return an undefined value. +.IP \(bu 4 +set \f(CW$Module::errstr\fR or similar (\f(CW\*(C`errstr\*(C'\fR is a common name used by +DBI and other popular modules; if you choose something else, be sure to +document it clearly). +.IP \(bu 4 +\&\f(CWwarn()\fR or \f(CWcarp()\fR a message to STDERR. +.IP \(bu 4 +\&\f(CWcroak()\fR only when your module absolutely cannot figure out what to +do. (\f(CWcroak()\fR is a better version of \f(CWdie()\fR for use within +modules, which reports its errors from the perspective of the caller. +See Carp for details of \f(CWcroak()\fR, \f(CWcarp()\fR and other useful +routines.) +.IP \(bu 4 +As an alternative to the above, you may prefer to throw exceptions using +the Error module. +.PP +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. +.SH "DOCUMENTING YOUR MODULE" +.IX Header "DOCUMENTING YOUR MODULE" +.SS POD +.IX Subsection "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: +.IP \(bu 4 +A synopsis of the common uses of the module +.IP \(bu 4 +The purpose, scope and target applications of your module +.IP \(bu 4 +Use of each publicly accessible method or subroutine, including +parameters and return values +.IP \(bu 4 +Examples of use +.IP \(bu 4 +Sources of further information +.IP \(bu 4 +A contact email address for the author/maintainer +.PP +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 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. +.PP +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. +.PP +The recommended order of sections in Perl module documentation is: +.IP \(bu 4 +NAME +.IP \(bu 4 +SYNOPSIS +.IP \(bu 4 +DESCRIPTION +.IP \(bu 4 +One or more sections or subsections giving greater detail of available +methods and routines and any other relevant information. +.IP \(bu 4 +BUGS/CAVEATS/etc +.IP \(bu 4 +AUTHOR +.IP \(bu 4 +SEE ALSO +.IP \(bu 4 +COPYRIGHT and LICENSE +.PP +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). +.SS "README, INSTALL, release notes, changelogs" +.IX Subsection "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). +.PP +An INSTALL file should be included, and should contain simple installation +instructions. When using ExtUtils::MakeMaker this will usually be: +.IP "perl Makefile.PL" 4 +.IX Item "perl Makefile.PL" +.PD 0 +.IP make 4 +.IX Item "make" +.IP "make test" 4 +.IX Item "make test" +.IP "make install" 4 +.IX Item "make install" +.PD +.PP +When using Module::Build, this will usually be: +.IP "perl Build.PL" 4 +.IX Item "perl Build.PL" +.PD 0 +.IP "perl Build" 4 +.IX Item "perl Build" +.IP "perl Build test" 4 +.IX Item "perl Build test" +.IP "perl Build install" 4 +.IX Item "perl Build install" +.PD +.PP +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. +.PP +Unless you have good reasons for using some other format +(for example, a format used within your company), +the convention is to name your changelog file \f(CW\*(C`Changes\*(C'\fR, +and to follow the simple format described in CPAN::Changes::Spec. +.SH "RELEASE CONSIDERATIONS" +.IX Header "RELEASE CONSIDERATIONS" +.SS "Version numbering" +.IX Subsection "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. +.PP +The most common CPAN version numbering scheme looks like this: +.PP +.Vb 1 +\& 1.00, 1.10, 1.11, 1.20, 1.30, 1.31, 1.32 +.Ve +.PP +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 +.PP +.Vb 2 +\& perl \-MExtUtils::MakeMaker \-le \*(Aqprint MM\->parse_version(shift)\*(Aq \e +\& \*(AqFoo.pm\*(Aq +.Ve +.PP +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. If +you do this, the following idiom is recommended: +.PP +.Vb 5 +\& our $VERSION = "1.12_01"; # so CPAN distribution will have +\& # right filename +\& our $XS_VERSION = $VERSION; # only needed if you have XS code +\& $VERSION = eval $VERSION; # so "use Module 0.002" won\*(Aqt warn on +\& # underscore +.Ve +.PP +With that trick MakeMaker will only read the first line and thus read +the underscore, while the perl interpreter will evaluate the \f(CW$VERSION\fR +and convert the string into a number. Later operations that treat +\&\f(CW$VERSION\fR as a number will then be able to do so without provoking a +warning about \f(CW$VERSION\fR not being a number. +.PP +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. +.PP +Once picked, it is important to stick to your version scheme, without +reducing the number of digits. This is because "downstream" packagers, +such as the FreeBSD ports system, interpret the version numbers in +various ways. If you change the number of digits in your version scheme, +you can confuse these systems so they get the versions of your module +out of order, which is obviously bad. +.SS Pre-requisites +.IX Subsection "Pre-requisites" +Module authors should carefully consider whether to rely on other +modules, and which modules to rely on. +.PP +Most importantly, choose modules which are as stable as possible. In +order of preference: +.IP \(bu 4 +Core Perl modules +.IP \(bu 4 +Stable CPAN modules +.IP \(bu 4 +Unstable CPAN modules +.IP \(bu 4 +Modules not available from CPAN +.PP +Specify version requirements for other Perl modules in the +pre-requisites in your Makefile.PL or Build.PL. +.PP +Be sure to specify Perl version requirements both in Makefile.PL or +Build.PL and with \f(CW\*(C`require 5.6.1\*(C'\fR or similar. See the documentation on +\&\f(CW\*(C`use VERSION\*(C'\fR for details. +.SS Testing +.IX Subsection "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"). +For Module::Build you would use the \f(CW\*(C`make test\*(C'\fR equivalent \f(CW\*(C`perl Build test\*(C'\fR. +.PP +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. +.PP +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. +For more sophisticated test suites there are Test::More and Test::MockObject. +.SS Packaging +.IX Subsection "Packaging" +Modules should be packaged using one of the standard packaging tools. +Currently you have the choice between ExtUtils::MakeMaker and the +more platform independent Module::Build, allowing modules to be installed in a +consistent manner. +When using ExtUtils::MakeMaker, you can use "make dist" to create your +package. Tools exist to help you to build your module in a +MakeMaker-friendly style. These include ExtUtils::ModuleMaker and h2xs. +See also perlnewmod. +.SS Licensing +.IX Subsection "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). +.PP +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. +See perlgpl and perlartistic. +.SH "COMMON PITFALLS" +.IX Header "COMMON PITFALLS" +.SS "Reinventing the wheel" +.IX Subsection "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. +.SS "Trying to do too much" +.IX Subsection "Trying to do too much" +Your module will be part of a developer's toolkit. It will not, in +itself, form the \fBentire\fR toolkit. It's tempting to add extra features +until your code is a monolithic system rather than a set of modular +building blocks. +.SS "Inappropriate documentation" +.IX Subsection "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. +.PP +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 \f(CW\*(C`My::Module::Tutorial\*(C'\fR or +\&\f(CW\*(C`My::Module::FAQ\*(C'\fR and provide a link in the SEE ALSO section of the +main documentation. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +.IP perlstyle 4 +.IX Item "perlstyle" +General Perl style guide +.IP perlnewmod 4 +.IX Item "perlnewmod" +How to create a new module +.IP perlpod 4 +.IX Item "perlpod" +POD documentation +.IP podchecker 4 +.IX Item "podchecker" +Verifies your POD's correctness +.IP "Packaging Tools" 4 +.IX Item "Packaging Tools" +ExtUtils::MakeMaker, Module::Build +.IP "Testing tools" 4 +.IX Item "Testing tools" +Test::Simple, Test::Inline, Carp::Assert, Test::More, Test::MockObject +.IP <https://pause.perl.org/> 4 +.IX Item "<https://pause.perl.org/>" +Perl Authors Upload Server. Contains links to information for module +authors. +.IP "Any good book on software engineering" 4 +.IX Item "Any good book on software engineering" +.SH AUTHOR +.IX Header "AUTHOR" +Kirrily "Skud" Robert <skud@cpan.org> |