Masteries

技術的なことや仕事に関することを書いていきます.

CPANモジュールの開発リリース(Development release)について

この記事は, Perl Advent Calendar 2022の7日目の記事です*1.

qiita.com

昨日は, MacOlinさんの「perlでタイムスタンプを変更したい、Time::Pieceを使って」でした.

qiita.com

CPANモジュールの開発リリース(Development release)について

CPANモジュールを書いている方からすると非常に今更! という感じがするのですが, この機会にCPANモジュールの開発リリース(Development release)についてまとめておこうと思います.

さて, CPANモジュールを開発するにあたって, 「いい機能を開発したので, ちょっと試してみてほしい...!」という時があると思います. そういう時に使えるのがタイトルにあるDevelopment releaseです.

Development releaseの見え方

metacpanであるモジュールを見ると, 基本的には最新のDevelopment releaseではないモジュールが表示されます. 例えば, 拙作のClass::Accessor::Typedは, 現在Development releaseの0.03_02が最新ですが, metacpanで表示すると0.03の様子が表示されます. しかしながら, Jump to version を見ると, 次のように Development release である 0.03_02 が選べます.

Development releaseの場合, このように赤背景に白文字で「Development release」と表示されて, 区別できるようになっています.

Development releaseの扱い

Development releaseは開発版なので, 意図的に指定しないとインストールできないようになっています. 先のClass::Accessor::Typedの場合, 例えば cpanm Class::Accessor::Typed のようにインストールした場合, 最新であるDevelopment releaseの0.03_02ではなく, 0.03がインストールされます.

なお, Development releaseのモジュールをApp::cpanminusやCartonでインストールする方法はちょうど過去にブログを書いていましたのでご参考まで:

papix.hatenablog.com

Development releaseにする方法

さて, CPANモジュールをDevelopment releaseする方法としては, これまで見てきたように, モジュールのバージョンの末尾に _\d+ を付与する方法が代表的です. 例えば, Class::Accessor::Typedの0.03_02では, 次のようなバージョン指定になっています:

our $VERSION = "0.03_02";

あとはこのまま, Minillaなどでリリースすれば, 自動的にDevelopment releaseとして扱われます. 便利ですね. なお, 例えば今0.10をリリースしたところだとして, その次のリリースのためのDevelopment releaseをする時に, 「これは0.11に向けたDevelopment releaseだから0.11_1がいいのか, それとも0.10_1なのか...?」と悩んだことがあったのですが, id:shoichikaji さんに次のように教えていただきました:

なので, 先の場合では, 0.10の次のDeveloper releaseは0.10_1にすると良い, という訳ですね.

まとめ

備忘録を兼ねて, CPANモジュールのDevelopment releaseについて書きました.

Perl Advent Calendar 2022の8日目は, id:tomcha0079 さんの「2023年、Perlをはじめてみよう!」です. 実際, スイスアーミーナーフ的に使うPerlは2023年でも普通に便利なので, 今から始める価値はある... と自分は思っています.

tomcha.hatenablog.jp

*1:日付をいじってさも7日のうちに投稿しました, という体裁を整えていますが, 実際のところ7日の26時頃に公開しました... すいません...

小ネタ: Perlモジュール探訪

Perlで開発しているときに, 「このモジュールについて調べたいな...」と思う時があると思います. 皆さんどうしていますか?

metacpan

metacpan.org

ブラウザからmetacpanでモジュールを検索してドキュメントを見る, というのがまあ鉄板という気がします. ハイライトがついていたり, リンクがあったら遷移できたりと便利です.

perldoc コマンド

一方で, 「サクッとターミナルでドキュメントが読めたらいいんだけどな...」という場合は perldoc コマンドを使うのもアリです.

$ perldoc Teng

但し, perldoc コマンドの場合, そのモジュールがインストールされている必要があります. 上の例だと, Tengがインストールされていない場合は, 次のような結果になります:

$ perldoc Teng
No documentation found for "Teng".

cpandoc コマンド

というわけで, Pod::Cpandoc が提供する cpandoc コマンドを使いましょう. モジュールがインストールされていない場合, CPANをスクレイピングしていい感じに表示してくれます.

そういう意味で, perldoc の上位互換的存在なので, 自分は perldoccpandoc の alias にして使っています.

スペシャルサンクス

ちなみにcpandocを知ったのは, id:toku_bass さんのこのエントリだった気がします. ありがとうございます.

qiita.com

相談の「型」

チームメンバーと1on1をしていた時, チームメンバーとの相談についての話になりました. 例えば, ある機能を実装するとき, A案, B案, C案があって, それぞれメリデメなどがあって, どれにするべきか悩ましい... という時がありますよね. そういう時, (内容なチームメンバーの様子など, 時と場合によりますが)より良い案を選びたいので, チームメンバーに相談することがあります.

そういう時, 予めドキュメントを書くようにしています(会社ではScrapboxを使っているので, これに書くことが多いです). 自分の場合, 物忘れが激しいのでノー準備で行くと何を話せばいいのかわからなくなるのと, 後はドキュメントに相談内容をまとめることで, いわば「一人で壁打ち」のような状態になって, より良いアイデアが浮かんできたりするのが嬉しいところです.

そういった行いをしていると, 「相談の型」みたいなのができてきます. 自分の場合, だいたいこういう感じです.

  • 前提: どういうタスクをしているのか, 関係するドキュメントやIssueの紹介
  • 課題: そのタスクで, どのような問題に直面しているのか
  • 解決案: どのような解決案が思いついているか, 概要とメリデメの共有
  • 私案: 解決案の中で, 自分が良いと思う案とその理由

この辺りをまとめておくと, 相談された側としてもドキュメントを見るだけで様子がわかって, 回答しやすくなる気がします(相談のミーティングを開かず, 非同期にドキュメントにコメント書くだけで事足りたりもします. 同期的なミーティングはお互いの時間拘束するので, 非同期で済ませられるのはありがたいですね).

ところで書いていて, これ論文っぽい気もしますね, と思いました. 論文も, 前提を紹介して, 課題を述べた後, 解決案を提案/評価して, 結論を出す(先の相談の型では, 結論が私案の提案になるのかな)... と捉えると似ている気がします.

そう考えると, まだ読んだことないのですが, 「理科系の作文技術」とか読んだら, 実はこういう相談の場でも活きてくるんじゃないか? という気がしました. ちょっと読んでみようかな...

デバッグ用のコードが残っているとGitでコミットできないようにする(改)

だいぶ前に, こういったエントリを書きました:

papix.hatenablog.com

一方で, こちらのエントリにこういったブクマコメントを頂いていました:

デバッグ用のコードが残っているとGitでコミットできないようにする - Masteries

文字列リテラルの中とか関係ないところにDDPという文字列が現れる場合はどうするんだろう?

2017/04/04 09:46
b.hatena.ne.jp

これについては仰るとおりで, 例えばテストなどで意図的にData::Printer(DDP)を使っている場合は引っかかってしまってコミットできなくなってしまいます.

この対策としては, 完全ではないのですが, 自分は「意図的にData::Printerを使っているファイルはチェックの対象外とする」ことで回避しています. 以下の例では, lib/Foo.pm, lib/Bar.pm, lib/Baz.pm に限って DDP というテキストが含まれていても許容するようになります:

#!/bin/sh

if ag --perl DDP $(git rev-parse --show-toplevel)/lib $(git rev-parse --show-toplevel)/t \
    | grep -v 'lib/Foo.pm' \
    | grep -v 'lib/Bar.pm' \
    | grep -v 'lib/Baz.pm' \
; then
    echo "some file contains code for debugging: DDP"
    exit 1;
fi

課題としては, チェックの対象外にしたファイルでデバッグ用のコードが残っている場合, 当然ですが気づけません(が, チェックの対象外にするのが数ファイル程度なら, これでも十分に役立つと思います).

小ネタ: Test2でテストを書く時に, hashやarrayにundefがあることをU()でテストすると, なんか意図しない感じになることがある

またまたまたまた小ネタです. PerlのテストモジュールであるところのTest2において, U()undef であることをテストします.

is undef, U(); # => ok
is 1, U(); # => not ok

では, ハッシュや配列にundefがあることをテストしたい時はどうするといいでしょうか?

my $array = [ 'a', undef ];
is $array, array {
    item 'a';
    item U();
    end;
};

my $hash = { a => 1, b => undef };
is $hash, hash {
    field a => 1;
    field b => U();
    end;
};

一見良さそうに見えます(テストもパスします). が, 次の場合はどうでしょう.

my $array = [ 'a' ];
is $array, array {
    item 'a';
    item U();
    end;
};

my $hash = { a => 1 };
is $hash, hash {
    field a => 1;
    field b => U();
    end;
};

なんとこちらもパスします. undef があることをテストしたくてテストを書いたはずなので, このままだといけませんね.

この場合, きちんとundefが存在することをテストするには, U() ではなく, 明示的に undef を指定して, 比較する必要があります.

my $array = [ 'a' ];
is $array, array {
    item 'a';
    item undef; # エラー
    end;
};

my $hash = { a => 1 };
is $hash, hash {
    field a => 1;
    field b => undef; # エラー
    end;
};

このへんは, HASH BUILDERのところに,

# Ensure the key exists, but is set to undef
field bat => undef;

metacpan.org

...と書かれていました. なので, 「絶対にundefであることをテストしたい!」という場合は, 前述の通り U() を使わずに常に undef でテストしてあげましょう.