Hatena::Diary

masartz->log RSSフィード

2009-12-12

JPerl Advent Calendar 2009 にQudoの記事を書きました JPerl Advent Calendar 2009 にQudoの記事を書きました - masartz->log を含むブックマーク はてなブックマーク - JPerl Advent Calendar 2009 にQudoの記事を書きました - masartz->log

12月1日より、日本のPerl界の有志によって実施されている

「JPerl Advent Calendar 2009」のhacker trackに

「Qudo」についての記事を書いてみました。


http://perl-users.jp/articles/advent-calendar/2009/hacker/13.html


正直hacker trackは名だたる有名なギークさんばっかりで場違い感が否めないのですが、、

数少ない自己モジュールからひねり出してみました。


内容としては、せっかくのadvent calerndarなのでクリスマスネタを入れてみました。


結果としては、オブジェクト指向入門書の第1章の

動物から馬が出来たり、乗り物から車が出来る、みたいな

読んでて違和感を感じるノリになってるかも知れません。


この記事自体はさらっと読み流していただいて、

その他のhacker trackや、casual trackにもカジュアル以上の

気合い入ったエントリがたくさん投稿されているので合わせて

ご覧ください。


同じくQudoの開発者のid:nekokakさんのDBIx::Skinny track(1人舞台)も展開中ですので、そちらもどうぞ。


さて、とは言ったもののインデックスページからの

リンクがない件が、nim のソースとかもチラっと見たんですが

わかりませんでした。。運営に支障をきたすような、なんか悪い事してなければいいんですが・・・大丈夫っぽい。

http://perl-users.jp/articles/advent-calendar/2009/hacker/

2009-11-09

Params::Validate覚書き Params::Validate覚書き - masartz->log を含むブックマーク はてなブックマーク - Params::Validate覚書き - masartz->log

Params::Validateを触ってみようと思い、色々ソースを見たんですが、イマイチわからなかったです。。そんな時に限って、ググっても意外にヒットしない・・・


普通の人は解読して、何かを残すほど難しいモジュールじゃないのかな、、と思いつつ

ドキュメント見るのは正直いまだに苦手なので、とりあえずサンプル書きながら体で覚えようとしてみました。


なんか落ち着いて読んでるうちに理解出来たと思う部分もあるけど、

まぁせっかく試したので貼っておきます。


必須項目のテストコード(test_mandatory.pl)

#!/usr/bin/perl 

use strict;
use warnings;
use Params::Validate;

my %test = (
    foo => 'hoge',
    bar => 'moge',
    baz => 'tete'
);

&test_func( %test );

delete $test{baz};
&test_func( %test );

delete $test{foo};
eval { &test_func( %test ); };
print $@ if $@;

sub test_func{
    Params::Validate::validate( @_,
        {
            foo => 1,
            bar => 1,
            baz => 0,
        }
    );
    return 1;
}

上の実行結果

Mandatory parameter 'foo' missing in call to main::test_func

at test_mandatory.pl line 23

main::test_func('bar', 'moge') called at test_mandatory.pl line 19

eval {...} called at test_mandatory.pl line 19


一番単純なパターンですね。


対象のキー値に対して1を渡せば必須。0を渡せばnot必須。

だから「delete $test{baz};」しても怒られないけど、

「delete $test{bar};」したら怒られる。


これだけで、済ませるっていうのはさすがに少ないかも知れません。




型チェックのサンプル(test_type.pl)

#!/usr/bin/perl 

use strict;
use warnings;
use Params::Validate qw/:all/;

my $scalar = 'scalar_ref';
my %test = (
    'scalar'    => 'abcde',
    'scalarref' => \'scalar_ref',
    'arrayref'  => [qw/ 1 2 3 4 5 /],
    'hashrref'  => { 'key1' => 'value1','key2'=>'value2' },
    'coderref'  => sub{ return 'test_code'.'ref_test';},
    'boolean'   => '1a2b',
);

# All OK
&test_func( %test );

# Scalar Error
$test{'scalar'} = {key => 'value'};
eval { &test_func( %test ); };
print $@."\n" if $@;

# ScalarRef Error
delete $test{'scalar'};
$test{'scalarref'} = [qw/6 7 8/];
eval { &test_func( %test ); };
print $@."\n" if $@;

# ArrayRef Error
delete $test{'scalarref'};
$test{'arrayref'} = 9;
eval { &test_func( %test ); };
print $@."\n" if $@;

# HashRef Error
delete $test{'arrayref'};
$test{'hashref'} = 9;
eval { &test_func( %test ); };
print $@."\n" if $@;

# CodeRef Error
delete $test{'hashref'};
$test{'coderef'} = {'key' => 'value'};
eval { &test_func( %test ); };
print $@."\n" if $@;

# Boolean Error
delete $test{'coderef'};
$test{'boolean'} = [qw/ 10 11 12/];
eval { &test_func( %test ); };
print $@."\n" if $@;

sub test_func{
    Params::Validate::validate( @_,
        {
            'scalar'    => {type => SCALAR},
            'scalarref' => {type => SCALARREF},
            'arrayref'  => {type => ARRAYREF},
            'hashrref'  => {type => HASHREF },
            'coderref'  => {type => CODEREF },
            'boolean'   => {type => BOOLEAN },
        }
    );
    return 1;
}

上の実行結果

The 'scalar' parameter ("HASH(0x826670)") to main::test_func was a 'hashref', which is not one of the allowed types: scalar

at test_type.pl line 49

main::test_func('boolean', '1a2b', 'scalar', 'HASH(0x826670)', 'coderref', 'CODE(0x826460)', 'arrayref', 'ARRAY(0x800d80)', 'hashrref', ...) called at test_type.pl line 20

eval {...} called at test_type.pl line 20


The 'scalarref' parameter ("ARRAY(0x82679c)") to main::test_func was an 'arrayref', which is not one of the allowed types: scalarref

at test_type.pl line 49

main::test_func('boolean', '1a2b', 'coderref', 'CODE(0x826460)', 'arrayref', 'ARRAY(0x800d80)', 'hashrref', 'HASH(0x826664)', 'scalarref', ...) called at test_type.pl line 25

eval {...} called at test_type.pl line 25


The 'arrayref' parameter ("9") to main::test_func was a 'scalar', which is not one of the allowed types: arrayref

at test_type.pl line 49

main::test_func('boolean', '1a2b', 'coderref', 'CODE(0x826460)', 'arrayref', 9, 'hashrref', 'HASH(0x826664)') called at test_type.pl line 30

eval {...} called at test_type.pl line 30


The following parameter was passed in the call to main::test_func but was not listed in the validation options: hashref

at test_type.pl line 49

main::test_func('boolean', '1a2b', 'hashref', 9, 'coderref', 'CODE(0x826460)', 'hashrref', 'HASH(0x826664)') called at test_type.pl line 35

eval {...} called at test_type.pl line 35


The following parameter was passed in the call to main::test_func but was not listed in the validation options: coderef

at test_type.pl line 49

main::test_func('boolean', '1a2b', 'coderef', 'HASH(0x8267b4)', 'coderref', 'CODE(0x826460)', 'hashrref', 'HASH(0x826664)') called at test_type.pl line 40

eval {...} called at test_type.pl line 40


The 'boolean' parameter ("ARRAY(0x800eac)") to main::test_func was an 'arrayref', which is not one of the allowed types: scalar undef

at test_type.pl line 49

main::test_func('boolean', 'ARRAY(0x800eac)', 'coderref', 'CODE(0x826460)', 'hashrref', 'HASH(0x826664)') called at test_type.pl line 45

eval {...} called at test_type.pl line 45


実際に多く使いそうなパターンですね。


テストはそれぞれの型が順番にこけるのを確認しつつ、

終わったものはエラーが出ないようにdelete していっています。


「{type => 『hoge』}」のhashrefを対象のキー値に対して渡してやります。

チェックできる型のタイプは上で全部じゃなくて、

GLOBとかOBJECTとかまだまだあるようです。詳しくはドキュメント参照。


OBJECTは後述のisaの方がいいんじゃないかと思いますが、違うかな。



オブジェクト正規表現のチェック(test_isa_regex.pl)

#!/usr/bin/perl 

use strict;
use warnings;
use Params::Validate;

my %test = (
    object => (bless{},'Test::Object') ,
    regex  => 111
);

&test_func( %test );

# Object Error
$test{object} = bless{}, 'Test::Object2';
eval { &test_func( %test ); };
print $@."\n" if $@;

# REGEX Error
$test{object} = bless{}, 'Test::Object';
$test{regex} .= 'a';
eval { &test_func( %test ); };
print $@."\n" if $@;

sub test_func{
    Params::Validate::validate( @_,
        {
            object => {isa   => 'Test::Object'},
            regex  => {regex => qr/^\d+$/},
        }
    );
    return 1;
}

上の実行結果

The 'object' parameter ("Test::Object2=HASH(0x800e34)") to main::test_func was not a 'Test::Object' (it is a Test::Object2=HASH(0x800e34))

at test_isa_regex.pl line 24

main::test_func('object', 'Test::Object2=HASH(0x800e34)', 'regex', 111) called at test_isa_regex.pl line 15

eval {...} called at test_isa_regex.pl line 15


The 'regex' parameter ("111a") to main::test_func did not pass regex check

at test_isa_regex.pl line 24

main::test_func('object', 'Test::Object=HASH(0x81ffe4)', 'regex', '111a') called at test_isa_regex.pl line 20

eval {...} called at test_isa_regex.pl line 20


ちょっとオマケっぽくやってみました。

ただ、regexは結構使いますね。数値チェックとかそういや各所にある気がします。


使い方は型の時と同じで指定が違うだけです。

regexの方は期待値の部分は当然正規表現になりますな。




まとめると、ドキュメントにあること以上はやってない。。

けど、なんとなくわかった気がするのでこれはこれでOKかと。

(勘違いしてる部分がなければいいのですが・・・)




途中から気づいたというか思い出しましたが、

どっちかって言うと、validationの指定方法より

validate , validate_pos , validate_with あたりが区別ついてなくて混乱してたんじゃないか、という気がしてきました。


「validate_pos」は「validate_posisitional」の事をおそらく指していそう。

引数の渡し方(ハッシュor配列)の違いで、配列を受け取る用かと思われます。


んで、validate_withがやっぱりわからない、、

文字通りvalidateしつつ、何か出来そうなんだけど・・・

というところで眠くなってきたので一旦終了します。

2009-10-22

mixiボイスからはてなブックマークできる、連携機能をでっち上げました mixiボイスからはてなブックマークできる、連携機能をでっち上げました - masartz->log を含むブックマーク はてなブックマーク - mixiボイスからはてなブックマークできる、連携機能をでっち上げました - masartz->log

本日はてなよりアナウンスがあった、

Twitter のつぶやきからブクマできる連携機能

http://hatena.g.hatena.ne.jp/hatenabookmark/20091022

に触発されて、mixiボイスからブクマするのを勢いで適当に作ってみました。



以下コード

#!/usr/bin/perl 

use strict;
use warnings;

use AnyEvent::Impl::Perl;
use AnyEvent;
use WWW::Mixi::Scraper;
use WebService::Hatena::Bookmark::Lite;
use Config::Pit;
use Date::Calc;

my $hatena_conf = Config::Pit::pit_get('http://www.hatena.ne.jp');
my $mixi_conf   = Config::Pit::pit_get('http://mixi.jp');


my $mixi = WWW::Mixi::Scraper->new(
    email    => $mixi_conf->{email} , 
    password => $mixi_conf->{password} ,
    mode     => 'TEXT'
);

my $org_post_time = $ARGV[0] || join('', map{ sprintf( "%02d", $_); } Date::Calc::Today_and_Now() );

my $cv_timer = AnyEvent->condvar;
my $timer; $timer = AnyEvent->timer(
    after   => 0,
    interval => 60,
    cb   => sub {
        my @echo_list = $mixi->list_echo->parse();

        if( _is_bookmark_post( $echo_list[0]->{comment} ) &&
            _is_new_post( $echo_list[0]->{'time'} )       ){

            # post to hatena bookmark
            _post2hatena( $echo_list[0]->{comment} );
        }
    },
);

$cv_timer->recv;

sub _is_new_post{
    my $post_time = shift;
    $post_time ||= 0;

    if( $post_time > $org_post_time ){
        $org_post_time = $post_time;
        return 1;
    }
    else{
        return 0;
    }
}

sub _is_bookmark_post{
    my $comment = shift;

    $comment ||= '';
    return $comment =~ /B\!/;
}

sub _post2hatena{
    my $comment = shift;

    my( $str , $url ) = split( /B!/, $comment);

    my $hatena = WebService::Hatena::Bookmark::Lite->new(
        username => $hatena_conf->{username} , 
        password => $hatena_conf->{password}
    );

    return $hatena->add(
        url     => $url,
        comment => $str
    );
}

以下が実験結果。

mixiで発言する

f:id:masartz:20091023003618j:image

はてブで確認する

f:id:masartz:20091023003619j:image


なんか出来ているように見えます。


とりあえず勢いすぎた反省ポイント。

・AnyEvent意味ない。

はい、、使ってみたかっただけです。

ここのところの流れに追いつきたいと思いつつ、触る機会を作れてなかったので、無理矢理です。

gihyo.jpで連載されている内容(http://gihyo.jp/dev/serial/01/modern-perl/0013)を参考にさせていただき、書いてみました。

別にこれならwhileでループすればいいと言われたら何も言えません。


・毎回スクレイピングしている

はい、、RSSフィードでも吐く形式にすれば良かったんですが、ちゃんと勉強します><

これのせいで、posttimeをずっと保持しておいて、それより最新だったら、なんて比較もしてます。お恥ずかしい限り。


もしくはmixiボイスにAPIでもあれば、一番ラクだったのに(多分、今はないハズ)


※ちなみに

$mixi->list_echo->parse();

$mixi->recent_echo->parse();

に変えると、マイミク全員のボイスをブクマできます。(だから何だ!)


今回も勢い余って痛さだけが残る形に終わってしまいました・・・

2009-09-25

『4Gbpsを超えるWebサービス構築術』読了 『4Gbpsを超えるWebサービス構築術』読了 - masartz->log を含むブックマーク はてなブックマーク - 『4Gbpsを超えるWebサービス構築術』読了 - masartz->log


昼休みにご飯食べながら読むという進め方だったせいもあって、かなり時間かかりましたが読み終わりました。


ライブドアが誇る技術が幅広く書かれているとの事でしたが、その内容は。


■Chapter1 Webサービスの概要と要素技術

タイトル通り、Webサービスというものの歴史とその概要についての章。

Webエンジニアとしてはアイスブレイクと捉えられないとちょっとマズいかもしれません。



■Chapter2 キューイング

負荷分散のよくある一つの解決策、キューイングによる後回し。

僕も普段から考えている場所だけあって、凄くすんなり読めました。

逆に言うとGearmanとTheSchwartzの概要説明に終始していたので、もうちょっと

ライブドアなりの工夫みたいなものが知りたいと思ったりしました。


ちょっと話がそれますが、YAPC::Asia2009でも思いましたがやっぱりこの

キューイングはトラフィックが多いサイトではもはや必須対応なのかと。

もともと使っていたsix apartをはじめ、livedoorでも(malaさんセッションより)、

はてなのコーポレートトラックでもTheSchwartzを使っているらしきことが

伺えたので各社でどんな感じなのかなーと改めて興味が沸きました。




■Chapter3 DBキャッシング

来ました、memcached。今の職場ではこれがないなんて想像出来ない。。。

そんな11211ポートに住まう偉大なシステムですが、確かに前の職場で普通のサイトを

運営する分にはむしろどんなもんかすら触る機会すらなかった。

ここでは導入の前提となるWebアプリにおけるDBのボトルネックの部分も

解説されているので、それも合わせて読みたいところ。

そして、書かれていますが便利な上に導入するデメリットがほとんどない

というのがmemcachedのいいところだと思います。


と言いつつ、僕もプロジェクトの関係上ガリガリ使えてる訳ではない、、、

引っかかるところなんかが書かれても良いかと思いましたが、まぁそういうノウハウは

ネット上に溢れているという割り切りで、それはそれでよいと思います。




■Chapter4 HTMLキャッシング

この辺からは個人的に名前と概要は知っているけど、使った事とかはあんまりない

という部分になってきます。

Squidなんかはまさにその典型。confファイルの例まで書かれているんですが、

リアクションが出来ない自分。同時に説明の図の中にある箱の数が飛躍的に増えてきます。




■Chapter5 検索サービスの技術

この本は全体的に章の最初というか導入だったり・前提だったりの説明が明瞭

に感じましたが、この章の「検索」という項目の前提となる検索方式・言語解析の仕組み

の部分に触れていたのが非常にわかりやすかったです。

この章も社内ではそれに特化して研究している人がいたりするので、自分が

あんまり触れてない。。




■Chapter6 入出力パフォーマンス

恥ずかしながら、Blackholeエンジンについて無知でした、、

そんなんを読み進めていくと、この章はタイトルから察する事が出来るように

内容が複合的。前の章の技術なんかも含まれてきます。

特に気になったのが「最終出力に近い部分でのキャッシュ」。理由まで読んでみると

確かに納得ですが、やはり細かい運用という意味ではちょっと聞いてみたいなと

思う部分があったりしました。

あとCache::Memcached::Managedはこれまた知りませんでした。あとで読みます、、




■Chapter7 分散ストレージ

タイトルはストレージとなってますが、物理的な話のみならず運用するモジュール

の部分にも踏み込んでます。

最初がNFSから始まったことに歴史を感じますし、そこから現在まで試行錯誤で

運用されているという事に実績を感じます。




■Chapter8 モバイルの技術

ここは他とはちょっと毛色が変わって、日本のモバイル事情を浅く広く紹介。

またまた弊社の話ですと、モバイルもある程度切り分けがされているので

普段それ程触れられてません。なのでちょっと遠めから眺める視線で読ませて

いただきました。

内容的にはYAPC::Asia2009のkazeburoさんのセッション内容を合わせて

確かめると良いのではないでしょうか。




■Chapter9 ネットワークを取り巻く技術

自分が一番弱いところ、低いレイヤーの話はホントにダメです。

ここは多分何度も読み直した方がいいな、、、

ここら辺は知識として知っておくだけではなく、実際に動かさないと真の理解には

繋がらないんだろうなとつくづく感じます。

1台のサーバーすら運用せず、ネットワークを学ぶのがそもそもの間違いな気がしているので

そろそろroot権限のあるようなレンタルサーバー借りるか、自鯖を立てるか

しなければと思いました。




■Chapter10 Webサービスの性能評価

大規模サービスにおいて必要なのは、新技術の投入。ただそれよりも現状のチューニング。

と感じさせる、これだけは・まずはこれからやるべし、っていう内容。

もしMySQLのEXPLAIN構文を知らない人がいたら絶対読んでおいた方がいいです。



■まとめ

やっぱり自分が何を知っていて、何を知らないかが凄く良くわかりました。

アプリケーションで意識するmemcachedなんかは普段触っているので、

すっと頭に内容が入ってくるし、キューイングの部分なんかは正直物足りませんでした。

逆に後半になってくると、若干くじけそうな程知らない事が多すぎる。。。

所詮自分はイチアプリプログラマーに過ぎないんだなと痛感させられました。


とてつもない巨大サイトでなくていいので、この10分の1のトラフィックのサイトを

こういう技術を使って作ってみたいなと思いました。

今の会社ではなかなかそういう事がしにくいのが難点ですけどね、、


ただ、僕のようにプログラマーな人が「エンジニア」になるのに何が足りないのか

検定試験的に読むのにはオススメな1冊でした。著者の方々、執筆ありがとうございました。

2009-09-13

YAPC asia 2009 まとめて感想 YAPC asia 2009 まとめて感想 - masartz->log を含むブックマーク はてなブックマーク - YAPC asia 2009 まとめて感想 - masartz->log

一応業務の一環で来ているので、会社用にレポートを書かないといけないのだけど、

数多あるまとめサイトとスピーカー本人様達のエントリを集めればそれで十分すぎると思ったので、とりあえず私的感想から。


◎前夜祭

yokohama.pm出張版。

・なにより自分が喋れなくて残念。準備不足でした。次回のyokohama.pm通常版ではまた何か喋れるよう今からネタ仕込んでおかねば。


ざざっと書くと

・acotiesさん: AnyEvent的ななにか(仮)

AnyEventとは何か、がホントに軽くわかった気がする。2週間くらいしか触ってないと言っていたのでスゲー


・spiritlooseさん: Schenker - DSL for quickly creating web applications in Perl

記述量の少なさが半端ない。最近思う事は他言語を知っている人は皆凄い。


・kawanetさん: YAPC::Europe 2009(ポルトガル)参加報告

海外のYAPCではトーク聞くのと同じ位BOFが重要。今回終わってみて確かに

そうだと思った。会場移動しまくりで疲れたし。


・k-z-hさん: PerlのWAF今昔

非常によくまとまった話でした。


・amachangさん: Web的ななにか

HTML5の話。DOMとは違う木構造とか初めて知った。JSですぐデモるあたりはさすがamachangだと思った。

本編には来ていなかったようで、懇親会とかで話したかったのに残念・・・


・sugyanさん: 全裸でワンライナー(仮)

全裸イナー!一番ウケてました。1行野郎としての男気を感じました。


・nekokakさん: SmokerっていうぷらっがぶるWAFをつくってみたよ!

「それPla」の一言で片付いてしまう動きが直前に発生しつつも、使いやすいと言われているものを使ってサクっと実際に作ってしまうあたりは見習わなければと思った。


・junichiro x btoさん: PHP的な何か(仮)

すみません、外にシュウマイ食いに行ってて聞いてませんでした><


・yusukebeさん: エロサイト管理者の憂鬱2

これほど感想の書きにくいトークもなかなかないけど、内容はともあれやっている事は凄かった。

世界は広い?/狭い?





◎YAPC本編

このペースで書いていくと終わらなそうなので、本編は省略・・・

それこそ皆書いてるしね。

でも、一番印象に残ったのはmiyagawaさんとtokuhromさんの1日目のPSGIのセッション。

とんでもない勢いで進んでいるプロジェクトだけど、もうまとまりつつあるって。。。

HTTP::Engineを元に再構成しつつ、既に作成されたアプリについては手を加える必要がないフォローつき。

PSGIは仕様

Plackは実装

この前提重要。とりあえず引き続きwatchしていこうと思います。


あとはコーポレートトラックも多くの企業が「自社でのperlの使い方」風なセッション内容になっていて、JPAが目指すperlの啓蒙という意味で良かったのはないかと。six apartの使用ツール群の紹介がおもしろかった。


今回一番関わりが深かったのが、id:nekokakさんの「Qudo」のセッション。

自分も開発をお手伝いさせてもらっているものだったので、どういった反応が出るか結構ドキドキしてた。


フタを開けてみると、同時間のセッションがどれも魅力的だったため思ったより人少ない^^;

かと思いきや、質問タイムにはdanさんやyappoさんから質問来たり。どれも的確な内容でした。


セッション終了後に、Lin You-Anさんさんからの英語の質問にあたふたしつつ、ちょうど僕も

欲しいと思っていた複数ジョブの一括管理(っぽい事だと思う)機能を求められたりしていて、これは発表して正解だったというか、宿題がたくさん出来て良かったと思いました。

最近あんまり触ってなかったので、これを期にちょいちょいコミットしようとモチベーション上がりました。


懇親会ではもっと色んな人と話たいと思いつつ、道半ばでした。それでも

退職された元同僚の方々

yokohama.pmでお世話になっている方々

などなどをはじめ、1日目のLTでイカしたマイク持ちをしていたkamipoさんなんかとも

お話させていただき楽しかったです。


さて、来年こそは自分がトーク出来るようになってみたいなと思います。

LTこそヘタな事が出来ない場だとわかったので、本編で。

id:precuredaisukiさんとも話してましたが、やっぱりちゃんと喋ろうとすると20分くらい

使いますよね、という考えにも至極納得しました。


今回、実は2日目のmiyagawaさんのLTに向けて、手元のCPANモジュールをアップしておいたのですが、

どうやらあのトークの最中にアップしないと意味なかったみたいですね、、、

唯一参加している気分になれるかもと淡い期待をしてましたが、残念でした。。




なにはともあれ,lestrratさんをはじめ運営者の方々(ボランティアの方含め)お疲れさまでした。

次回も楽しみにしています。