Pod::Coverageを使うと、作成したモジュールにPODが記述されていないとテストがこけるようにできます。メソッドにも当該メソッドに関するPODがないとこけます。
このテストは自然にPODを書くことが開発サイクルの習慣になるので、おおむねよいプラクティスだと考えます。 しかし、一部、ユーザにインタフェースを公開しない、内部で利用しているだけ等のPODを書きたくない(書くべきではない)メソッドがある場合、そのメソッドに関してはPODの記述を必須から外したいと思います。方法としては下記のようにします。
例で言えば、これでDESTROYとDEBUGメソッドはPODを書かなくてもテストを通るようになります(でも、コメントはちゃんと書きましょう)。
モジュールをModule::Starter で作成するとデフォルトでt/pod-coverage.tというテストが作成されます。このテストはPod::Coverageを使って開発したモジュールにてPODが書かれているかチェックしてくれますが、全メソッドに対するPODの記述を求めてしまうので、PODを書かないメソッドがあればalso_privateパラメータで適宜指定して、エラーにならないようにします。
モジュールのインストールをmake、make testで行う場合はt/pod-coverage.tはskipされてエラーにはならないのですが、Build、Build testで行う場合はエラーになりますので要注意です。モジュールを開発する際はmake test、Build testのどちらでもエラーにならないことを確認しましょう。
参考:
・Test::Pod::Coverageで関数の記述の試験を無視する方法 - サンプルコードによるPerl入門 ~ 安定と信頼のPerlを学ぼう ~
・ドキュメントをどうするのか - kuchimuraのメモ
2014年12月28日日曜日
[Perl] オブジェクト同士の比較
オブジェクト 同士の比較には==もeqもどちらも使えます。
==の場合はPerlがオブジェクトを数値として扱います。eqの場合はPerlはMyClass=HASH(0x7fda6181be28)のようなオブジェクトの文字列表現を用いて比較します。
==の場合はPerlがオブジェクトを数値として扱います。eqの場合はPerlはMyClass=HASH(0x7fda6181be28)のようなオブジェクトの文字列表現を用いて比較します。
ラベル:
==,
eq,
Perl,
オブジェクト同士の比較
[Perl] 相互参照するデータ構造(循環参照)のメモリリークを解決する方法
Perlは他のスクリプト言語と同じく、通常はメモリの管理をプログラムが行う必要はありません(というか、そんな必要があったらスクリプト言語を使う意義が激減する)。オブジェクト(変数や定数等)に割り当てたメモリはPerlがよしなに解放してくれます。ただ、Perlのメモリは参照カウント方式で管理されていて、 当該オブジェクトがどこからも参照されなくなった時にメモリを解放するというGC(ガーベッジコレクション)なので、お互いを参照しあう循環参照を作ると、それは(プログラム終了まで)永遠に解放されないメモリリークとなる問題があります。
循環参照の例は次の通り。
こうした循環参照で発生するメモリリークを解決するにはオブジェクトのデストラクタ(DESTROY)を使います。
ちなみに、メモリリークが発生するかどうかの調査にはDan Kogaiさん開発のData::Decycleが便利です。
参考:
・Perlのガーベッジコレクション(GC)の特性について - サンプルコードによるPerl入門 ~ 安定と信頼のPerlを学ぼう ~
・404 Blog Not Found:基本はDESTROY()
・404 Blog Not Found:perl - Data::Decycle で悪循環を断とう!
循環参照の例は次の通り。
こうした循環参照で発生するメモリリークを解決するにはオブジェクトのデストラクタ(DESTROY)を使います。
ちなみに、メモリリークが発生するかどうかの調査にはDan Kogaiさん開発のData::Decycleが便利です。
参考:
・Perlのガーベッジコレクション(GC)の特性について - サンプルコードによるPerl入門 ~ 安定と信頼のPerlを学ぼう ~
・404 Blog Not Found:基本はDESTROY()
・404 Blog Not Found:perl - Data::Decycle で悪循環を断とう!
ラベル:
DESTROY,
GC,
memory leak,
Perl,
ガーベッジコレクション,
デストラクタ,
メモリリーク,
参照カウンタ,
循環参照
2014年12月27日土曜日
[Perl] ソートした結果をさらにソートする方法
例えば、名前の長さでソートした後、同じ長さの名前同士では辞書順にソートする場合などは下記のようにsort関数内で || でソートロジックをつなげます。
2014年12月26日金曜日
[Perl] mainに存在する変数を知る方法
mainパッケージ(特に指定しなければデフォルトでmainパッケージにてプログラムは実行されます)に存在する変数一覧を取得するには次のようにします。これをシンボルテーブルといいます。
任意のパッケージのシンボルテーブルはmain::の箇所を、当該パッケージ名に変えれば良いだけです。 ちなみに、myを使って宣言した変数はレキシカル変数といい、シンボルテーブルには登録されないので、この方法では参照できません。myで宣言した変数は、当該変数のスコープ内でのみ存在し、スコープを抜けると解放されます。
参考:
perlmod - Perl のモジュール (パッケージとシンボルテーブル) - perldoc.jp
Perlのスコープを理解する - サンプルコードによるPerl入門 ~ 安定と信頼のPerlを学ぼう ~
任意のパッケージのシンボルテーブルはmain::の箇所を、当該パッケージ名に変えれば良いだけです。 ちなみに、myを使って宣言した変数はレキシカル変数といい、シンボルテーブルには登録されないので、この方法では参照できません。myで宣言した変数は、当該変数のスコープ内でのみ存在し、スコープを抜けると解放されます。
参考:
perlmod - Perl のモジュール (パッケージとシンボルテーブル) - perldoc.jp
Perlのスコープを理解する - サンプルコードによるPerl入門 ~ 安定と信頼のPerlを学ぼう ~
2014年12月23日火曜日
2014年12月12日金曜日
[Perl] [CPAN] CPAN Autherの登録手順(後編)
前編でPAUSEのアカウント登録まで終わりました。
後編はモジュールを書いてCPANにアップするまでの流れを私が嵌ったポイントを中心に書きます。
1. モジュールのスケルトンの作成の準備(必要なモジュールのインストール)
スケルトンの作成はModule::Starter::PBPを使用します。その為に、次の3モジュールをCPANからインストールします。
通常はスケルトンにファイルの追加ができないので、これを可能にするためにModule::Starter::Smartもインストールしています。
ターミナル上で下記の手順を実行し、ホームディレクトリにスケルトンの雛形~/.module-starter/を生成します。
Module::Starter::Smartを有効にするために、~/module-starter/configに下記を追記します。
2. スケルトンの作成
下記のコマンドでスケルトンを作成します。例は先日CPANにアップしたDataStructure::LinkedListを使っています。
実行するとカレントディレクトリにDataStructure-LinkedListディレクトリが作成され、DataStructure-LinkedListディレクトリ内にスケルトンが作成されます。
3. モジュールの実装
スケルトンで生成されたモジュールに対して実装を加えていきます。ファイルはDataStructure::LinkedListモジュールなら ./DataStructure-LinkedList/lib/DataStructure/LinkedList.pmになります。つまり、一般にFoo::Barモジュールを作るなら、./Foo-Bar/lib/Foo/Bar.pmが実装対象のモジュールになります。
スケルトンで生成されたモジュールには、初期状態でpodが書かれています。全体の構成と、BUGS、SUPPORT、ACKNOWLEDGEMENTS、LICENSE AND COPYRIGHTはそのまま使えますので、便利に利用して実装を進めていきます。ちなみに、名前の表記やメールアドレスなど、微調整したい場合は、これらの値も書き換えます。
また、既にあるモジュール(例だと./DataStructure-LinkedList/)に新しくモジュールを追加したい場合はコマンドラインで下記のようにします。
私の場合は、DataStructure::LinkedList::Cellなどの追加モジュールは自分で直接ファイル作って置きました(汗
この場合、追加したモジュールにはpodが全く記述されていないので(当たり前か)、最初に作った モジュールをコピペするなりして実装します。podを書いていないモジュールをアップすると、エラーレポートが送りつけられるので、気をつけましょう。面倒ですが、ユーザが直接使わないモジュール(クラス)にもpodを書いてください。
さて、この段階で、次のようにmake & installしてみます。
このコマンドで、作業ディレクトリ(例の場合は~/DataStructure-LinkedList/)のlib/配下のファイルがblib/配下にコピーされ、また、自環境のPerlライブラリに追加されます。注意が必要なのは、この時点でテストプログラム等を書いた場合に、そのプログラムが参照するのは自環境のPerlライブラリ、blib/配下、lib/配下の順に参照されるという事です。モジュールの実装を進めるにあたって、度々実行テストをすると思いますが、lib/配下のモジュールをアップデートしてもPerlライブラリ、blib/配下にはコピーされず、変更が反映されないので、テストプログラムの挙動に変化がないということになります。これを避けるにはlib/配下のモジュールをアップデート後、下記のようにmake cleanしてinstallし直します。(実はmake installを実行していなければ、テストプログラムはblib/配下を見に行きますので、毎回のmake installは省略可能です)。
実装の最後に、Build.PLにモジュールが利用(依存)している他のモジュールの情報を書き足します。DataStructure::LinkedListの場合、Class::Accessor、Scalar::Util、Carpを使っていますので、下記のようにMakefile.PLのPREREQ_PM、Build.PLのrequiresに記述します。Module::Starterを使ってモジュールを作成する場合、Makefile.PLとBuild.PLを使った2通りのインストール方法がREADMEに記述されますので、どちらの方法でインストールされても良いように二つのPLファイルに依存関係を記述します。
Makefile.PLでのモジュールの依存関係の定義 Build.PLでのモジュールの依存関係の定義 依存関係のある各モジュールの自環境(=開発環境)でのバージョンはコマンドラインにて下記のようにして調べられます。
依存関係にあるモジュールのバージョンを 自環境でのバージョンを正として書いてよいのか、どのバージョンでも良い様に0とするか悩みました。しかし、結局テストして動作確認できているのは自環境だけだから、そのバージョンを明記した方が良心的だろうと判断しました。
4. デブロイ(リリース)
モジュールの実装が終わったらCPANにアップするtar ball(tar.gzファイル)を作ってPAUSEからアップロードします。
まず、下記のようにMANIFESTを作ります。
これで、MANIFESTファイルが作成されます。MANIFESTにはtar ballに含める全ファイルのリストが書かれています。基本的にはカレントディレクトリ配下の全ファイルが記述されます(ただし、.svnなどの隠しファイルは記述されない)。MANIFESTをエディタで開き、余計なファイルが含まれているか、足りないファイルがないか、よく確認してください。特に、既にあるモジュールに新しくモジュールを追加する際に、module-starterを使わずに私のように直接ファイルを置いて作った場合は、そのモジュールがMANIFESTから漏れているかもしれないので要注意です。おそらく、モジュールを追加した後に一度でもmake manifestしていれば大丈夫だと思います。
それでは、いよいよtar ballを作ります。まず、tar ballに固める内容をテストします。
これが問題なく通れば、MANIFESTの記載内容や開発環境(カレントディレクトリ配下)以外の環境でもテストが通ることを確認できます。make disttestはアーカイブ用のディレクトリの中にMANIFESTに記載されている全ファイルをコピーしmake testしてくれるからです。
make disttestでの結果が問題なければ、次のようにmake distしてtar ballを作ります。
例の場合だとDataStructure-LinkedList-0.01.tar.gzが作成されます。一般にversionがxのFoo::Barモジュールをmake distするとFoo-Bar-x.tar.gzが作成されます。
最後に、PAUSEにアクセス、ログインして、メニュー[Upload a file to CPAN]を選び、表示されるフォームから作成したtar ballを指定してアップロードします。
これで、しばらく待つと(承認されれば)CPANに登録されて検索可能になります。アップロードから24時間ぐらいのタイミングでエラーレポートのメールがCPANから届きます(エラーがなければ届かないのかどうかは私には不明。 )。
以上です、お疲れさまでした。
X. 参考
Module::Starterを使ってみる - 色々メモにっき
Perlのmakeフェーズの挙動 : D-7 <altijd in beweging>
Y. 推奨
本当はアップロードする前にGitHubかブログにリンクを貼った状態でtar ballをPrePANに公開し、PrePANの有志のテスターにモジュールのレビュー/テスト(特に名前の付け方)をしてもらうことが推奨されています。私は今回、PrePANを知ったのがtar ballをアップロードした後だったので(汗、使いませんでしたが。次のモジュールからは使います。大体3日ぐらいフィードバックを待って、特に指摘がなければそのままPAUSEからアップすればよいようです。
後編はモジュールを書いてCPANにアップするまでの流れを私が嵌ったポイントを中心に書きます。
1. モジュールのスケルトンの作成の準備(必要なモジュールのインストール)
スケルトンの作成はModule::Starter::PBPを使用します。その為に、次の3モジュールをCPANからインストールします。
通常はスケルトンにファイルの追加ができないので、これを可能にするためにModule::Starter::Smartもインストールしています。
ターミナル上で下記の手順を実行し、ホームディレクトリにスケルトンの雛形~/.module-starter/を生成します。
Module::Starter::Smartを有効にするために、~/module-starter/configに下記を追記します。
2. スケルトンの作成
下記のコマンドでスケルトンを作成します。例は先日CPANにアップしたDataStructure::LinkedListを使っています。
実行するとカレントディレクトリにDataStructure-LinkedListディレクトリが作成され、DataStructure-LinkedListディレクトリ内にスケルトンが作成されます。
3. モジュールの実装
スケルトンで生成されたモジュールに対して実装を加えていきます。ファイルはDataStructure::LinkedListモジュールなら ./DataStructure-LinkedList/lib/DataStructure/LinkedList.pmになります。つまり、一般にFoo::Barモジュールを作るなら、./Foo-Bar/lib/Foo/Bar.pmが実装対象のモジュールになります。
スケルトンで生成されたモジュールには、初期状態でpodが書かれています。全体の構成と、BUGS、SUPPORT、ACKNOWLEDGEMENTS、LICENSE AND COPYRIGHTはそのまま使えますので、便利に利用して実装を進めていきます。ちなみに、名前の表記やメールアドレスなど、微調整したい場合は、これらの値も書き換えます。
また、既にあるモジュール(例だと./DataStructure-LinkedList/)に新しくモジュールを追加したい場合はコマンドラインで下記のようにします。
私の場合は、DataStructure::LinkedList::Cellなどの追加モジュールは自分で直接ファイル作って置きました(汗
この場合、追加したモジュールにはpodが全く記述されていないので(当たり前か)、最初に作った モジュールをコピペするなりして実装します。podを書いていないモジュールをアップすると、エラーレポートが送りつけられるので、気をつけましょう。面倒ですが、ユーザが直接使わないモジュール(クラス)にもpodを書いてください。
さて、この段階で、次のようにmake & installしてみます。
このコマンドで、作業ディレクトリ(例の場合は~/DataStructure-LinkedList/)のlib/配下のファイルがblib/配下にコピーされ、また、自環境のPerlライブラリに追加されます。注意が必要なのは、この時点でテストプログラム等を書いた場合に、そのプログラムが参照するのは自環境のPerlライブラリ、blib/配下、lib/配下の順に参照されるという事です。モジュールの実装を進めるにあたって、度々実行テストをすると思いますが、lib/配下のモジュールをアップデートしてもPerlライブラリ、blib/配下にはコピーされず、変更が反映されないので、テストプログラムの挙動に変化がないということになります。これを避けるにはlib/配下のモジュールをアップデート後、下記のようにmake cleanしてinstallし直します。(実はmake installを実行していなければ、テストプログラムはblib/配下を見に行きますので、毎回のmake installは省略可能です)。
実装の最後に、Build.PLにモジュールが利用(依存)している他のモジュールの情報を書き足します。DataStructure::LinkedListの場合、Class::Accessor、Scalar::Util、Carpを使っていますので、下記のようにMakefile.PLのPREREQ_PM、Build.PLのrequiresに記述します。Module::Starterを使ってモジュールを作成する場合、Makefile.PLとBuild.PLを使った2通りのインストール方法がREADMEに記述されますので、どちらの方法でインストールされても良いように二つのPLファイルに依存関係を記述します。
Makefile.PLでのモジュールの依存関係の定義 Build.PLでのモジュールの依存関係の定義 依存関係のある各モジュールの自環境(=開発環境)でのバージョンはコマンドラインにて下記のようにして調べられます。
依存関係にあるモジュールのバージョンを 自環境でのバージョンを正として書いてよいのか、どのバージョンでも良い様に0とするか悩みました。しかし、結局テストして動作確認できているのは自環境だけだから、そのバージョンを明記した方が良心的だろうと判断しました。
4. デブロイ(リリース)
モジュールの実装が終わったらCPANにアップするtar ball(tar.gzファイル)を作ってPAUSEからアップロードします。
まず、下記のようにMANIFESTを作ります。
これで、MANIFESTファイルが作成されます。MANIFESTにはtar ballに含める全ファイルのリストが書かれています。基本的にはカレントディレクトリ配下の全ファイルが記述されます(ただし、.svnなどの隠しファイルは記述されない)。MANIFESTをエディタで開き、余計なファイルが含まれているか、足りないファイルがないか、よく確認してください。特に、既にあるモジュールに新しくモジュールを追加する際に、module-starterを使わずに私のように直接ファイルを置いて作った場合は、そのモジュールがMANIFESTから漏れているかもしれないので要注意です。おそらく、モジュールを追加した後に一度でもmake manifestしていれば大丈夫だと思います。
それでは、いよいよtar ballを作ります。まず、tar ballに固める内容をテストします。
これが問題なく通れば、MANIFESTの記載内容や開発環境(カレントディレクトリ配下)以外の環境でもテストが通ることを確認できます。make disttestはアーカイブ用のディレクトリの中にMANIFESTに記載されている全ファイルをコピーしmake testしてくれるからです。
make disttestでの結果が問題なければ、次のようにmake distしてtar ballを作ります。
例の場合だとDataStructure-LinkedList-0.01.tar.gzが作成されます。一般にversionがxのFoo::Barモジュールをmake distするとFoo-Bar-x.tar.gzが作成されます。
最後に、PAUSEにアクセス、ログインして、メニュー[Upload a file to CPAN]を選び、表示されるフォームから作成したtar ballを指定してアップロードします。
これで、しばらく待つと(承認されれば)CPANに登録されて検索可能になります。アップロードから24時間ぐらいのタイミングでエラーレポートのメールがCPANから届きます(エラーがなければ届かないのかどうかは私には不明。 )。
以上です、お疲れさまでした。
X. 参考
Module::Starterを使ってみる - 色々メモにっき
Perlのmakeフェーズの挙動 : D-7 <altijd in beweging>
Y. 推奨
本当はアップロードする前にGitHubかブログにリンクを貼った状態でtar ballをPrePANに公開し、PrePANの有志のテスターにモジュールのレビュー/テスト(特に名前の付け方)をしてもらうことが推奨されています。私は今回、PrePANを知ったのがtar ballをアップロードした後だったので(汗、使いませんでしたが。次のモジュールからは使います。大体3日ぐらいフィードバックを待って、特に指摘がなければそのままPAUSEからアップすればよいようです。
2014年12月11日木曜日
[Perl] DataStructure::LinkedListをアップデート
podを追記して、再アップロード(バージョンを0.02にアップデート)したら、Errorは消えました。
http://www.cpantesters.org/distro/D/DataStructure-LinkedList.html
よかった。
http://www.cpantesters.org/distro/D/DataStructure-LinkedList.html
よかった。
2014年12月10日水曜日
[Perl] クラス名を得る(何らかのオブジェクトであるかどうかを判定する)方法
Scalar::Utilのblessedで何らかのクラスのオブジェクトかどうかを簡単に判定できます。
また、ref関数でクラス名を得ることができます。
2014年12月8日月曜日
2014年12月6日土曜日
[Perl] [CPAN] CPAN Autherの登録手順(前編)
CPANにモジュールをアップしていきたいなぁと思い、CPAN Autherの登録を行いました。
CPAN Autherになるためには、PAUSE(The Perl Authors Upload Server)のアカウントを取る必要があります。
PAUSEアカウントの取得とGravatarによるユーザ画像の設定まで行いました。
そこまでを、以下のエントリーの通りに進めました。
・CPAN Author になった話 - えがわたにっき
・こんな僕が CPAN Author (一応) になるまで。 - (゚∀゚)o彡 sasata299's blog
私が詰まったポイントを少し補足します。
・PAUSE アカウント取得の確認メールは送られるまでに少し時間がかかります。といっても、私の場合、10分ぐらいできましたが。
・PAUSEアカウント取得の確認メールはIDを通知するだけのものと、パスワード(これはPAUSE側が自動的に生成したパスワード)を通知するだけのものと、2通に分けて届けられます。
・PAUSEの[Edit Account Info](ログイン後にアクセス可能)にて、「Publicly visible email address (published in many listings)」(公開するメールアドレス)と、「Secret email address only used by the PAUSE, never published.」(非公開メールアドレス)の設定をしますが、同一のメールアドレスで良い場合は、公開するメールアドレスのみを指定して、非公開側は空欄にします。そして最後のcpan.orgメールアドレスの転送先を選ぶラジオボタンにて、「my public email address」を指定します。公開も非公開にも同じアドレスを指定すると、cpan.orgメールアドレスへのメールを指定したメールアドレスに転送できず、Gravatarへの登録などができません。ご注意を。
CPAN Autherになるためには、PAUSE(The Perl Authors Upload Server)のアカウントを取る必要があります。
PAUSEアカウントの取得とGravatarによるユーザ画像の設定まで行いました。
そこまでを、以下のエントリーの通りに進めました。
・CPAN Author になった話 - えがわたにっき
・こんな僕が CPAN Author (一応) になるまで。 - (゚∀゚)o彡 sasata299's blog
私が詰まったポイントを少し補足します。
・PAUSE アカウント取得の確認メールは送られるまでに少し時間がかかります。といっても、私の場合、10分ぐらいできましたが。
・PAUSEアカウント取得の確認メールはIDを通知するだけのものと、パスワード(これはPAUSE側が自動的に生成したパスワード)を通知するだけのものと、2通に分けて届けられます。
・PAUSEの[Edit Account Info](ログイン後にアクセス可能)にて、「Publicly visible email address (published in many listings)」(公開するメールアドレス)と、「Secret email address only used by the PAUSE, never published.」(非公開メールアドレス)の設定をしますが、同一のメールアドレスで良い場合は、公開するメールアドレスのみを指定して、非公開側は空欄にします。そして最後のcpan.orgメールアドレスの転送先を選ぶラジオボタンにて、「my public email address」を指定します。公開も非公開にも同じアドレスを指定すると、cpan.orgメールアドレスへのメールを指定したメールアドレスに転送できず、Gravatarへの登録などができません。ご注意を。
ラベル:
CPAN,
CPAN Auther,
Gravatar,
PAUSE,
Perl
2014年12月3日水曜日
[Perl] 連結リスト(LinkedList.pm)を書いてみた
「Javaプログラマのためのアルゴリズムとデータ構造」に記載のある連結リストのクラスをPerlで書いてみた。一つのファイルに詰め合わせしているのは、ファイルを沢山作るのが面倒だったからです。
だけで使えるのも便利だし。 一応、package mainに使用サンプルを書いているので、
で実行してみることができます。お試しあれ。
※コメントが全然書いてないですが、、、、そのうち書きます。podで。怠惰ですみません。
use LinkedList;だけで使えるのも便利だし。 一応、package mainに使用サンプルを書いているので、
perl LinkedList.pmで実行してみることができます。お試しあれ。
※コメントが全然書いてないですが、、、、そのうち書きます。podで。怠惰ですみません。
2014年9月3日水曜日
登録:
投稿 (Atom)