Yokohama.pm #8 に参加してきました

blogを書くまでがYokohama.pmです。たぶん。


金曜日はYokohama.pm #8に参加してきました。
今回は僭越ながら発表させていただきましたので、資料は以下に置きました。
http://masartz.github.com/presentation/yokohamapm-8/start.html


ustもどうやら下にアップされているようです。
http://www.ustream.tv/recorded/18590454


YAPC::Asia 2011で話せなかった後悔から勢いで申し込みましたが、なんとか喋りきりました。
練習では全然尺におさまってなかったんですが、本番は時間ぴったり。資料にも混ぜてますが、「ここで半分」みたいな区切り入れるのを真似して良かったです。


内容については、コードはほとんど出てこなくて、最近やってたお仕事の業務報告的な感じですが、今までとちょっと違う事をやったので色々と知る事が多かった点を話してみたいと思ってやってみました。


最後にも触れましたが、「大規模すげーわ、マジすげーわ」という事が言いたい訳でもなく、
「マネジメントキツいわ、マジキツいわー」という事が言いたい訳でもなく(というか俺リーダーじゃない・・・)、
日々黙々としている仕事について発言してみる事も自分や誰かのためになるんじゃないかなと思います。


個人的には、今後はまたちょっとやる事変わりそうなので、このように振り返って残しておけて良かったかなと。


一部でてきたコードの部分について、早くもその場でアイコンカッコ良い人から突っ込み入りましたが、その後オンライン/オフラインで話して、結論としては資料のサンプルが良くなかった。。


bindのミスならnamedプレースホルダを使えばおk、というご指摘はまさに仰る通りです。同じように突っ込む方もいるかもしれませんので、少しだけ補足すると、
bindはサンプルとも言えないただの例で、要は「実際にInsertメソッドをよびだしたあとの結果をdbから引き直して中身チェック」っていうことがしたかっただけで、bindに限ったアプローチという訳ではありません。
これは基本的に動的にSQL文を作らない開発フローにも起因するので、多分これでも説明できてない・・・、この辺についてはもうちょっと自分の中でも再検討が必要なようです。




事前にclouderさんにはご相談させていただいたのですが、今回実は会場の入り口に弊社のちょっとしたグッズを置かせていただきました。
前回に引き続き今回の会場も、livedoor社さんの技術部会が支援してくださった会場であり、その場に他社のグッズを置く事を快く承諾してくださったclouderさんとlivedoor社さんに改めてお礼申し上げます。ありがとうございました。
会場自体もWifi提供など充実しており、非常に快適でした。


直前まですったもんだした懇親会も見事に確保したmyfinderさんも++でした。あのもつ鍋は旨かった!


そんなこんなでお疲れさまでした。
また次回楽しみにしています!

YAPC::Asia 2011に行ってきました

blogを書くまでがYAPCです。
今年も行われたYAPC::Asia 2011に前夜祭含め参加してきました。


トークの細かい内容とかは例によってhirataraさんの記事が一番詳しいのではないかと
思いますし、各スピーカーの方々が資料をアップされているので、そちらを参照すれば良いでしょう。


個人的には、去年はスピーカーとして発表させていただいてダメダメだったので、
今年はリベンジの意味でもう1回トークしたいと思っていたのに出来なかった事が
一番の反省要因です。


トークについては、ベストスピーカー賞に輝いたfujiwaraさんのトークは実際に聞いていて
実は投票もしていたのですが、話がすごく具体的かつ流れがある内容でおもしろかった。


zigorouさんの内容についてはdep-opsな同僚の人と聞いていて、アプローチや環境の違いについて
話したりしてました。課金に絡む部分だとトランザクションが多くなるのがその辺の違いに
現れてるかも、という見解には納得でした。


とかとかあるんですが、今年もたくさんの方と話す機会があって、もうトークよりそっち
メインだったんじゃないかという気もしてます。


印象に残っていること

  • 前夜祭でkanさんに、懇親会で刺身さんに、空気読まずにRubyの話を聞いたけど、丁寧に教えてもらってすごく嬉しかったです
  • 前夜祭LTのkamipoさん発表で、「最新20件を取る時、先にフォロワーの最新投稿者20人を絞り込む」というアプローチはなるほどと思った
  • 大規模サイトを運営している某社では、デプロイタイミングが定期的ではないらしい&テストは通らないとコミットできない仕組みになってるとか。
  • 2日目のyappoさんのLTで社内nopasteを作ったと言ってたので、これは確かに便利かも、あった方がいいかもと思った。それだけでなく、社内の情報をどう収集し、どう活かすかなどLTとは思えない密度だった。

今回発表できなかったのは残念ですが、この反省を活かさないとな。と思いました。
懇親会でclouderさんに「次のyokohama.pmいつですか?やりたいです」って話してたんですが、
近々開催しそうですね!YAPC熱が冷めないうちに「次のyokohama.pmではなんか喋ります!」ってここで言っておきます。




最後になりますが、運営スタッフの皆さん、ボランティアの皆さんお疲れ様でした。
会として過去最高の規模だったようですが、過去と比べても非常にスムーズな運営をされているように感じられました。
今回で最後と言わず、来年もぜひ開催してほしいです。


最後の最後におまけですが、今回一番の収穫。
milanoさんの豪腕で、とても貴重なダブルネームサイン入りTシャツになりました。
来年トークする機会があったら、これ着て喋りたいですね。(逆に普段着れない・・・)

svn の timelineを人別にsortして表示する

svn + tracという組み合わせを使っているプロジェクトで
timelineを見ればコミットされた一覧が俯瞰できるわけですが、
githubみたいに人単位でどういうコミットをしているのがわかると、
便利な事もあるかなと思って、軽く作ってみました。(というかまだ進行中)


https://github.com/masartz/sort_timeline


plackup app.psgi で起動して、http://localhost:5000/feed に
アクセスするとcodereposXML Feedを元にした情報が見られるようになってます。
対象とするTracのfeedはconfig.plのURLの値を書き換えれば、他でもできます。


ぱっと思いついたのがcodereposとかplaggertracだったのですが、
最近のコミット量からしてあまり履歴がないので、伝わりにくいかもしれません・・
業務等で活発なtimelineがある所の方はそっちに向けていただくとわかりやすいかも。


というようにRSSフィードだと当然時間と共に消えてしまうので、http://localhost:5000/log
とかをアクセスすると、過去の全履歴が見られるように、ログファイルなのか簡単なDBなのかを
用意して、そっちからデータを取るようにできればいいかなとか妄想してます。


psgiアプリも書き慣れてないので、まずはapp.psgiにゴリっと書いてみたり、
jqueryサンプルサイトからコピペしただけとか、まだ全体的に適当なので、整形していくつもりです。

「優れたPerlプログラマを見分ける27の質問」に回答

元ネタはこちら
http://d.hatena.ne.jp/gfx/20110301/1298944990


回答例はこちら
http://blog.livedoor.jp/dankogai/archives/51645218.html


以下、やってみました。

1. Perl5において変数のシジルが示すものは何か
 → $,@,%,*。スカラー、配列、ハッシュ、型グロブ
 →○

2. 配列のアクセスする際の $items[$index] と @items[$index] の違いは何か
 →$items[$index]は@items配列の$index番目の要素へのアクセス。
 →@items[$index]は%itemsハッシュの$indexをキーとする値へのアクセス。
 →× @items{$index} と勘違いしてた。。

3. == と eq の違いは何か
 →「==」は数値比較。「eq」は文字列比較
 →○

4. ハッシュをリストコンテキストで評価すると得られるものは何か
 →%hash = ( a => 1 , b => 2); だったら、 ( 'a' , 1 , 'b' , 2)の4要素を持つ配列
 →△ この順番とは限らないか・・

5. Perlドキュメントからキーワードを検索するにはどのようにするのか
 →わからなかった・・・
 →× perldocなのか。

6. Perl5における関数とメソッドの違いは何か
 → MyApps::hoge($param) だと第一引数が$paramで、MyApps->hoge($param)だと「MyApps」が第一で、$paramは第二。
 →○

7. Perl5が変数のメモリを再利用するのはいつか
 →わからない><
 →×

8. 変数のスコープがデフォルトでレキシカルであると保証するにはどのようにするのか
 → 「my」 で宣言する
 →○

9. モジュールからシンボルをインポートするにはどのようにするのか
 →?
 →× 設問が読解できてないので論外

10. perlがモジュールのロードを敢行するディレクトリの操作はどのようにするのか
 →「::」を「/」に変換して検索?
→× 適当に書きすぎた

11. Perl5のエラーメッセージの検索はどのようにするのか(発生するエラーメッセージに説明を加える方法を知っていればボーナスポイント)
 →?
 →×

12. 配列を関数に渡したときに起きることは何か
 → $class->func( @ary , $scalar );だったら、sub funcで$scalarを判別することは無理。@_の中に全部まとめて入ってしまうので。
 →× そういうことじゃない

13. 複数の配列をそれぞれ区別して関数に渡すときにはどのようにするのか
 → リファレンス渡し。$class->func( \@ary1 , \@ary2 , \@ary3 );
 →○

14. 呼び出された側から見た return; と return undef; の違いは何か
 → @result = sub func{ return; }; if @result は偽だけど、
   @result = sub func{ return undef; }; if @result は真。「undef」という要素が@resultに入っている。
 →○かな?

15. 標準的CPANディストリビューションではテストはどこに置かれるか
 → t/配下
 →○

16. 標準的CPANディストリビューションでテストを走らせるにはどのようにするのか
 → perl Makefile.pl → make → make test。
 →○

17. CPANから新しいディストリビューションをインストールする際に使うコマンドはなにか
 → cpan install App::cpanminus
 →○ そして、以後はcpanmを・・・

18. 組み込み関数openを3引数形式で使うのは何故か
 → ファイルハンドルをレキシカルスコープにするため
 →△ 微妙にズレてる

19. openのようなシステムコールのエラーを検出(と報告)するにはどのようにするのか(エラーの検出と報告を自動的に有効にする方法を知っていればボーナスポイント)
 → eval{};でくくって、 $@で検出?
 →× なんか読み違えてた

20. Perl5で例外を投げるにはどうするのか
 → die; もしくは Carp::croak;
 →○

21. Perl5で例外を捕捉するにはどうするのか
 → eval{};でくくって、 $@で検出?
 →○

22. ファイルの読み込みにおけるforとwhileの違いは何か
 → わからなかった。。
 →× 猛省します


23. メソッドと関数においてパラメータ*3を取り扱うにはどうしたらよいか
 → $param = shift; で取ると、@_から先頭要素を抜く。 ($param1 , $param2 ) = @_; で取ると、@_からコピーで取得。
 →○

24. my ($value) = @_; の変数を囲む括弧が意味するものは何か、またこの括弧を取り除くと何が起きるか
 → わからなかった。。
 →× 言われてみりゃ、そりゃそうだ・・・

25. new は組み込み関数ないしキーワードか
 → No。
 →○

26. コアライブラリやCPANモジュールのドキュメントを読むにはどのようにするのか
 → perldoc perl
 →○

27. ハッシュの値のみを取り出したい時はどのようにするのか
 → my $result = value ( %hash );
 →× 地味に「value『s』」だったorz

結果
○:14
△:2
×:11


なんていうか、50点・・・。8割で優れているとのことなので、
27 * 0.8 なので22問以上は答えられるよう頑張らないといけないですね。。
ダメすぎて凹んでますが、晒すネタとしてちょうどいいかも。

pm-uninstallで『localな環境』のコアモジュールを消せるアップデートをしていただきました

この前の文字コード問題で、local::libで作った手元の環境だけ
Encode.pmをアップデートしてテストなどしていました。


この辺は今は「 cpanm -l ~/local Encode 」でサクっと出来てステキですね。
そして、実験終了後に消そうと思って、

pm-uninstall -l ~/local Encode

とやったんですが、

Encode is Core Module!! Can't be uninstall

と怒られてしまい、終了。


どうやら過去の経緯からコアモジュールは削除できないようです。


確かに通常のlibの下で考えるなら気軽に消せてはマズイという事で
正しいのですが、同じようにlocalにな環境に入れる場合はないのかな、
ということで #perl-casualで相談してみたところ、即効で対応していただけました!


http://search.cpan.org/~xaicron/App-pmuninstall-0.16/


特にオプション等を増やして実行する必要はなく、対象がコアモジュールでも
コア以外のところ(local等)にインストールされているもので、コアなlibにはちゃんとそれがある、
という確認が出来れば削除するようにしていただきました。


上の判定による対応は非常にスマートで、相談する前の時点では -f のオプションで消せるようにして
欲しいくらいのお願いをするつもりだったので、相談してみて良かったです。


すばやく対応していただいたxaicronさん++

utf8とEncodeの焼きまわし記事

2011年にしてようやくutf8と向き合うことになりました。
と言っても、95%は「原則」を正しく読めば解決しました。
エントリとしては過去情報の焼き増しになるけど、一応メモとして残しておく。


原則
http://d.hatena.ne.jp/tokuhirom/20080408/1207619640
http://perl-users.jp/articles/advent-calendar/2009/casual/10.html


特にxaicronさんのエントリを改めて読み直したらカンペキにまとまっててすごい!Advent Calendar++


最初に認識しておくこと
sjisな世界、eucな世界、utf8な世界は他のレイヤーでもあるが、utf8フラグが立っている世界はperlの中にしかない」


今回困ったのは、

Cannot decode string with wide characters. 〜

のように出た場合と

Wide character in print 〜

が出た場合。
後者はフラグが立った状態でprintした場合なので、encodeして内部文字列じゃなくしてからprintすればおk。


上記原則に則るとまずdecode処理をするわけですが、
Encode::decodeはすなわちutf8フラグを立てることであって、既に立っているものに対して
実行すると上記エラーが発生します。
なので基本は「入口 -> decode-> 処理 -> encode -> 出口」 なんですが、
入口の時点でutf8フラグが立っている場合に備えて、フラグが立っているか確認したほうがいい。
入口が完全に外界のみならば、フラグが立った状態で来ることはないわけだけど、perlの世界における外界からの場合はその可能性がある。これが今回混同してたところ。


実際の処理の中は

  • use utf8; されている(その中で扱う文字列には自動でフラグが立つ)
  • ファイルそのもののエンコーディングがutf8になっている

という前提でいくと、「フラグが立っていない場合のみdecodeする」で状態はめでたく統一される。
もし仮に、フラグが立ってない世界を構築しているのであれば、「立っていたらEncodeする」ことで同じくデータ的には揃った状態になる。

#!/usr/bin/perl
             
use strict;  
use warnings;
             
package UTF8World;
             
use strict;  
use warnings;
             
use Test::More;
use Test::Warn;
use Encode;  
use utf8;    
             
sub function_of_utf8world{
    my $charset = shift;
    my $arg_str = shift;
             
    my $flagged_utf8;
    if( Encode::is_utf8( $arg_str ) ){
        diag 'arg_str is flagged utf8';
        $flagged_utf8 = $arg_str;
    }        
    else{    
        diag 'arg_str is not flagged utf8';
        $flagged_utf8 = Encode::decode_utf8( $arg_str );
    }        
    ok Encode::is_utf8( $flagged_utf8 ) , 'flg ON';
             
    warning_like { print STDERR $flagged_utf8 } qr/^Wide character in print/ ,q/Wide character in print/ ;
             
    $flagged_utf8 .= 'フラグON';
             
    return Encode::encode( $charset , $flagged_utf8 );
             
}

package OutWorld;
             
use strict;  
use warnings;
use Test::More;
use Encode::Guess;
{            
    use utf8;
    my $flg_on_utf8 = 'あ';
    no utf8; 
             
    ok Encode::is_utf8( $flg_on_utf8 );
             
    my $ret = UTF8World::function_of_utf8world( 'utf-8' , $flg_on_utf8 );
             
    ok ! Encode::is_utf8( $ret );
    my $enc = guess_encoding($ret, qw/ shiftjis euc-jp /);
    is $enc , 'shiftjis or utf8' , 'flg on utf8';
}            
             
{            
    use utf8;
    my $str = 'あ';
    no utf8; 
    my $flg_off_utf8 = Encode::encode_utf8( $str );
             
    ok ! Encode::is_utf8( $flg_off_utf8 );
             
    my $ret = UTF8World::function_of_utf8world( 'utf-8' , $flg_off_utf8 );
             
    ok ! Encode::is_utf8( $ret );
    my $enc = guess_encoding($ret, qw/ shiftjis euc-jp /);
    is $enc , 'shiftjis or utf8' , 'flg off utf8';
}            
             
{            
    my $str = 'あ';
    my $euc = Encode::encode( 'euc-jp' , $str );
             
    ok ! Encode::is_utf8( $euc );
             
    my $ret = UTF8World::function_of_utf8world( 'euc-jp' , $euc );
             
    ok ! Encode::is_utf8( $ret );
    my $enc = guess_encoding($ret, qw/ shiftjis euc-jp /);
    is $enc , 'shiftjis or euc-jp' , 'shiftjis or euc-jp';
}            
             
             
done_testing();

=================================================================
2011.02.21追記
nihenさんより、ブクマコメントいただきまして、以下のリンクを見ました。
http://subtech.g.hatena.ne.jp/miyagawa/20080218/1203312527
同じ事はこちらにもありました。
http://perl-users.jp/articles/advent-calendar/2010/casual/4
先人の知恵を活かしきれずに同じ過ちを犯してしまっていたようです。。。


今回書いた意図としては、日本語文字列変換の際に
One.pm -> Convert.pm
Other.pm -> Convert.pm
Another.pm -> Convert.pm
みたいな呼び出し関係があり、Convert.pmに
文字列を渡すとConvert.pmの中身が
sub utf8_to_euc{
# decode
# ごにょごにょ
# encode
}
となっている。という前提で
フラグがONだと、最初のdecodeで怒られてしまう、
というのが解決したい課題でした。


ここで、Convert.pmの中で
my $enc = encode_utf8($str) if is_utf8($str);
を挟むことによって、decodeが通る、という理解を残したかったのです。


理解できていなかったのは、日本語以外のケースとモジュールの立ち位置でしょうか。
latin-1で扱われる文字があることと、この処理をするのがCPANモジュールなのか
特定サービスの限られた呼び出しのみを想定するのか。が把握できていませんでした。

また上のテストスクリプトがフラグOFFの時にdecodeするようになってるので、
残したかった事と合ってない、と今更気づきました。


まとめると、対象が文字列であるか否かを意識した上で処理をすること、でしょうか。
(まだ混乱してるかも・・・、時間を空けて読み直す)

それにしてもやっぱりAdvent Calendar(2009も2010も)++でした。

今さらですが

あけおめ、ことよろです。
今年の抱負なんぞ書いてみたいところですが、
そもそも去年は沈黙な1年でした。


前半は主にクローズドソースなコードを書いておりまして、
オープンソースに貢献できてませんでした。
後半はYAPCトークできたことは非常に貴重な経験でしたが、逆に言うとそれだけだったかなと。


さて、今年に至っては仕事内での立ち位置も微妙に変わって、クローズドソースなコードすら書けておりませぬ。。
今まではやっぱりソースで語る事がエンジニアとしての役目かなと思っていたんですが、一向にアウトプットできそうにないのでちょっと取り組み方を変えようかなと思っています。


本の感想を書いてみるもよし、コードリーディングの結果を書いてみるもよし、業務でやったこともをもう少しスマートに公開していけたら幅広がるんじゃないかなとかとか。


そんな色々を試してみるために・・・


MacBook Air 11インチ欲しい!


前振りが長くてすみません…
でも前振り部分も本音だったりしますので、今年もよろしくお願いします。