2011年 09月 27日

全然更新してないが普通に生きている。この日記書いてない期間というのは、自分の場合

  • 何も考えてない
  • 考えているけど公開で書けない
  • 考えているふりしかしていない

のうちのどれかで、今回のこの期間については「考えているふりしかしていない」が当てはまると考える。

いろいろ不安やら考えごとはあるものの、日記に落とす前に寝てしまっている。しかし文章に起こせなかった考えはなかったも同然だ。「昨日はたくさん考えたな」と自分で思ってはいても、実際のところ頭の中は整理されておらず、ループする思考の波に身をまかせているだけになってしまっている。

文章に限らないけれど、何もアウトプットせずに「考えている」だけというのは「考えているふりしかしていない」ことと同じだ。

南禅寺 大寧軒

久しぶりに南禅寺に行ったら、いつもは拝観を受け付けていない大寧軒という庭園が見られるようになっていた。三柱鳥居があるということで、それに期待を持って入ってみた。

三柱鳥居は木嶋坐天照御魂神社にあるのを何度か見にいっていて、形がかっこいいので気に入ってる。京都だとその神社の元糺の森にしかないと思い込んでいたのだけれど、今回行った大寧軒にも確かに小さいものの一基あった。元糺の森は水が沸きでるところに立っているけど、こっちもそうらしい。

高校生か、大学生ぐらいのときは、プログラムを書くときの長期的な目標として「作りたいものを作れるようになる」というのがあったことを思い出した。

今それはある程度できるようになったけれど、ただできるようになったと言っても、自分のフィールドに強引にひっぱってくる力がついたり、他人の成果 (ライブラリなど) を探しだす能力が多少ついただけで、プログラミングそのもののスキルはそんなに向上していないように思える。

「プログラミングそのもののスキル」というのは「アルゴリズム」「設計」「実装」にわけられると思うけど (もっとあるかもしれない)、特にアルゴリズム関係の力はほとんど成長していない。設計力と実装力は今の会社に入ってから特に重点的に考えていることだから、多少できるようになっていると思うけれど (できるようになっていないと困る)、それもまだまだやっぱり経験の不足は否めない。

それはともかく「作りたいものを作れるようになる」は今も良い目標だと思っていて、これはちょうど、馬が目の前のにんじんを食べたくて走るように、自分がすすめばすすむほど「作りたいもの」は遠くにいって、ずっと成長の指標になる気がしている。目標を立てた当初、自分が「作りたいもの」はブログシステムだったけれど、これは思うように作れるようになってきている。今作りたいものは、たくさんの人がストレスなく楽しく使えるサービスであるので、また遠くに餌がいってしまっている。

「ちょっと思いついたから実装書いてみるわ」みたいなノリでさっさと作りあげてしまう、というのに憧れている。

gerry++

DBI で dsn パースしてオプションを一部奪いとる

dsn ごとに接続オプションを独自で追加したいみたいなとき、別途設定を増やしたりするのが嫌なので、dsn の中の仕組みを利用したい。

Plack::Session::Store::MySQL

Plack::Session::Store::DBI というのがあって、最初とりあえずそれを使っていたのだけれど、もうちょいクエリの数を減らしておきたいと思い、以下のようなものを書いた。実際のところセッションのストレージに MySQL を使うべきかはよくわからないのですが…

変更点として

  • セッションの内容が不変だったら UPDATE を発行しない
    • ただしシリアライザがハッシュに関しても常に同じシリアライズ結果を返す必要がある (Data::MessagePack や JSON の場合 canonical オプションがあるので有効にする)
  • セッションキーの存在を確認せず、ON DUPLICATE KEY UPDATE する (アトミックになる + クエリの数が減る)
package Plack::Session::Store::MySQL;
use utf8;
use strict;
use warnings;
use parent qw(Plack::Session::Store::DBI);

sub fetch {
    my ($self, $session_id) = @_;
    my $table_name = $self->{table_name};

    my $sth = $self->_dbh->prepare_cached("SELECT session_data FROM $table_name WHERE id = ?");
    $sth->execute( $session_id );

    my ($data) = $sth->fetchrow_array;

    $self->{$session_id}->{_prev_data} = $data;

    $sth->finish;

    $data ? $self->deserializer->( $data ) : ();
}

sub store {
    my ($self, $session_id, $session) = @_;
    my $table_name = $self->{table_name};

    my $data = $self->serializer->($session);

    if ($self->{$session_id}->{_prev_data} ne $data) {
        my $sth = $self->_dbh->prepare_cached("INSERT INTO $table_name SET id = ?, session_data = ? ON DUPLICATE KEY UPDATE session_data=VALUES(session_data)");
        $sth->execute($session_id, $data);
    }
}

1;
__END__

Sample schema:

    CREATE TABLE session (
        `id`           CHAR(72) NOT NULL,
        `session_data` BLOB,
        `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY (id)
    ) ENGINE=InnoDB;
use Plack::Builder;
use Data::MessagePack;
use Plack::Session::State::Cookie;
use Plack::Session::Store::MySQL;

my $MessagePack = Data::MessagePack->new();
$MessagePack->canonical;

builder {
    enable
        "Plack::Middleware::Session",
        state => Plack::Session::State::Cookie->new(),
        store => Plack::Session::Store::MySQL->new(
            get_dbh      => sub { DBI->connect_cached(config->param('dsn_session'), 'foo', 'bar') },
            table_name   => 'session',
            serializer   => sub { $MessagePack->pack(+shift) },
            deserializer => sub { eval { $MessagePack->unpack(+shift) } || +{} },
        );
        
        $app
};

シリアライザ

Storable

  • 常に同じシリアライズ結果にできる ($Storable::canonical)
  • 可読性なし
  • データサイズ大
  • データ形式が Perl 限定 (Ruby でもパースできるという噂が)
  • bless 状態を保持できる

Data::Dumper

  • 常に同じシリアライズ結果にできる ($Data::Dumper::Sortkeys = 1)
  • 可読性あり
  • データ形式が Perl 限定
  • bless 状態を保持できる

JSON::XS

  • 常に同じシリアライズ結果にできる ($json->canonical(1))
  • 可読性あり
  • バイト列を保存できない
    • JSON の仕様上文字列しかないのでバイト列を保存したければ Base64 したりしなくてはいけなくて使いにくい
  • Storable よりは早い

Data::MessagePack

  • 常に同じシリアライズ結果にできる ($mp->canonical(1))
  • データサイズ小
  • バイナリ
  • 可読性ほぼなし (Storable と違って文字列は読める)
  • 早い