設定ファイルフォーマット考察 + Config::PP とか

tr;dr

__END__

設定ファイルフォーマット考察

YAMLがオワコンだと書いたらYAML便利派からツッコミ食らったので変遷過程を思い出してみた。楽したいと考えた挙句に最近はどのフォーマットも使わずに config.pl 作って do してる感じですけれども…。

ここで言う設定ファイルとは凡そ pit やコマンドラインツールで使うように、

  • 大した設定量がない
  • ハードコーディングしたくない(ちょっと隠しておきたい)
  • サッと作って済ませたい
  • できればのちのち再利用したい

ようなファイルのこと。

http://code.google.com/intl/ja/appengine/docs/python/config/appconfig.html みたいに量があってしっかり書く必要があるものに関しては始めからネイティブでちゃんと書いたほうがよさそう。

そもそも、本来はプログラムに直接埋め込みたかったものだから、その言語を使って書いたほうがいいんじゃないかな。

pros/cons

YAML pros
  • コメントが書ける
  • それなりに読める
YAML cons
  • YAML 1.0, 1.1, 1.2 の違いを暗記している人はいない
  • 各言語のパーサがどのバージョンに対応してるのか誰も知らない(他言語で使うときのストレスのもと)
  • 設定ファイル読み込みだけのために依存が増える
  • 新規で作られたものではあまり見かけない(気がする)
  • 同じ構造でも表記方法が複数ある
XML pros
  • (誰か考えて...)
XML cons
  • 大袈裟
  • 人間の精神を破壊する
JSON pros
  • みんな読める(はず)
  • ウェブで使われているがゆえに多くの実績と信頼
JSON cons
  • コメント書けない
PP pros
  • 依存なし
  • お手軽
  • コメント書ける
  • みんな読める/書ける
PP cons
  • 設定ファイルなのに自由すぎる
  • 他言語からの読み込みは基本的にできない
  • PPで書かれた設定ファイルの読み書き専用のモジュールはない(はず)

Config::PP

自分の中でいろいろとフォーマットを移り変わった結果、config.pl 作って do してるのが最近の事情なのでこんなの作った https://github.com/punytan/p5-Config-PP/blob/master/lib/Config/PP.pm (ドヤッ!)


YAPC::Asia 2011 に行ってきた

YAPC楽しい

今年は芝生で餃子食べられた!

トークが素晴らしいのはもちろんのこと、YAPCくらい大きなイベントになると普段会えない遠方の人たちと会えたり、面識のない人でも話ができるのでとてもいいイベントですね!(面識がないと言ってもTwitterのscreen nameで誰だかわかるので初対面だけど初対面じゃない、みたいな不思議な感じで話ができてよかった)

やや後悔

ただ、今年は何か発表したいな、なんて思いつつ過ごしていたものの大きなネタもなく発表を見送ってしまった点はsugyanさんの心境に近いものが…。

やって良かったと思えたこと

今年はアプリが出なさそうだったので、モバイル向けのタイムテーブルを作った( http://d.hatena.ne.jp/punitan/20111007/1317960797 )ところ、公式アカウント@yapcasiaをはじめ、多くの人に(紹介して|使って)もらえたようで良かった。

勝手にスクレイピングして作ったものがいつの間にか公式アカウントで紹介されたりと、自由で寛容的な文化がこのコミュニティーにはあるんだなぁと実感。

Google Analyticsによると10/13(木),10/14(金)だけで下記表のとおり大半の人の目に触れたのではないかと思います。

ページ ページビュー数 ページ別訪問数 平均ページ滞在時間 直帰率 離脱率
1. /yapcasia-timetable-2011/ 780 673 00:10:01 88.11% 86.28%

ちなみに今年のYAPC参加者は672人と過去最多だったようで、いままで以上に人が集まった回だったようです。

ブログ書くまでがYAPC

https://twitter.com/#!/lestrrat/status/125216229068771328

https://twitter.com/#!/lestrrat/status/125216296488026112

ブログ書くまでが YAPC ですね!ただ書いただけだと自分の見てる範囲の外にあるものはなかなか見つけにくいんじゃないかなぁと思ったので、後夜祭のあとにちょっとしたアプリを書いてみた( http://app.linknode.net/ )のでとりあえず一週間動かしておきます。

怠惰な自分に嬉しいRSS出力もあるので、ブログを書いたらポストして、SNS でお知らせしてもらえるとLazyな人同士で幸せになれるはず!


YAPC::Asia 2011 用タイムテーブル(モバイル用)作った

去年の反省(?)から、タイムテーブルはよく確認しておいたほうが良さそうだったので作っておいた。

http://linknode.net/yapcasia-timetable-2011/

項目を(タップ|クリック)で詳細が見られるようになっております。


マンガとキャッシュとスワイプとManga Swipe

http://blog.livedoor.jp/dankogai/archives/51732941.html をみてなかなか面白いなぁと思ったけれど、やっぱりAjaxだとキャッシュ(ページの先読み)が効かないのでページをめくるときにラグがあってなんだかイマイチ操作性悪いなぁと思ったのでスワイプで見られるように http://linknode.net/misc/swipe/ 作ってみた。

もっと作りこめば面白いこと出来そう。

工夫してみたことろ

画像を小さく

iPhoneで快適に見られるサイズだとこれが限界のようで、デバイスの性能に引っ張られる形。Imagerで小さくした。

ページ先読み

ページ先読み(の代替手段)として、display:none;な画像を事前にダウンロードさせる形式。

一度読み込みが完了すればリクエストは発生しないのでページめくりがスムーズにできる。

雑感

やっぱりモバイル用にコマ割りしてないとセリフが小さくて読みにくい。この問題は個人ではどうしようもなくて、オリジナルがそれに合わせた形でないとお手上げ状態。

キャッシュに関しては通信量との兼ね合いで、画像を少なめにしてページを大量に用意するような方法であれば、しおり替わりにもできるし長編でも読破できそうな印象。


Test::Continuous(autoprove)をサーバにインストールするには

Test::Continuous(autoprove)とは

ファイルを監視して、変更があった場合に自動でテストを走らせる autoprove というコマンドラインツールを含む便利なモジュール

インストール

cpanm の --interactive オプションを使って Log::Dispatch::DesktopNotification をインストールしないようにする

$ cpanm Test::Continuous --interactive

...

[Graphical notifications]
- Log::Dispatch::DesktopNotification ...missing.
==> Auto-install the 1 optional module(s) from CPAN? [y] n

原因

autoprove をGUIのないサーバに(cpanmのデフォルトオプションのまま)インストールしようとすると Log::Dispatch::DesktopNotification のインストールを試みる。

Linux の場合は芋づるで依存が Gtk2 まで広がり、Pango や Glib や Cairo まで依存関係が広がってしまうため最終的にインストールがコケる。


SSHFSが便利なのでメモっておく

随分前から使っているSSHFSがなかなか便利。

SSHFSとは

SSHFSはリモート(サーバ)のディレクトリをマウントしてひとつのボリュームとして扱えるようにするファイルシステムのことで、サーバ側ではsshdさえ設定してあればクライアントのセットアップだけで使えるようになる。

基本的にはDropboxからキャッシュ機能を引いたものと同じと考えても問題ないでしょう。Dropboxに見られると嫌な書類をおいておくのは気持ち悪い( http://sourceforge.jp/magazine/11/04/27/0455251 ) / ( http://blog.dropbox.com/?p=821 )&容量面でMP3を置くのが躊躇われるので、そこそこ使い道はありそう。

使い道

最近は

  • iTunes Media ディレクトリ
  • ドキュメント類

をサーバに置いて、クライアントではそれをマウントする形で利用中。

セットアップ

サーバ側はSSHの設定さえしてあれば何もする必要はない(必要に応じてディレクトリを作っておくくらい)なので、クライアント側をセットアップ。

Linuxの場合は

sudo apt-get install sshfs
sshfs host:/path/to/dir path/to/mount/point

だけ。

以下MacOSXの場合を紹介。

インストール

この2つをインストール。名前が酷似していてややこしいので取り違えないように注意。

macfuseがないと接続できないので必ずインストールしておく。

Macfusionを起動

Macfusionは~/.ssh/configの設定通りに private key を選んでくれている(っぽい)ので、普段からしっかり設定してある場合は何もせずにMacfusionを起動し、

このように画面の通り設定するだけでマウント/アンマウントできる。


git push + さくらのレンタルサーバーで github pages ライクにデプロイする方法

static なサイトを作るにあたっては、「コミット + scp などでファイルを一気に転送」を繰り返すことがよくある方法だと思う。 github pages のように、 git push のみでできると楽なのでこの環境を構築してみた。

さくらレンタルサーバー以外でも使える方法なのでそこそこ応用が効きそう。

サーバに git 環境を構築する

% cd $HOME
% mkdir tmp; cd tmp;
% wget http://kernel.org/pub/software/scm/git/git-1.7.6.tar.gz
% tar xvf git-1.7.6.tar.gz
% cd git-1.7.6
% ./configure --prefix=$HOME/local
% gmake
% gmake install
% vi $HOME/.profile
PATH に $HOME/local/bin を追加し、$HOME/.profile を読みなおす
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:$HOME/bin:$HOME/local/bin; export PATH

bare repository を準備する

% cd $HOME
% mkdir -p repos/www
% cd repos/www
% git init --bare
hooks/post-receive を編集する

push された後にフックすることで、pushと同時に公開ディレクトリにファイルを展開する事ができる。

% cd $HOME/repos/www
% cp hooks/post-receive.sample hooks/post-receive
% vi hooks/post-receive

以下のように編集する。さくらの場合は $HOME/www が公開ディレクトリ。

#!/bin/sh

env GIT_WORK_TREE=$HOME/www git checkout -f

ローカルに戻って編集作業

$ git clone user@user.sakura.ne.jp:/home/user/repos/www
$ cd www
$ touch index.html
$ git add .
$ git commit -m 'initial commit'
$ git push origin master

これで push された内容が反映されている。次回の push からは `git push` のみで反映させることができる。

簡単!


SQL文をテストする

書いたSQLのシンタックスチェックを自動化する

スキーマを書くときにはSQLを書くわけですが、作る過程では変更後のシンタックスが正しいか確認するのが意外と手間だったりします。

カンマ付け忘れや typo は自動でチェックしたいですね。

そんな時は Test::mysqld を使うと手軽に CREATE TABLE 文の文法チェックをテストに含めておけるので、

下記のようなテストを準備しておくとよさそうです。

t/sql/01_create_table.t

use strict;
use warnings;
use Test::mysqld;
use Test::More;
use DBI;

# debian installs mysqld into /usr/sbin
$ENV{PATH} = $ENV{PATH} . ':/usr/sbin';

my $mysqld = Test::mysqld->new(
    my_cnf => { 'skip-networking' => '' }
) or plan skip_all => $Test::mysqld::errstr;

my $dbh = DBI->connect( $mysqld->dsn );

for my $file (glob "schema/*") {
    my @sqls = (sub {
        open my $fh, "<", $file or die $!;
        grep { not /^\s?$/ } split /;/, do{ local $/; <$fh> };
    })->();

    for my $sql (@sqls) {
        note $sql;
        ok $dbh->do($sql), 'CREATE TABLE';
    }
}

done_testing;

App::cpanmigrate

前回エントリーに

App::cpanmigrateにするんだ! / perl のリリースサイクルと perlbrew の共存 - punitan (a.k.a. punytan) のメモ http://htn.to/t17B6J

https://twitter.com/#!/__gfx__/status/84448610938392576

とコメント頂いたので

http://search.cpan.org/dist/App-cpanmigrate/lib/App/cpanmigrate.pm

として出しました。

まだbashしか対応していませんが、他の環境用の pull request いただければ merge で対応します。

「え、シェルスクリプトなの?」

実行される本体はシェルスクリプトを exec (正確には bash -c)しているだけ(参考: http://stackoverflow.com/questions/571368/how-can-i-use-bash-syntax-in-perls-system )ですが、

@__gfx__ @punytan Text::CSV::UniqueColumnsの例があるから大丈夫

https://twitter.com/#!/maka2_donzoko/status/84495972729749505

とのこと。

http://search.cpan.org/dist/Text-CSV-UniqueColumns/lib/Text/CSV/UniqueColumns.pm

たしかにコレは…!


perl のリリースサイクルと perlbrew の共存

perl のリリースサイクルが短くなったこの頃、みなさまいかがお過ごしでしょうか。

リリースサイクル短期化による影響

perlbrew を使ってリリース毎にバージョンを切り替えたりしていると、意外と面倒に感じるのがインストール済みのモジュール類を別バージョンに移行することではないでしょうか?

さらに頻繁にリリースされるとなると、移行するのが面倒ですね。

移行時にやるべき事

移行時には、

  • 既存のバージョンにインストールされているモジュール一覧の抽出
  • 新バージョンのインストール
  • 既存のバージョンにインストールされていたモジュールを新バージョンでインストール

結構手間がかかります。

そこで

こんな bash script を ~/.bashrc などに追記しておくと楽に移行できる tips をお届けします。

ちなみに、最新の perlbrew 0.25 からはエラーが起きた際には exit 1; をよんでいるので、シェルの戻り値で処理を継続するかどうかを判定することができるようになりました(パッチ投げたらマージしてもらえた。やったね!)

function migrate {
    if [ $# -ne 1 ]; then
        cat << EOM
Usage:
    migrate [perl-version]
    migrate perl-5.14.1
EOM

    else
        echo "@@@@@ Start migration to $1"; sleep 1;

        echo "@@@@@ Installing ExtUtils::Installed"; sleep 1;
        cpanm ExtUtils::Installed;

        echo "@@@@@ Extracting all modules"; sleep 1;
        rm /tmp/modules.list;
        perl -MExtUtils::Installed -E 'say for ExtUtils::Installed->new->modules' > /tmp/modules.list;

        echo "@@@@@ Upgrading perlbrew"; sleep 1;
        curl -L http://xrl.us/perlbrewinstall | bash;
        source ~/perl5/perlbrew/etc/bashrc;

        echo "@@@@@ Installing $1"; sleep 1;
        perlbrew install "$1" -v &&

        echo "@@@@@ Switching new environment"; sleep 1;
        perlbrew switch "$1" &&

        echo "@@@@@ Installing cpanminus for new environment"; sleep 1;
        perlbrew install-cpanm &&

        echo "@@@@@ Installing all modules into new environment"; sleep 1;
        cpanm < /tmp/modules.list;

        echo "@@@@@ Re-running cpanminus to check everything is OK"; sleep 1;
        cpanm < /tmp/modules.list;

        echo "@@@@@ Done migration!"
        perl -V;
    fi
}

« 4 »