モダンPerl入門の読む順番

モダンPerl入門 (CodeZine BOOKS)


前回なんとか1章を読みましたが、やっぱりよく理解出来てなかったのと2章に至っては「???」だったので、読めそうなところから読んで行って、一通り読み終わりました。


んで、僕のような初心者向けの読む順番として経験から一考察を。
一応目次には

==========
初心者
9章
1章、2章
==========

==========
Web系の方
4章
5章
6章
3章
==========

==========
システム管理を行っているかた
1章
5章
8章
==========


というような振り分けがなされています。


僕の感想としては、
(9章) ⇒ (「1章の6ページまで」) ⇒ (6章) ⇒ (3章→4章) ⇒ (7章→5章→8章) ⇒ (1章→2章)
かなと思います。

9章

9章はホントに「Perlとは」っていうところについて。「perlCPAN」と取れなくもない図式のCPANについてもフォロー済み。


次はおまけですが、Moose前までのPerlOOPをもし知らなければひとまずというレベル。

6章

ついで6章。テスト、テスト、テスト。単体テストからApache::Testまで網羅されてます。
その一方で「サーバーを通してしかテスト出来ないのは設計としてNG」という事も触れられて反省。開発手法はT
DDですよね、そしたら勉強する順番だってテストが先ですよね(違

3,4章

そしてなんだかんだ言っても現時点最も普及しているだろうフレームワークとORマッパーのお話な3,4章。
歴史的な流れも含められている点が凄いです。どのプロダクトが流行っていたり、どういう風に設計方法が移り変わったり、という部分も触れられています。
この辺はネットで検索しても往々にして古い情報(「Catalyst::Plugin」とか)が出てきたりするので・・・。
ここら辺は書けばそれだけで1冊になるレベルですが、分量としてすごくコンパクトにまとめられていて素晴らしい感じでした。

5,7,8章

5,7,8章はガッツリ開発というよりも保守・運用で継続してシステムを触っていく上でのTips。
非同期化したり、チューニングしたり、Cのライブラリ使って最適化したりと言った感じですね。


自分としては5章のforkの部分をすっ飛ばして非同期処理とか触っていたので、ちゃんと勉強しないと猛省。


XSについては、単純に移植するというよりもレイヤーが全く違う事だと思っているので、位置的には「ソフト(アプリ)⇔ハード」くらい距離感があるものかと思っています。
たまに聞く失敗談でperlで実装すべき部分までXSに持っていっちゃった。という「車輪を作るつもりが自動車作ってた」感じとか住み分けもちゃんと考えないといけないし。

1,2章

そして、最後に残るもの「Moose」。ぶっちゃけここまで読まなくても、明日から半年(3ヶ月?1ヶ月?)後の業務に支障はないと思います!?が、そんなことよりなにより、ここを読まなきゃこの本を買った意味がない。ということで読んだ方がいいです。


内容については・・・別でまとめたいと思います>< さて、もう1回読み直すか。。。

モダンPerl入門感想 第1章

本日購入の「モダンPerl入門」。さっそく読んでみたのでその感想を。


まずは、本当に『モダン』だという事。
7ページ目にして自分にとっての未知数であるMoooooooose!


この1章だけでMooseオブジェクト指向の基本とRoleの概念を理解出来る(ように素人には読める)という充実のボリューム。


Mooseは書き方がそれまでのPerlOOに比べるとかなり独特であり、記述量も少ないので今までも色んな人のソースを見ていたけど、なかなか理解出来ず・・・
やっぱり書いてみなきゃわからんということで、真似して書いてみました。


hello_world.pl

  1 #!/usr/bin/perl 
  2 
  3 use strict;
  4 use warnings;
  5 
  6 use lib './lib';
  7 
  8 use HelloMoose;
  9 use HelloMoose::Date;
 10 
 11 my $hello = HelloMoose->new(param => 'Moooooose' );
 12 $hello->message;
 13 
 14 my $hellodate = HelloMoose::Date->new(param => 'Moooooose' );
 15 
 16 $hellodate->message( scalar(localtime()) );
 17 exit;
 18 


lib/HelloMoose.pm

  1 package HelloMoose;
  2 
  3 use Moose;
  4 
  5 has 'param' => (
  6     is       => 'rw',
  7     isa      => 'Str',
  8     required => 1,
  9 );
 10 
 11 __PACKAGE__->meta->make_immutable;
 12 
 13 no Moose;
 14 
 15 sub message{
 16     my $self = shift;
 17 
 18     print 'Hello '. $self->param ." World \n";
 19 
 20 }
 21 
 22 1;


lib/HelloMoose/Date.pm

  1 package HelloMoose::Date;
  2 
  3 use Moose;
  4 
  5 extends 'HelloMoose';
  6     
  7 override 'message' => sub{
  8 #around 'message' => sub{
  9     my $self = shift;
 10     my $date = shift;
 11 
 12     print 'Hello '. $date .' '. $self->param ." World \n";
 13 
 14 };
 15 
 16 no Moose;
 17 
 18 1; 

以下が実行結果。

% ./hello_world.pl
Hello Moooooose World 
Hello Tue Feb 10 00:10:47 2009 Moooooose World 


という感じで使い方合ってるのかはわかんないけど、動く!!
ただ、これをoverride → aroundに変えるといきなり怒られる。。。

% ./hello_world.pl
Hello Moooooose World 
Can't call method "param" on unblessed reference at lib/HelloMoose/Date.pm line 12.


この辺でいきなりつまづくあたりがいかにも自分らしい訳ですが・・・


もともと、beforeとかoverrideが「継承」というよりは「Hook」のような挙動っていう風に読めたので(継承元のメソッドはそれ単体で実行されるあたりが)、aroundとの違いを色々いじりながら見ようと
思ったら意外なエラー><


こういうのはやっぱりソース見ないとダメかなーと思いつつ、今日は終了。
次の2章もMooseを前提としたデザパタの話になってるので、もうちょい1章でゆっくりしてから進もうと思います。



=====


追記:
やっぱり書いてあるべきところには書いてありました
ググレカスということですねorz

githubにコミットしました

前回の
http://coderepos.org/share/browser/lang/perl/TheSchwartz-Worker-Plugin-Manager

http://coderepos.org/share/browser/lang/perl/TheSchwartz-Worker-Plugin-Hook
の形にリネームして再コミットしておきました。


んで同じものをgithubにも投入しました。
http://github.com/masartz/the-schwartz-plugin-hook/tree/master


Plugin-Logの方は
http://github.com/nekokak/the-schwartz-plugin-logger/tree/master
こっちの方が素晴らしいので自重しました。


最近皆様絶賛移行中のgitですが、
手元のMac OS X(Leopard)の環境では
sudo port install git-core +doc++svn
で一発で通りました。
『git』ではなく、『git-core』なのがポイントなのだとか。
オプション他にもいくつかあるんですが、とりあえずこんだけで充分かと。


最初混同してたんですが、
・git(コマンド)のインストール
githubのアカウント及びリポジトリ作成
は全く別物なんですね。。。orz


ということで、
http://webtama.jp/series/aorserver/articles/18
こちらなどの参考にアカウント作成も完了。


テストも兼ねて、冒頭のPlugin-Hookをcommitしたんですが、よく見ると、、、
http://coderepos.org/share/browser/lang/perl/TheSchwartz-Worker-Plugin-Hook
http://github.com/masartz/the-schwartz-plugin-hook/tree/master


「the-schwartz-plugin-hook」になっとるやないかい・・・。


ありえない事に既に何人かwatchしてくださっていて、今更変えられない。。。
「the-schwartz-plugin-hook」だと名前の意味広がっちゃってるし><
すみません、すみません、すみません。workerのHookです、ご了承ください。

codereposにTheSchwartzのプラグインをコミットしました

http://coderepos.org/share/browser/lang/perl/TheSchwartz-Worker-Plugin-Log
http://coderepos.org/share/browser/lang/perl/TheSchwartz-Worker-Plugin-Manager

◎TheSchwartz-Worker-Plugin-Log
 実際に案件で使った際のログ仕様をほぼそのまま載せてしまっているのですが、
 - pathとfileを指定して、任意のディレクトリにログファイルを吐く
 - 日付でローテーションされる
 週ごとにログに吐きたいとか、そもそもDBに保存したいとかいう
 要望には全く応えられない程度のシロモノです。
 なので、今後の修正もその辺を念頭に考えてます。


◎TheSchwartz-Worker-Plugin-Manager
 とりあえず名前訂正します><
 - TheSchwartz::Worker::Plugin::Hook
 - TheSchwartz::WorkerHookable
 とかそういう系であるべきですね。
 もともと色々くっつけて「Manager」とか作ってたのを、Hook部分しか
 残ってないので、これはこれで名前空間切るべきですね。


 内容としては大したことしてません。
 一応流れとしてはworkerは一度動かすと動きっぱななので、
 ジョブの処理内容のライブラリが更新された場合なんかに再読込したい
 っていう要望が最初にありました。
 それやるんだったらworkとは別にpre_workみたいに別のところで
 事前に書きたいよね、っていう流れでうまれました。


 テストにはid:nekokakさんが作っているTheSchwartz-Test
 ほぼそのまま使わせてもらってます。
 

yokohama.pm #3に参加してきました

先週の金曜日はyokohama.pm #3に参加させてもらいました。
聴講者としては過去2回とも参加済みでしたが、今回は
何故かスピーカーという立場でLTをしてきました。

資料は以下に置いてあります。
http://www.slideshare.net/masartz/the-schwartz-presentation


◎反省点
・資料がパワポ形式
 id:nekokakさんを倣ってsporkを使おうと思ってましたが、どうもインストールに手こずる。
 /usr/binとかにコマンドが出来ないという事象に追われ、面倒なのでパワポにしたら
 windowsで作る→macopenofficeで開く→バグるorz
 spork問題は開催前日くらいに「コマンドファイル持ってきちゃえば?」の啓示で解決したので、
 次回はそっちも使ってみようと思います。

 
・内容に工夫を
 もうちょっとコードとか、デモとか出来たらいいなぁと思いましたけど、
 5分だとあれが限界でしょうか。。。ただ笑いは必要だと痛感しますた。

 余談ですが、高橋メソッドは慣れてないとなかなか難しいですね。ある程度ちゃんと順を
 追って説明する場合には1ページにいくつかの箇条書きが必要かと思いました。
 
 あとは、マイクの使い方だったり、喋りの部分は初ということもあって、想定内の
 ダメっぷりでした。


・実装が中途半端だった
 もうちょっと作りこんでから発表したかったというのが本音ですね。
 テストが書けてないモジュールなんて、あってないようなものですし。
 

◎イベントそのものの雑感
id:typesterさん++
 一番印象深かったのが、id:typesterさんのライブコーディング。
 事前でも何回も練習していたと仰っていましたが、それでもあの短時間でプロダクトを
 作り上げたのにはビックリでした。
 「使う時をイメージしてテストから書く」「いまどきはMooooooose」などハイレベルな
 設計も凄かったですし、emacsのカスタマイズっぷりも興味がありました。


・初めての方も是非トーク
 今回自分のようなヘタレもトークさせてもらいましたが、yokohama.pmはそういう敷居の
 低さが良さであって、貴重な体験をさせてもらいました。今後も新人枠を
 残してもらいつつ、色んな方のトークが聞きたいと思いました。


・機会があれば、また喋りたい
 今回やってみて、まぁ当然ながらダメダメな部分が多かったわけで、そういう
 意味でも別の機会でリベンジがしたいと思いました。


◎幹事の皆様、お疲れ様でした。
 参加者が増え続ける中、id:clouderさん、id:zigorouさんをはじめとする皆様、
 毎回異なる会場(次回からは今回のところで固定という話も?)探しや懇親会の手配など、
 スムーズな運営に尽力していただきありがとうございました。-

TheSchwartzの拡張:続き(Prefork,log)

前回の日記からもうちょい進めてみました。

http://code.google.com/p/theschwartz-plugin/source/browse/#svn/trunk

とりあえず、以前に適当に作ってたリポジトリのブランチ作業というのが
猛烈に恥ずかしくなったので、新プロジェクトにしてみました。
前回が適当すぎてゴメンナサイ。
節操なくプロジェクト作ってゴメンナサイ。

変更点は
・log機能の追加実装
・ForkをParallel::FockManagerからParallel::Preforkへ
・それらを使うManagerを作成
の3点になります。


◎log機能
これは実際、社内のプロジェクトにTheSchwartzを導入したときに
取り入れたもの。
そのプロジェクトでは、割と重要処理のトリガとしてTheSchwartzを
使っていたので、やりっぱなしというのはマズかった。
が、本体にはファイル出力系のログがない。
(エラーが発生すると、標準のerrorテーブルにインサートされるという意味でログはある)
ということで、処理結果用のログを残すものを実装してみた。

ちょっと冷静になってみると、社内で使ったままの状態で
日付ごとに管理される部分なんかが丸々残っているけど、
この辺ももっと緩くしてもよかったかもです。。。。


◎ForkをParallel::Preforkへ
前回のエントリ時点ではParallel::FockManagerを使っていましたけど、
シグナルに対応するのにPreforkが良いというのを聞きまして、
ちょっといじってみました。

結果的にはうまく行ったように思えるというか、
id:tokuhiromさんのを参考にさせてもらったらほとんど一緒になっちゃいました。あわわ。。
http://d.hatena.ne.jp/tokuhirom/20081110/1226291955


◎Managerを作成
前回ので、もうちょっとスマートに呼べるようなクラスを用意すべきかも、と
自問自答してた部分の一つの解決策ということでManagerとでっちあげた
ものを作ってみました。
管理するというよりはラップしてるだけ程度のものですが。


◎動作実験
プロジェクト直下にある
・manager_client.pl がジョブのインサート側、
・test_manager_worker.pl がワーカー側です。
処理される内容は
・lib/MyApp/Async/Test3.pm
・lib/MyApp/Async/Test4.pm
にそれぞれ書かれているあたりは前回と同じです。

MyApp::Async::Test3 1226941406 moge : 3
MyApp::Async::Test3 1226941406 moge : 1
MyApp::Async::Test4 1226941408 fuga : 2
MyApp::Async::Test4 1226941408 fuga : 3
MyApp::Async::Test4 1226941410 fuga : 4
MyApp::Async::Test3 1226941410 moge : 2
MyApp::Async::Test3 1226941412 moge : 4
MyApp::Async::Test4 1226941412 fuga : 5
MyApp::Async::Test4 1226941414 fuga : 1
MyApp::Async::Test3 1226941414 moge : 5


◎次回
テスト書きます。
はい、ホントすみません><
ありえないです。
手探りでやってたので、とりあえず作る事に意識がいってました。

とは言いつつ、ラップしてるのが全体的に多いですが、
こういうテストってどうやって書くのがいいんでしょう。。

TheSchwartzでforkとモジュールの動的リロードを実装実験

http://code.google.com/p/themasartz/source/browse/#svn/branches/workerbase

ひとまず暫定で↑にコミットしてありますが、構成としては

/test_client.pl
/test_para_worker.pl
/test_worker.pl
/test_worker2.pl

/lib/MyApp/Async/Test.pm
/lib/MyApp/Async/Test2.pm

/lib/MyApp/Hoge.pm

/lib/TheSchwartz/Worker/Plugin/ModuleReload.pm
/lib/TheSchwartz/Worker/Plugin/Parallel.pm

こんな感じ。

上から順に。

・/test_client.pl
ジョブを突っ込むpl。2種類のジョブを投入
・/test_worker.pl
・/test_worker2.pl
1種類ずつのジョブを処理するworker。
一般的なTheschwartzのworkerで言うと、package main; に相当する部分。
・/test_para_worker.pl
後述するfork処理によって、これひとつで複数のジョブを処理します。


・/lib/MyApp/Async/Test.pm
・/lib/MyApp/Async/Test2.pm
それぞれ、test_worker.pl or test_worker2.plのジョブの実態。
一般例で言うところの、package Myworker;的なところにあたります。


・/lib/MyApp/Hoge.pm
でっちあげモジュール。
動的再読み込み試験用で、外部モジュールが都度読み込まれることを
返却値いじることで実験するため。


・/lib/TheSchwartz/Worker/Plugin/ModuleReload.pm
・/lib/TheSchwartz/Worker/Plugin/Parallel.pm
一応今回のメイン。
ModuleReload.pmはHTTP::Engine::Plugin::ModuleReloadをそのまま参考にしただけです><

Parallel.pmも基本Parallel::ForkManagerを使っただけだけど、
test_worker.plあたりでは、ジョブの実態pmをuseしていたけど、そこをこっち側で巻き取って、UNIVERSAL::requireで読み込ませています。


これで、実行すると以下のような結果になってほしい。。。

$VAR1 = {
$VAR1 = {
'hoge' => 'moge : 3'
};
MyApp::Async::Test aaa
'hoge' => 'fuga : 3'
};
MyApp::Async::Test2 aaa
$VAR1 = {
'hoge' => 'moge : 1'
};
MyApp::Async::Test aaa
$VAR1 = {
'hoge' => 'fuga : 4'
};
MyApp::Async::Test2 aaa
$VAR1 = {
$VAR1 = {
'hoge' => 'fuga : 5'
};
MyApp::Async::Test2 aaa
'hoge' => 'moge : 4'
};
MyApp::Async::Test aaa
$VAR1 = {
'hoge' => 'fuga : 1'
};
MyApp::Async::Test2 1226509002
$VAR1 = {
'hoge' => 'moge : 5'
};
MyApp::Async::Test 1226509002
$VAR1 = {
$VAR1 = {
'hoge' => 'moge : 2'
};
MyApp::Async::Test 1226509004
'hoge' => 'fuga : 2'
};
MyApp::Async::Test2 1226509004


残課題としては、
lib/TheSchwartz/Worker/Base.pm
を作って、ModuleReload.pmとParallel.pm
を抱えるようにもしたいです。

test_para_worker.plからは

my $para = TheSchwartz::Worker::Base->new();
$para->para_work( $client , \@jobs);


みたいな感じで呼べるように、
lib/MyApp/Async/Test.pm
では、

$self->reload();

みたいに再読み込みできるようにするとかでしょうか。。。


このBase.pm自体がTheSchwartz::Workerを継承する形になると
思うのに『Base』ってどうなんでしょう。。。