perlmodstyle - Perl モジュールスタイルガイド
このドキュメントは Perl コミュニティにおける Perl モジュールを書くときの「ベストプラクティス」を 説明しています。 これは perlstyle にある推奨項目を拡張します; perlstyle はこのドキュメントに先立って目を通しておいてください。
このドキュメントは全てのモジュール作者に役立つように 意図していますが、CPAN にモジュールを公開しようと している作者を特に意図しています。
焦点は、モジュール開発者の目にとまる点ではなく、 モジュールのユーザの目にとまるスタイルの要素に置かれています。 しかし、このドキュメントであげられているガイドラインの 多くはモジュールの内部にも推測、適用できるでしょう。
perlnewmod は CPAN モジュールを作るためのチュートリアルであるのに対し、 この文書はスタイルに関するガイドという点で異なっています。 それはモジュールがベストプラクティスに沿っているかを これを成し遂げる方法を詳細に記述する必要なしに 決定するために比較するためのチェックリストを 提供しています。
このドキュメントに含まれる全てのアドバイスは 経験に富んだ CPAN 作者及びユーザの広範囲にわたる 議論から少しずつ集められています。 ここにあるアドバイスのどの欠片も以前の過ちの解決として 生まれました。 この情報は同じ過ちを繰り返さないように、 そして必然的にそれらを修正するという余計な作業が 必要とならないように、あなたを手助けするために ここにあります。
このドキュメントの最初のセクションでは項目別のチェックリストを 提供します; その後のセクションではリストの各項目について より詳しい説明を行います。 そして最後のセクション、「よくある落とし穴」で CPAN 作者が よくやってしまう、特にメジャーな失敗をいくつか説明します。
このチェックリストにおける各項目の詳細は後のセクションを 参照してください。
車輪の再発明をしない
可能であるのなら既存のモジュールにパッチ、拡張、 サブクラス化を行う
一つのことをうまくやる
ふさわしい名前を選ぶ
公開する前にフィードバックを得る
API は平均的なプログラマが理解できるようにするべき
簡単なタスクのための簡単なメソッドを
機能を出力から分離する
関数やメソッドには一貫性のある名前を付ける
二つ以上の引数ををとるのなら 名前付きの引数(ハッシュまたはハッシュリファレンス)を使う
use strict
及び -w
の環境下で動作することを 保証する
安定したモジュールは後方互換性を維持するべき
文書を POD 形式で書く
目的、範囲、及び対象となるアプリケーションを記述する
個々の公開されているアクセスメソッドまたは関数を、 引数及び返り値も含めて記述する
文書に使い方を例示する
README ファイルを提供する; またできればリリースノート、更新履歴も
さらなる情報へのリンク(URL, email)を提供する
Makefile.PL または Build.PL に依存(pre-requisites)を記述する
動作に必要な Perl のバージョンを use
で記述する
モジュールにはテストを含める
バージョン番号の採番には一般的で矛盾の起きない形式を選ぶ (Perl モジュールでは一般的に X.YY が使われている)
たとえそれがどんなに小さな変更であっても、変更毎にバージョン番号を増やす
モジュールのパッケージングには "make dist" を使う
適切なライセンスを選ぶ (GPL/Artistic はよいデフォルトです)
最初に少し考える時間を取らずにモジュール開発に取りかかろうとしないで ください。 予め少し考えておくことで、後での多くの苦労を防げます。
そもそもモジュールを書く必要がないかもしれません。 既に Perl で行われているかどうかを調べて、よい理由がない限り 車輪の再発明は避けてください。
既にあるモジュールを探すのによい場所は、 MetaCPAN および PrePAN と、 module-authors@perl.org
(https://lists.perl.org/list/module-authors.html) に聞くことです。
もし既にあるモジュールがやりたいことを ほとんど しているなら、 それを書き直すのではなく、パッチを作ったり、派生クラスを作ったり、 あるいは既にあるモジュールを拡張するためのその他の手段を考慮してください。
当たり前のことを述べるという危険を冒しますが、モジュールはモジュール式で あることを目的としています。 Perl 開発者は、自身のアプリケーションの建築ブロックを寄せ集めるために モジュールを使えるようにするべきです。 しかし、ブロックが正しい形をしていて、開発者が小さいブロックが必要な だけのときに大きいブロックを使う必要がないようにすることが重要です。
モジュールは、一文だけで表現できる明確に定義されたスコープを持つべきです。 あなたのモジュールは関係するモジュール群に分割できませんか?
悪い例:
「FooBar.pm は、FOO プロトコルと、関連する BAR 標準の実装を提供します。」
良い例:
「Foo.pm は FOO プロトコルの実装を提供します。 Bar.pm は関連する BAR プロトコルを実装します。」
これは、もし開発者が BAR 標準のモジュールだけを必要としているなら、 FOO ライブラリのインストールを強制されないということです。
前もって、モジュールのための適切な名前を選んでください。 これは人々がモジュールを探したり覚えたりする助けになり、モジュールを 使ったプログラミングがより直観的になります。
モジュールに名前を付けるときには、以下のことを考慮してください:
説明的にする (モジュールの目的を正確に表現する)。
すでにあるモジュールと一貫性をもつ。
モジュールの実装ではなく、モジュールの機能を反映させる。
新しいトップレベル階層を作るのを避ける(特にモジュールを置くのに 適切な階層がすでにある場合は)。
もし過去に CPAN にモジュールをアップロードしたことがないなら(そしてたとえ したことがあっても)、PrePAN でフィードバックを 得ることが強く推奨されます。 PrePAN は CPAN モジュールのアイデアを他の Perl 開発者と議論することに特化した サイトで、新しい (そして経験のある) Perl 開発者にとって素晴らしい リソースです。
また、すでにモジュールのアプリケーションドメインと CPAN 命名システムに 親しんでいる人々からフィードバックを得ようとするべきです。 同様なモジュールの作者や、似た名前のモジュールは始めるのに いいところでしょう; また Perl Monks のような コミュニティサイトもよいです。
モジュールの設計とコーディングで考慮すること:
モジュールはオブジェクト指向 (OO) にするかしないか、あるいは両方の インターフェースを持つようにもできます。 それぞれの技術には、API を設計するときに検討するべき メリットデメリットがあります。
Perl ベストプラクティス(Perl Best Practices>) (2004 年、 オライリーメディアによって出版)で、Damian Conway は OO が問題を解決するのに 向いているかを判断するときに使う基準の一覧を提供しています:
システムが大きかったり大きくなりそう。
データが、オブジェクトになるよくある構造に集約される; 特にそれぞれの集約が 大量のデータである。
データ形式が継承や多態性を容易にするような自然な階層を形成している。
様々な異なる操作が行われるデータがある。
データの型に関係する同じ一般的な操作をする必要があるけれども、操作を 適用するデータの型によって少しずつ異なる。
後で新しいデータ型を追加する必要がありそう。
データとの典型的な相互作用が演算子によって最もよく表現される。
システムの個々の要素の実装が後でやがて変更になりそう。
システム設計自身が既にオブジェクト指向である。
大量のクライアントコードがこのソフトウェアを使う (そして実装から変更を 分離しておくべき) とき
あなたのモジュールに OO が適切かどうかを慎重に考えてください。 不必要なオブジェクト指向は、平均的なモジュール利用者が理解や使用するのが 困難な複雑な API となります。
インターフェースは平均的な Perl プログラマが理解可能であるべきです。 以下のガイドラインは、API が充分に簡単かどうかを判断する手助けに なるでしょう:
少量の巨大なルーチンよりも、たくさんの単純なルーチンの方がよいです。 ルーチンが引数によって大きく振る舞いを変えるなら、複数のルーチンに 分割するべきと言うサインです。
結果は出来るだけ一般的な形式で返して、ユーザがそれをどのように使うかを 選択できるようにします。 最も一般的な形式とは、おそらく後でテキストレポート、HTML、XML、 データベースクエリ、あるいはユーザが求めるもの何でも生成できる Perl データ構造です。
あなたのルーチンがある種のリスト(ファイルのリスト、データベースの レコードなど)に対して反復するなら、ユーザがリストのそれぞれの要素を 操作できるようなコールバックを提供することを考慮してください。 File::Find は find(\&wanted, $dir)
という文法で、この場合の例を 提供しています。
単純な結果を得るために全てのモジュールユーザに同じ輪をくぐることを 要求しないようにしてください。 より複雑だったり標準でない振る舞いのためには、常にオプションの引数や ルーチンを用意して管浅い。 もしほとんどのユーザがモジュールを使い始めるときにほとんど同じ 数行のコードを書く必要があるなら、それはその振る舞いをデフォルトに するべきというサインです。 デフォルトを使うべきというもう一つの指標は、ユーザのほとんどが同じ引数で ルーチンを呼び出すときです。
命名は一貫性を持たせるべきです。 例えば、以下のものは:
display_day();
display_week();
display_year();
以下のものよりよいです:
display_day();
week_display();
show_year();
これはメソッド名、引数名、その他ユーザに見えるもの何にでも (そして見えない物のほとんどにも!)適用されます。
名前付き引数を使いましょう。 これは以下のようにハッシュを使えば:
$obj->do_something(
name => "wibble",
type => "text",
size => 1024,
);
…以下のように名前のない引数の長いリストより簡単です:
$obj->do_something("wibble", "text", 1024);
引数のリストは 1 引数、2 引数、そして 3 引数でもうまく動作するでしょうが、 それ以上になるとモジュールユーザが覚えるのが難しくなり、モジュール 作者が管理するのも難しくなります。 新しい引数を追加したいときは、後方互換性のためにリストの最後に追加する 必要があり、そしてこれによっておそらくリストの順序が直観的では なくなるでしょう。 また、多くの要素が未定義の場合、以下のような美しくないメソッド呼び出しを 見ることになるでしょう:
$obj->do_something(undef, undef, undef, undef, undef, 1024);
引数に、意味のあるデフォルトがあるならそれをデフォルトにしましょう。 ユーザーに、毎回ほとんど同じような引数を指定させてはいけません。
引数をハッシュで渡すかハッシュリファレンスで渡すかの問題は主に個人的な スタイルの問題です。
ハイフンで始まるハッシュキー (-name
) や全て大文字のハッシュキー (NAME
) は、普通の小文字の文字列が =>
演算子で扱えなかった 古いバージョンの Perl の遺物です。 一部のモジュールでは歴史的な理由や個人的なスタイルの問題で大文字や ハイフン付きのキーのままですが、ほとんどの新しいモジュールは単純な 小文字のキーを使うべきです。 どちらを選ぶにせよ、一貫性を持ちましょう!
モジュールは stirct プラグマ付きでも正しく動作し、一切の警告なしで 動作するべきです。 また、適切な場所では汚染チェックも扱うべきですが、これは多くの場合で困難を 伴います。
「安定版の」モジュールは、少なくとも長い移行フェーズとバージョン番号の メジャー番号の変更することなく、後方互換性を壊すべきではありません。
モジュールがエラーに遭遇した場合、以下の一つあるいは複数を行うべきです:
未定義値を返す。
$Module::errstr
あるいは同様のものを設定する (errstr
は DBI および その他の有名なモジュールで使われている一般的な名前です; もし他のものを 選んだなら、それを明確に文書化しておきましょう)。
warn()
や carp()
を使ってメッセージを STDERR に出力する。
croak()
は、あなたのモジュールが何をすればいいのか全く分からないときにのみ 使います。 (croak()
はモジュール内で使うための die()
の改良版で、 エラーを呼び出し元の観点から報告します。 croak()
, carp()
およびその他の便利なルーチンについては Carp を参照してください。)
上述の代替案として、Error モジュールを使って例外を投げる方を 好むかもしれません。
設定可能なエラー処理はユーザーにとってとても便利です。 警告やデバッグメッセージのレベルの選択、メッセージの別のファイルへの書き出し、 エラー処理ルーチンの指定方法、あるいはその他の同様の機能の提供を 考慮してください。 これらのオプション全てのデフォルトは最も一般的な使用法に設定してください。
モジュールは Perl の開発者向けの文書を含めるべきです。 一般的な技術文書に対しては Perl の "plain old documentation" (POD) を 使うべきですが、追加の文書 (ホワイトペーパー、チュートリアルなど) は その他のフォーマットで書きたいかもしれません。 以下のような主題に対応する必要があります:
モジュールの一般的な使い方の概要
モジュールの目的、スコープ、対象アプリケーション
(引数と返り値を含む) 公開されているメソッドやサブルーチンの使用法
使用例
さらなる情報の情報源
作者/メンテナへ連絡するための email アドレス
Perl モジュール文書の詳細度は、一般的に概略から詳細へという順序に なっています。 SYNOPSIS 節には使うための最小限の例を含むべきです (おそらくは一行でしょう; 一般的でない使い方やほとんどのユーザーにとって 必要でないものは省略します); DESCRIPTION はモジュールを広義で記述し、一般的には単に数段落です; モジュールのルーチンやメソッドに関する更なる詳細、長いコード例、その他の より深い内容は引き続く節に書くべきです。
理想的には、モジュールに対して少しなじみのあるユーザーなら "page down" キーを 押すことなく記憶を思い出せるようにするべきです。 読者が文書を読み進めるにつれて、徐々に多くの量の知識を受け取ります。
推奨する Perl モジュール文書の章の順序は:
NAME
SYNOPSIS
DESCRIPTION
利用可能なメソッドやルーチンのより詳細と、その他の関係する情報のための 一つまたは複数の節。
BUGS/CAVEATS など
AUTHOR
SEE ALSO
COPYRIGHT と LICENSE
文書は、記述しているコードの近くになるように(「インライン」文書) 維持してください。 メソッドのための POD はメソッドのサブルーチンの直前に書いてください。 これにより文書を最新に保つのが容易になり、一つのコードに対して 2 箇所 (POD とコメント) に書く必要がなくなります。
モジュールには、モジュールの説明と、さらなる情報へのポインタ (ウェブサイト、 作者への email) を記述した README ファイルも含めるべきです。
INSTALL ファイルを含めて、そこに簡単なインストール手順を記述するべきです。 ExtUtils::MakeMaker を使っているなら、これは普通は以下のようになります:
Module::Build を使っているなら、これは普通は以下のようになります:
リリースノートまたは changelogs は、ユーザーからの観点でモジュールの ユーザーから見える変更点を記述して、リリース毎に作成するべきです。
他の形式を使う良い理由 (例えば、会社で使われている形式) がない限り、 変更履歴ファイルは Changes
という名前にして、CPAN::Changes::Spec に ある単純な形式に従うのが慣習です。
バージョン番号は少なくともメジャーリリースとマイナーリリース、そして 場合により副マイナーリリースを示すべきです。 メジャーリリースは、主な機能の変更や、あるいは主な新機能が 追加です。 マイナーリリースは機能の一部の追加や修正です。 副マイナーバージョン番号は普通、文書パッチのような機能に影響を与えない 変更に使われます。
最も一般的な CPAN のバージョン番号付け方式は次のようなものです:
1.00, 1.10, 1.11, 1.20, 1.30, 1.31, 1.32
正しい CPAN バージョン番号は、小数点の後に少なくとも 2 桁の数字がある 浮動小数点数です。 CPAN に準拠しているかどうかは以下のようにしてテストできます
perl -MExtUtils::MakeMaker -le 'print MM->parse_version(shift)' \
'Foo.pm'
「ベータ」あるいは「アルファ」バージョンのモジュールをリリースしたいけれども CPAN.pm に最新版として扱ってほしくない場合、通常のバージョン番号の 後に '_' を使い、引き続いて最低 2 桁の数字を付けます; 例えば 1.20_01。 こうするなら、以下の慣用句が推奨されます:
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't warn on
# underscore
この小技を使うと、MakeMaker は最初の行だけを読むので下線付きで読み、 一方 perl インタプリタは $VERSION を eval して文字列を数値に変換します。 これにより、後の操作で $VERSION を数値として扱うものがあっても $VERSION が数値でないという警告が出なくなります。
(たとえ 1 文字の文書パッチでも)バージョン番号を増やすことなく何かを リリースしてはいけません。 1 文字の文書パッチであっても副マイナー番号を変更するべきです。
一旦選択したら、数字の数を減らすことなく、そのバージョンスキームに こだわることは重要です。 これは、FreeBSD port システムのような「下流」パッケージ作成者は バージョン番号を様々な方法で解釈するからです。 バージョンスキームで数字の数を変えると、これらのシステムが混乱して、 モジュールのバージョンの順番が間違ったことになるかもしれません; 明らかに これは悪いことです。
モジュール作者は、他のモジュールに依存するかどうか、どのモジュールに 依存するかについて注意深く考慮するべきです。
もっとも重要なこととして、できるだけ安定しているモジュールを選んでください。 優先順位としては:
コア Perl モジュール
安定している CPAN モジュール
不安定な CPAN モジュール
CPAN から利用できないモジュール
Makefile.PL か Build.PL の pre-requisites に、他の Perl モジュールの 必要バージョンを指定します。
Makefile.PL や Build.PL と、require 5.6.1
のような形の両方で、 Perl の必要バージョンを指定します。 詳しくは "require" in perlfunc の use VERSION
の節を参照してください。
全てのモジュールは配布する前に ("make disttest" を使って) テストされるべきですし、テストはモジュールをインストールしようとしている 人々によっても ("make test" を使って) 実行可能であるべきです。 Module::Build の場合は make test
の等価物である perl Build test
を 使います。
これらのテストの重要性はモジュールの安定性に比例します。 安定していると表明したり、広く使われることを望むモジュールは、できるだけ 厳密なテスト体制に固執するべきです。
(開発プロセスや時間に与える影響を最小限にするように) テストを書くのを助ける モジュールには Test::Simple, Carp::Assert, Test::Inline などがあります。 さらに洗練されたテストスイートは Test::More と Test::MockObject です。
モジュールは標準パッケージツールの一つを使ってパッケージ化されるべきです。 現在のところ ExtUtils::MakeMaker と、よりプラットフォーム非依存で モジュールを一貫した方法でインストール出来る Module::Build という 選択肢があります。 ExtUtils::MakeMaker を使う場合、パッケージを作るには "make dist" を使います。 MakeMaker に親和性のある形でモジュールのビルドを助けるツールが存在します。 ExtUtils::ModuleMaker や h2xs です。 perlnewmod も参照してください。
モジュールにはライセンスを付け、(そのライセンスが一般的なもので、 そのライセンスがライセンスの全文を配布物に含めることを要求していないのでない 限り)、その全文を配布に含めるようにしてください。
もしどのライセンスを使えばいいかわからない場合は、GPL と Artistic licenses のデュアルライセンス (Perl 自身と同じ) にするというのが いい考えです。 perlgpl と perlartistic を参照してください。
CPAN によって提供されている、すでにとてもとてもうまくいっている アプリケーション分野もあります。 例としてはテンプレートシステムや日付と時間のためのモジュールであり、 その他にもたくさんあります。 これらのものの自分専用版を書くというのは通過儀礼ではありますが、 あなたがそれを公開することを Perl の世界が本当に必要としているかどうかを 慎重に検討してください。
あなたのモジュールは開発者のツールキットの一部です。 ツールキット 全体 ではありません。 これはあなたのコードをモジュール化された建築ブロックではなく一枚岩のシステムに なるまで余分な機能を追加しようとする誘惑です。
間違った読者に向けて書くという罠に陥らないでください。 主な読者は、少なくともモジュールの適用分野についてある程度の理解のある 適度に経験を積んだ開発者で、単にモジュールをダウンロードして、できるだけ 早く使い始めたいと思っている人々です。
チュートリアル、エンドユーザー向け文書、研究論文、FAQ などはモジュールの 主文書としては不適切です。 どうしてもこれらのものを書きたいなら、My::Module::Tutorial
や My::Module::FAQ
のような副文書として含めて、主文書の SEE ALSO 節に リンクをつけてください。
一般的な Perl スタイルガイド
新しいモジュールの作り方
POD 文書
POD の正しさを検証する
Test::Simple, Test::Inline, Carp::Assert, Test::More, Test::MockObject
Perl Authors Upload Server。 モジュール作者のための情報へのリンクがあります。
Kirrily "Skud" Robert <skud@cpan.org>