2006年04月24日 21:20 [Edit]

perl - 勝手に添削 - Hatena::API::Auth

cpan

というわけで、好評につき続けます、勝手に添削のコーナー。

今回はハテナオヤ作、Hatena::API::Auth 0.02です。


以下、ソースの一部を抜き出したものです。

 1: package Hatena::API::Auth;
 2: use strict;
 3: use warnings;
 4: our $VERSION = 0.02;
 5: 
 6: use base qw (Class::Accessor::Fast Class::ErrorHandler);
22: 
23: __PACKAGE__->mk_accessors(qw(api_key secret));
24: 
67: sub login {
68:     my $self = shift;
69:     my $cert = shift or croak "Invalid argumet (no cert)";
70:     my $auth = $self->_get_auth_as_json($cert)
71:         or return $self->error($self->errstr);
72:     my $json = $self->_parse_json($auth);
73:     if ($json->{has_error}) {
74:         return $self->error($json->{error}->{message});
75:     } else {
76:         return Hatena::API::Auth::User->new($json->{user});
77:     }
78: }
79: 
80: package Hatena::API::Auth::User;
81: use base qw(Class::Accessor::Fast);
82: 
83: __PACKAGE__->mk_accessors(qw(name image_url thumbnail_url));
84: 
85: 1;
86: 
87: __END__

さすがです。きれいですねえ。モジュールの使い方もツボをおさえていい感じですね....

と思ったあなた、このモジュールには1つの比較的深刻な問題、1つのメンテナンス上の問題をもっています。わかりますか?

それでは、メンテナンス上の問題から。このAPI.pmには、Hatena::API::AuthおよびHatena::API::Auth::Userの二つのモジュールが入っています。上記の書き方をすることにより、Perlでは複数のモジュールを一つのファイルに入れることも出来ます。

が、これはCPANなどで公開する場合には、避けるべきなのです。

このdistributionで、Hatena::API::AuthHatena::API::Auth::Userの更新頻度は異なるはずです。恐らくHatena::API::Auth::Userの方が多くなる事でしょう。それにつれてPODを別々にしたいという需要も高まるでしょう。ところが、perldoc Hatena::API::AuthはOKでもHatena::API::Auth::UserはNGなのです。lib/Hatena/API/Auth/User.pmに相当するファイルはないのですから。

こういう場合は、めんどくさがらずにFileを分ちましょう。一モジュール、一パッケージというのは原則として覚えておいていいと思います。例外は、モジュール、というよりパッケージをユーザーに見せない場合で、これもどちらかというと一緒に乗せるメリットはuse strict; use warningsの二行を一ファイルあたりに節約できる程度のご利益しかありません。コンパイル速度などはほとんど変わらないのです。

いっそ、別distributionにしたっていいのです。そうすれば、APIで出来る事が増えても、ハテナオヤの方はHatena::API::Auth::Userの方だけ更新すればいい。いや、折角社員も増えたのだし、別の社員にHatena::API::Auth::Userをまかせ、ハテナオヤ自身はHatena::API::Authをしっかり面倒みるという切り分けも出来るようになります。この辺は、miyagawa君を大いに見習うべきところでしょう。「モジュール大杉!」という陰口もあるみたいですが、陰口をたたいている暇があったらCPANに上げましょう。それがBetter Practiceというものです。

もう一つはその逆、CPANモジュールへの過度の依存です。ここでは、Perl Core以外のモジュールとして、JSONないしJSON::Syck, LWP、Class::Accessor::FastそしてClass::ErrorHandlerを使っています。

通常であれば、これはGood Practiceです。しかし、Hatena::API::Authは認証を実装するモジュールです。普段はあまり注意を払わない、モジュールそのもののセキュリティをも視野に入れなければならないのです。

例えば、誰かが偽CPANサイトを作り、そこで悪意を持ったClass::Accessor::Fastを配布し、そこで定義されたメソッドにアクセスするたびにそれをLWPなどでこっそり別サイトに横流しするモジュールを作ったとしたらどうでしょうか?もちろんこの問題はどんなCPAN Module、いやどんなopen source projectでも多かれ少なかれ抱えている問題ではありますが、ことが認証だけに、一段高い注意が求められます。

実は、この問題に関しては我らがヒロイン、鳳たんがModule::Signatureという解決策を提示してはいます。しかし、これはまだ普及していない解決策でもあり、またこれを使うことにより、installの際にGnuPGが必要になるという、インストールの敷居が上がるというちょっとうれしくない効用もあります。

ここで一番簡単な解決策は、Class::Accessor::FastおよびClass::ErrorHandlerの使用を避ける、というものです。この二つは、実装もそれほど難しくないため、自分で書いても手間はほとんど変わりません。もちろん、例えばHatena::API::Auth::Utilというモジュールの中に実装して一緒に配布するというのもありです。

さすがにLWPやJSONまで内包するのは大げさでしょう。これらの二つは実に多くのところで使われており、Hatena::API::Authがインストールされる前にインストールされている公算が大だからです。

あと、肝心のAPIそのものにもいくつか問題があると思うのですが、それはまた別の機会に。

DANKOGAI at cpan.org


この記事へのトラックバックURL