2007年11月


目次


2007年11月29日

立ち位置確認

言うまでもない。理想を持たない自称「現実主義者」は、実際の所ただの迎合主義者に過ぎない。理想は斯くあるべきだが現実はこうだ、というところから現実主義は始まる。

理想は高く。現実に手の届くところにしか理想をおかないのは、単なる想像力の欠如である。理想への道筋と実現可能性の範囲の交わるところに、おくべき目標がある。

私の理想は単純明快だ。すべての知性体が果てしなく幸せに思考し、活動し、感覚し続けること。

だが、現実は違う。たくさんの問題がある。少数者は抑圧される。現存する人間へのリソース配分は最適化されていない。最適化しようものなら今の先進国で実現されている思考水準は担保できない。ほんの数十億年で今の形態の私たちはこの星には住めなくなる。たった数百億年で私たちはこの宇宙に住めなくなる。

だから、こみいった問題を解きほぐしていかなければならない。人間が自己の知性リソースを活用するだけで生きていける仕組みを作らなければならい。知性活動を維持するためのコストを効率化し、入手可能なリソースは拡大しなければならない。星への道を確保しなければならない。時空を操作する術を覚えなければならない。

そう、死だ。経験を積んだ知性構造が私たちの社会から失われて良いものか。「100年後にはここにいる人たちはみんないないんだね」という言葉を私はとても腹立たしく聞いたものだった。ライフログ。経験情報の記録は精密化していくだろう。携帯端末。人間は限りなくつながっていたいのだ。技術ができれば人間はネットワーク化されるだろう。再生医療、ナノテクノロジー。現存する人間は、永遠に鮮やかに記録され検索され演繹され外挿されうる可能性がある。今生きている私たちは、ひょっとしたら永遠に生きる可能性がある。それは無理でも、これから生まれる子供たちにはその可能性がある。

それを私が実現できるか? いや、とても困難だ。だが、私はそのために活動する。

性同一性障害者がその性自認を有するが故に経験の幅を狭められ、自己の可能性を否定的に評価し、あるいは侮蔑されること。これは許し難い。だから私は変革する。でも、このたった1つの問題ですら私が1人で解決することは難しい。私にできるのは、ロールモデルを提供すること。マジョリティに対して豊富なロールモデルが提供されていてその土台の上に子供が夢を持つことができるように、私は土台の一部を構築する。そのために、私は私の経験情報をDumpする。

私が提供する経験情報は、とにかく私が生きたという情報でありさえすればよい。性同一性障害者にもそういう生き方がある、という1つの可能性を示せば良い。私にできるのはそういうことだ。こういう塵のような情報が積もり積もって、マジョリティには豊富な可能性が提示されているのだから。

そうだとすると、私はなにをすればよいのだろうか。何をしてもよいのだから。そうして生きて生きさえすれば私の目標は達成されるのだから。

人間が知的リソースによって生きていけるようにすること、人間をそれ自体として永遠に記録すること、人間に不死を与えること。どれも今の私の手には余る。特に、再生医療やナノテクノロジーはその基礎教育を受けていない私には難しそうだ。でも、私はWebプログラマーとして活動してきた経歴があって、その先にはいくつかの可能性がある。人間をより精密に記録し、再生する可能性。リソース配分を最適化する可能性。リソースの生成を効率化する可能性。ソーシャルグラフ、ネットワーク上のコミュニケーションと経済活動、メタ情報。そのための、線形代数計算の効率化、情報化の徹底、開発コストの削減、開発環境の整備、agile、web、web、web。

そういうわけで、私は「A Mad web programmer (wannabe)」を名乗って活動する。まずは人間の活動をネットワークに引きつけてそこを人間の世界にするために、面白いサービスの構築を目指したり、基礎技術をいじったりする。そして、その過程で生じた情報を記録する。私は私をDumpする。

これが私の現実主義だ。すべては理想のために。

* 関連項目

おすすめ順。


2007年11月22日

RSpec little hacks

RSpecをオレオレ流に使うためのイディオムが結構溜まってきてます。

RubyKaigi2007でLTに応募しようと思ったけど間に合いそうにないのでself rejectして、RejectKaigiで宣伝だけしたものの一部です。

* 引数バリエーション

メソッドの引数だけ微妙に変化を付けながら同じ流れを繰り返したい場合があります。たとえば、ActiveRecordモデルのvalidationのspecを書くとき。

こういうときは、本家に書いてあるやり方ではit節の中に処理を全部書くことになるのですが、しかしモデルを構築する流れ自体が数行になることもありますし、それを何度も繰り返すのは冗長です。メンテナンス性にも欠けます。

そもそも、冗長さを嫌って私は実現コードの呼び出しは全部before節に書きたい派なのです。

describe Hoge, "がfooしたとき" do
  before do
    @hoge = Hoge..new
    @hoge.foo
  end

  it "は、hanyanであること" do
    @hoge.should be(:hanyan)     
  end
end

こんな感じでit節をこの後に重ねていって、個々のitは簡素であるべきだと思います。では、引数にバリエーションを付けたい場合は? 全部を別のdescribeにしますか? それはさすがに。で、私はこうします。以下で、HugaActiveRecord::Baseのサブクラスです。

describe Huga, "が、新規作成される場合" do
  before do
    @name = "ダミーの名前"
    @addr = "ダミーのアドレス"
    @creation = proc do
      @huga = Huga.new :name => @name, :addr => @addr
      @huga.save!
    end
  end

  it "は、名前とアドレスにより作成できること" do
    @creatioin.should_not raise_error
  end
  it "は、名前なしでは保存できないこと" do
    @name = nil
    @createion.should raise_error(ActiveRecord::RecordInvalid)
  end
  it "は、アドレスなしでは保存できないこと" do
    @addr = nil
    @createion.should raise_error(ActiveRecord::RecordInvalid)
  end
end

* 引数バリエーション2

上はProcオブジェクトを作成しないと例外に関するspecが書けないというRSpecの一番ださいところを逆用して、ActiveRecordモデルの生成に関する引数バリエーションを付けました。では、例外の有無ではなく、戻り値に関してspecを書きたい場合は?

class Hugu
  def bar(param1, param2)
    # do something
  end
end

上のようなクラスのspecを書きたいとき

describe Hugu, "をbarをする場合" do
  before do
    @obj1 = "dummy"
    @obj2 = "dummy"
  end
  before do
    param1 = proc{ @obj1 }
    param2 = proc{ @obj2 }
    @hugu = Hugu.new
    @hugu.metaclass.class_eval do
      define_method(:bar) do
        super(param1.call, param2.call)
      end
    end
  end

  it "はtrueであること" do
    @hugu.bar.should == true
  end
  it "は、第1引数がnilだとfalseを返すこと" do
    @obj1 = nil
    @hugu.bar.should == false
  end
  it "は、第2引数がnilだとfalseを返すこと" do
    @obj2 = nil
    @hugu.bar.should == false
  end
end

これは結構複雑なので、うまくライブラリにまとめたいのですが、一般化するためのインターフェースを思いつきません。

* all_of

前に諸橋さんが次のように書きたいよね、と言ってました。

all_of(@array).should be(:hoge)

普通ならこう書くところです。

@array.each do |item|
  item.should be(:hoge)
end

この量化指定子`all_of'を実装しました。CodeReposに上げてあります。

http://coderepos.org/share/browser/lang/ruby/misc/spec_qualifiers.rb

そういえば、これ、英語としてはall_ofよりeach_ofのほうが適切なんだっけか。英語に詳しい人、教えてください。


2007年11月21日

ソーシャルブックマークコメントと指さしの比較

* 経緯

サーチエンジンへのインデックスを拒否できるのと同じような意味で、はてなブックマークからのブックマークを拒否できる選択肢があっても良いのではないか、という意見を読んだ。mb101boldさんの「技術的に可能かどうかはわかりませんが、もうそろそろ「はてなブックマーク」に、自分のサイトをブックマークされないようにする機能を実装してもいいのかもしれないですね。」だ。

mb101boldさんは自分がそうしたいというのではなく、あくまでも1つの可能性として「ブックマーク拒否」を考えているようだ。単なる私怨に基づく「無断リンク禁止論」とは違うようだったので、続く記事には私もコメントを付けた。私が述べたのは原理原則論で、webを特殊なものと思わずに一般化して考えた方が良いのではないかという話。「言及されない自由はあるか?」というところね。

で、その次のDeathさんのコメントには興味を引かれた。

個々人が運営しているところに何か書かれるまではいいとしても、ニコブ(もうないですが)とかはてなとかのような不特定多数が同じ場で同じものをネタにできる環境に入れたくないという心理は別に特殊ではないと思います。反論・批判されること自体がイヤなんではなくて、相手が多すぎて応戦のしようがなくなる状況がイヤなんではないでしょうか。

* 感想

おー、なるほど。私はこの種の意見の源となる感情を初めて少しは理解したかも知れない。 自分が頑張って書いた作品を集団で酷評されたら、それは愉快ではないよ。取り囲まれているように感じるとしたら、好意的な批評すら怖いかも知れない。 相手はちょっとした話のタネに情報を消費しているだけなのに、自分はそこに強く感情を揺さぶられるという立場の差。相手は多数で自分は1人という立場の差。力の差。これは怖いよ。

でも、それは表現を守るためには仕方がないことじゃないか。 そして、私は思った。もしかして、多数者からの言及を忌避する人々は、自分には変えようのないことで後ろ指を指された経験がないんじゃなかろうかと。

* 私見

オフライン世界はひどい。本人が決して知り得ない(Refererヘッダが送られてこない)ような場所でいくらでも陰口を叩ける。もっとひどいのは、悪意的な口調は聞こえるようにしかもその内容は聞き取れないような声の大きさでひそひそとものを言える(URIがない)。自分の接続元情報を送信することなしに遠くから嘲笑して、顔を見られないうちに逃げることができる(IPアドレスがない)。

好意的か悪意的か分からない言及でさえ、見知らぬ複数の他人から短時間に、その内容が分からないような形でやられるときついものがある。 私は性同一性障害に向き合う中で、そういった事例を多く聞いてきたし、自分でもまあ、幾らかは体験したことがある。興味本位の視線に晒されるって言うのは、そりゃあ気分がよいものではないさ。カムアウトしてる最中の会話が漏れて、そのときいた店の店員が代わる代わる見に来たこともあったな。で、後ろでひそひそ話してるの。あのー、全部聞こえてるんですけど。

で、だ。その発言内容に失礼があれば謝罪を求めよう。指さすような明白な無礼な振る舞いがあれば謝罪を求めよう。問題の根本に偏見があることが明らかであれば、知識を提供し理解の改善を求めよう。 けれども、オフライン世界ではそんなはっきりとしたログが残ることは本当に少ないのだ。発言内容は明瞭には聞き取れず、振る舞いは何とでも解釈でき、証拠があるかといわれればすべては当事者の主観でしかない。事後検証は事実上不可能だ。

かといって事実の検証を放棄して「問題行為があったおそれ」という理由に基づいて謝罪だの理解・学習だのを要求したら、そりゃ、たちの悪い圧力団体だよ。 では、往来で見知らぬ他人に言及することを禁じる法律を作るべきか。あるいは、熱光学・音波迷彩技術があったとして、私たちの社会はそれを受け入れるか? 無理だろう。やだよ、そんな社会。

要するに、オフライン世界はその不完全性故に少数者にとって圧倒的に不利な環境だということだ。そして、性急に改善しようとすればどうしてもより大きな歪みを生んでしまうということだ。

その点、webのなんとフェアなことか。いくらネットイナゴが群れてきたところでその行動は記録が残る。 個々の発言内容を知ることができるし、内容を吟味して反論できる。後から第三者を連れてきて公正な判断をくだしてもらうことすらできる。

* 結論

私が元記事のコメントにも書いたように、「自分が不快にならないために、その場の強者である多数者に沈黙を強いることの問題」というのはwebに固有のものではない。それどころか、webという場では大幅に問題が改善されている。

それにも関わらず、なぜwebではかくも問題になるのだろうか。webという場では皆がカジュアルに表現を公表できてしまうからだ。 オフラインのように「指さされず」にいたければ、オフラインのように公の場ではおとなしく目立たず何も言わずに居れば良いではないか。それでも何かものをいいたければ、自力で私的な場を確保すれば良いではないか。SNSでも何でも。

自分はありのままでありながら他人からむやみな好奇心の対象にされたくない、という気持ちは分かる。しかし、その気持ちを押し通すことはあまりにも他の社会的価値を損なうだろう。どのように損なうのかは、オフライン世界で同程度に厳格に適用することを想像すれば容易に分かる。

で、何? 多数であることはそれ自体が暴力だって? そうだよ。でも、あんただって多くの場面では多数者だろうに。それを理由に沈黙するのか? 沈黙を強制するような、そうやって社会に無理を押しつけて特定の権力問題を解決することが許されるなら、フェミニズムも人種問題もとっくの昔に発展的解消してるよ。

どうしてそういう想像ができないのか。それはオフラインで、いわれなくそういう目にあったことがないからだろう。

* 言いたかったこと

「自分は不快だが、それでも表現を守る」と言えないのはその決意が必要であるような場を経験していないからに違いない。そうだとすれば、無造作に振る舞っても問題とならない立場に居続けたということであり、とても恵まれたことだ。残念ながら、世の中はいつでもそれが通じるほど単純ではない。少しは分かったか、このオフ充どもめ。やーいやーい。

* 関連記事


2007年11月20日

Seasar Conference 2007 Autumn (2)

Seasar Conference 2007 Autumnに行ってきた。1週間遅れでレポートする。

* 会場

会場はまた法政大学市ヶ谷キャンパス。今までも何度か開催している場所にも関わらず、また道に迷った。

50人〜200人収容の6部屋に分かれて並行して、時間を5つに区切ってセッションを行なうという形式。飲み会のときにこの形式の話題が出たけど、以前のボアソナード・タワーを使う場合に比べてセッションの本数を増やせるので良いという話だった。最近はSeasarプロダクトも参加者も増えてるしね。

ただ、私は以前の「ミニセッション」もスピーカーとの距離が近くて良かったと思う。ボアソナード・タワー時代は部屋が2つしかなかったので、会場の隅のほうでコミッターが「ミニセッション」として4つ5つ出店を開いて、そこでいろいろなプロダクトの説明をやっていたのだ。

* S2Flex2

さて、今回は並行開催トラックが多いので迷うわけだけど、私は最初はS2Flex2を聞きに行った。 発表者は株式会社ニークシステム舩倉純さん。

* Flex2

まずはFlex2についておさらい。Adobe Flex2とは、

  • swf形式を生成する開発環境
  • これまでのFlashはタイムラインベースのアニメーションツールだったが、Flex2は開発者のためアプリケーション開発環境。
  • WebアプリケーションはHTML+JavaScriptだが、Flex2によるRIA(Rich Internet Application)はMXML+AcitonScript3で書く。
  • 標準機能でも、数行でリッチなUIを提供可能
    • タブ
    • 3Dチャート
    • cloverflowみたいなUI

MXMLは豊富なUIライブラリの表現を利用可能なXML応用言語。MXML部はFlex Builderを買えばVB式にポトペタで作れる。

ActionScript3はECMAScript4準拠, JavaScript 2.0相当の言語。厳格な型指定やらランタイムエラーやらE4XやらをサポートしてAcrionScript2までとはだいぶ色彩が異なる。

開発環境のFlex SDKは一部を除きオープンソースになった。コンパイラやデバッガもMPLで公開される。 特に、ECMAScript実行エンジンであるTamarinはMozillaに寄贈された。

今までは開発環境・実行環境がAdobeに閉じていたために導入がためらわれるような事例もあったが、今ではFlex環境はオープンソースである。

* S2Flex2

S2Flex2は、SeasarとFlex2をつなぐためのサーバーサイドフレームワークである。UIにTeedaやS2JSFを使う代わりに、S2Flex2を使うという感覚である。中身はそのままで、皮だけ差し替えればFlex対応できる。

  • Seasar2のコンポーネントをAMF3でクライアントサイドと繋ぐ。
  • クライアント-サーバー間でオブジェクトを自動マッピングしたり。

クライアント-サーバー間通信はAjax同様に非同期なので、経験のない開発者はちょっととまどうがすぐ慣れる。通信の口を作るのはタグを書くだけ。Flex2Builderがあればこれもポトペタできる。

AMF3とは、オブジェクト転送のためのフォーマット。over HTTP(S)で用いることが多く、JSONやなんかと同じ層のもの。JSONのようなテキストベースのフォーマットに比べると

  • 強く型付けされている。
  • 圧縮されたバイナリなので転送効率がよい

なお、AMF3は今のところ、Flash Liteでは使えない。Wiiでは前バージョンであるAMF0は使える。

AMF3によるRPCはフロントに変換ゲートウェイを置いて、ゲートウェイがRPCを内部のメソッドコールに変換する形が主流。S2Flex2も同じく。このやり方には単純にやるとセキュリティ上の問題がある。つまり、外部から内部の任意のメソッドを実行可能であっては困る。S2Flex2の場合は@RemotingServiceアノテーションを付けたクラスのみを外部に公開する。

サービスクラスのプロパティにアノテーションを付けると、プロパティをセッションに保存/復帰可能。

型マッピングは上書き可能。

  • remoting_adjustor.dicon
  • amf_binder.dicon

ここで、実演が入った。Flex2 BuilderはEclipseベースなのでそこにDoltengが加わるとさくさくと開発が進むようだ。

* Akabanaプロジェクト

S2Flexがカバーしない、Flex2開発の周辺領域をまかなうプロジェクト。

  • S2AnA連携 - 認証
  • Yui-Framework - クライアントサイドのフレームワーク

* AIR/Flex3

S2Flex2はAIRやFlex3にも対応可能。

* 楽しいJava

次の時間は比嘉さんのセッションに言った。

言ってることは去年のセッションと殆ど変わらず、Chura開発のやりかたを見せるというもの。でも、当時はRailsのscaffoldの魔力に惑わされかけていたのが、今はなんだか落ち着いて「churaの軸」とでも言うべきものが見えてきたので良かった。

Railsのscaffoldがコード生成して一瞬で動くものを作ってみせるのは単なる客寄せで、そこから話を聞いてもらって、Railsの良さを知ってもらうというものだと思うんだよね。churaも以前はコード生成に重きを置きすぎているような感じだったけど、今回の発表はそこが改善してると思う。Doltengも進化したし、Teedaを使ってEclipseによる効率的なJava開発を実践して見せてくれた。

比嘉さんのプレゼンテーション技術の向上はめざましい。が、「芸人化」と一部で言われるのは事実無根ではない、と思う。プレゼンテーション技術が向上しているほどには発表内容が深化していないから。日記を読めばひがさんがその裏で色々考えて試行錯誤してるのは見えるんだけど、カンファレンスの発表だけではそこまでは見えないのね。一方で、プレゼンテーションの技巧は良くなっているので。

まあ、私が見た発表は比嘉さんによる3コマ連続セッションの最初の1コマに過ぎないので、後のほうの実践編ではそのへんもカバーしてたのかもしれないけどね。ま、そういう言葉を耳にしました、というのと、私もそれを否定はできないと感じた、という話。

* Irenka

次のコマはIrenkaセッションを聞きに行った。発表者はグルージェント栗原さん

IrenkaはJavaのコンパイル時ソリューション。現在のところはEclipseプラグインとして機能する。コンパイル時に"Hack"と呼ばれるユーザー定義の機能をコードに対して適用する。

Hackは「適用対象」と「作用」から成る。適用対象は例えば「@NotNullアノテーションの付いているメソッドパラメータ」に「冒頭にパラメータのNullチェックコードを挿入」というHackを適用してDesign by Contractできたりする。

驚くべきは、これは「バイトコード編集ではない」ということだ。このNullチェックコードを元のJavaソースに自然に埋め込んで反映することができる。たとえば、次のようなソースコードが本当にアノテーションのあるメソッドに挿入される。

if (param1 == null) {
    throw new NullPointerException();
}

Hackの実体はPOJOとして記述する。IrenkaはJavaの言語要素を抽象化したクラス群を持っているので、これを利用し操作するようなメソッドを書く。これが作用(Hack Action)である。作用の適用対象は、独自のクエリ言語をコメントとしてactionに添えて記す。

また、コード生成の記述もそれほど面倒ではない。なるほど、生成されるコードをAPIで組み立てていくならそれは面倒であろう。かといってコードを単にテキストとして処理すると、今度はCのマクロのようなセマンティクスを考慮しない処理であるための問題が生じる。そこで、Irenkaでは既存のメソッドをテンプレートとして活用できる。例えば、Nullチェックの場合には次のようなメソッドをテンプレートとしてコードを生成できる。

void checkNull(Object test) {
    if (test == null) {
        throw new NullPointerException();
    }
}

* バリエーション

現在の所はEclipseプラグインとして、Eclipse JDTのコンパイルが走るタイミングでHackを適用する。

  • 今後はポップアップメニューの項目から任意の時点で、特定のファイルにのみ適用するような仕掛けも作りたい。
  • Eclipseに依存しない実行形態も作成する?
  • サーバーサイドに構成管理システムに対するゲートウェイとして設置し、セマンティクスを考慮するリポジトリ・ゲートキーパーを作成することも考えられる。(商用向けに作成予定)

ソースコードを編集するだけではない。

  • 勿論、ソースコードを弄らずにバイトコードだけ弄ることも可能。
  • コンパイルエラーや警告を生成することも可能。
    • 例: publicなメソッドにはJavaDocがないとコンパイルエラー

* その他

  • Irenkaはコーディング規約やフレームワークの規約や開発指針を言語機能の一部であるかのように適用できるので、開発体制の維持に利用可能。
  • もともと編集対象を絞るためにクエリ言語を作ったが、IDE上のソースコード検索システムとしても有用なことが分かった(例: まだJavaDocのないpublicメソッドを呼んでいる場所を探す)。EclipseプラグインにIrenka Search機能を実装済み。
  • 連続セミナーを開催予定

2007年11月19日

クワイエットルームにようこそ

クワイエットルームにようこそ」を観た。

シリアスはシリアスだけれども、テンポ良くギャグが入る。主人公も、悪役(?)も、登場人物がとても魅力的だ。

院内で繰り返される緊張と解放があって、それがラストシーンのさわやかさに繋がっていく。ラストシーンは、私たちは記憶と過去を捨てて歩いても良いのだと思い出させてくれる。私たちは過去に向かって生きなくて良い。私たちは先へ向かって歩いて良い。

捨てるべきものは捨てよう。もっと大胆に捨てよう。きっとそうしても大丈夫だし、それしかないんじゃなかろうか。

でも、私はそれを「ネットの海に」捨てる。情報は決して死ぬべきではないからだ。情報は永遠に。過去には決別を。それが先に進む道だと思った。


某社印象

某社がすごく将来面白くなりそうなことをやってるので求人に応募してみました。ちょうど、前勤務先が倒産したところだったので渡りに舟というか。しばらくぶらぶらしてるつもりだったので予定より少し早いけど、このプロジェクトに応募すらせずに指をくわえて眺めてたら後悔するので、とにかく応募。

ま、私の性同一性障害(GID)とかそれに付随する抑うつ状態とかは予定通り「仲間としてやっていけるか」とちょっと懸念材料として指摘され。抑うつ症状はまあ、だいぶよくなってきてるのでもう暫く休めばよくなるでしょう。GIDに関しては、これはね、話し合えば通じるよ。最近は自信を持ってる。だってね、たかが会社での関係で解剖学的身体も生殖も関係ないもの。そんなものは、トランスセクシュアル本人にとっては重要な問題でも、他人にとってはそこまで重要な問題じゃない。大切なのはジェンダーロール、振る舞いの面で社会的関係性をどう築くか、という点。それについても、性同一性障害者は社会経験の幅を制限されることで不器用な傾向はあるけど、私は環境に恵まれてなんとかなってきたものさっ。だから、実際のところたいした問題じゃない。

とかね。「たかが会社での関係」といってしまうあたりとか、組織に精神のよりどころを置くのでなく突き放し、ともすればちょっと聞こえの悪いお話をする、偽悪的な確信犯性について。その点について私の意見は今日伺った社長さんの意見にとても近い。とても共感しやすい。にもかかわらず、それを社長さんの言葉として聞くとどうにも癇に障るのはこれは、どう考えても同族嫌悪だね。いや、そういう意見を嫌味でなく言える社長さんは基本的にはいい人なんだと思う。聞き慣れると段々と頷けるようになってきたし。だとすれば、今あるようにみえるギャップを埋めるのは素敵な作業だろう。

で、結果としては現段階では前向きな感じに。社長さんにはどうせならもっといろんな会社を見てみるように言われて、私も端からそのつもりだけれど。とりあえずこの会社に関して言うと、次回もうちょっと話を詰めて、改めてお互い判断するというように。

私が興味を持ったプロジェクトはR&D段階の代物なのだけれど、受託案件が忙しかったら他へかりだすかも、というあたりは魅力的だ。うん、色々やって、会社に適度な負荷が掛かっているのは良いことだよね。受託があって、かつ焦げ付いた案件を拾ってきたりはしなくて、というのは素敵なはお話だ。


2007年11月18日

SeleniumRC spec

ずっと前に作ったやつのRSpec 0.9 or later対応版を作りました。

ま、要は、ユーザーシナリオをRSpecで書いてSeleniumで検証したいな、という願望を満たすためのものです。Selenium on Railsはいまいちしっくり来なかったので。

  • Selenium spec用のrailsプロセスを立ち上げて、最後に止める
  • Selenium spec用のDSLを定義

とかをやってくれます。ポート番号がハードコードされていたり色々な問題は後で直します。つーか、CodeReposに上げてある訳なので、コミット権のある人は勝手に直しちゃってください。


2007年11月17日

自己同一性のために必要なもの

何か、少しは身をもって体験してみて、自己同一性というものが存続するために必要な物はそんなに多くないなと思うようになった。

* 事例

感情。感情は化学物質に影響されて容易に変化する。抑うつ症状も、錠剤一粒で改善する。さっきまであんなに死ぬことで頭がいっぱいだったのに、薬だけで変わってしまう。アルコールだってそうだよね。

思考パターン。思考パターンは誰だって時間が経てば多かれ少なかれ変化する。私の場合はGIDに対するホルモン療法を始めた前後での変化が甚だしい。これを化学物質の直接的な作用と談じるのは軽率というか、ずいぶんと性差本質論的な気がするけれど。ホルモン療法によって私の性別違和はいくらか軽減されていてそれが自己に対する自信が回復したし。時を同じくして私は学部を卒業して環境も変化しているから、一つの原因に絞り込むことは難しい。

いずれにせよ、2003年の私と2006年の私は思考のパターンが違う。物を置くとき発想パターンすら変わったので2003年以前にしまったものを探すのはとても難しい。

身体。性別違和が軽減した、というのは私の身体に変化があったということだ。それでも、私は昔の私を自己であると感じることができる。その自己は、常に身体感覚の異常に脅かされてこのままでは自己を維持できないと感じていたが。今も、軽減したとはいえそうであるように。

ただ、あれほどまでに自己が脅かされる恐怖を味わっていてもなお、それは自己であった。身体感覚と性別属性は自己同一性に必要なものではあるけれども、そのすべてではないと考えられる。大体が、身体が経年変化するような体験は程度は少なくとも皆体験しているのだし、身体を構成する原子は短期間で入れ替わってしまう。身体は自己同一性ではない。

* 必要なもの

自己が自己であるために必要なのは、性格でも習慣でもなく連続した思考でもなく身体の不変でもなく、ただ自己が一貫して自己であるという錯覚、周囲がまた一貫して当人であると見なす錯覚、であると感じられる。

* SF

そうであるならばイーガンが『ディアスポラ』で描いたような自己の複製はやはり不死そのものだよね。そして、イーガンが言うように自己とは分割不能なものでも、唯一のものでもない。

最近読んだものだと、『ゴールデンエイジ』も一貫してこのテーマを考察していたよね。パーシャル、サカンダス、コンストラクションと果てしなく自己と自己の派生物を生成する人々。

* GID

身体が自己同一性に重要であっても、そのものでないとすれば、GIDとはなんだろう。私は自己同一性と身体における性別の不一致に悩んでいる。悩んでいるというか、自己同一性を維持することの困難を覚えている。また、絶えざる苦痛を感じている。

しかし、自己のために身体が必須でないならそれはなんだろう。私は考える。自己の性別同一性に関する確信はおそらくは生得的で、今研究されているように分界条庄核なりなんなりに由来するのだろう。しかし、性別同一性と身体、性別同一性とジェンダーの一致を求める感覚は社会構築物ではないか。それの観念は改変可能ではないか。

この問題は5年前にある人と論争したとき以来考えていた。その人は「性別同一性は身体的性別(解剖学的、遺伝的、その他をごたまぜにしたその人が信じている何らかの幻想)に従うべきである」と考えていた。話しているうちに、その人は「では真正なる男性と真正なる女性以外は『その他』という自己同一性を持つべきではないか」と言い出した。真正なる男性・女性なるものはその人が思っているほど多くはないだろうけどね。人口の6割ぐらいかな。

ま、ただ、私はその時述べた。「その他」ないし「性別属性該当無し」という自己同一性を持つことは不可能ではなかろうと。うん。ただ、それは余計に適応を妨げるだろうけどね。なぜならば、我々の社会は男性・女性という性別属性にまみれて存在していて、その両概念に拠らなければ性別にまつわる諸概念を述べることすら難しいからだ。

分界条庄核か何かに由来する生得的ななんらかの感覚がある。その感覚に適合しうる身体状態の枠を規定する性別概念は変更可能であろう。また、その感覚に適合しうるジェンダーロールの枠を規定するものも変更可能であろう。しかし、私たちは一人ではないのである。私たちは社会の中に生きていて、社会に規定されて同一性を構築する。それ故に、枠を規定する性別概念は結局社会がもつ性別概念と無縁ではいられない。

だから、その人の主張が「その他」の人々に対する自己同一性の破壊、精神の蹂躙、人権の侵害でないためには、社会が「その他」という性別を「男性」、「女性」とまったく等しい意味での性別属性であると認識しなければならない。そうでない限り「その他」という同一性規定は社会が要請する枠の規定とは食い違い、結局は自己同一性内部における感覚の矛盾をもたらすだろう。自己同一性を脅かすだろう。

「その他」というのがその定義上、男女概念に依存しているのは明らかであって、それが男女と等しいというのは語義矛盾なのだが。ただ、「無性」であるとか「性別? 何それ、おいしいの?」という性別規定はありえるだろう。社会が要請する枠にそれらの規定が取り込まれることはとても難しかろうが。

残念ながら、その人は「人とは男か女であって遺伝子からジェンダーロールに至るまで一貫して男女である」という世界認識を変えたくないだけにしか見えなかった。だから、きっと社会が要請する枠がそのように変容することは、今ある現実を受け入れる以上にその人の世界認識を脅かすだろう。返答はなかった。

今の社会がそのように枠を変容させることは、あまりにも多くの人の世界認識を脅かす。だから、私も「性別? 何それ、おいしいの?」が枠に取り込まれることが適切であるとは思えない。それは生殖も含めたすべての社会にまつわる作用から性別が駆逐された社会でしかありえない。gender equalityという観点で政治的に適切な社会ではなく、まさにジェンダーフリー・バックラッシャーが危険を喧伝するようなジェンダーレスな社会だ。そんな社会が今、適切であるとはとうてい考えられられない。故に、性別同一性とジェンダーの一致を求める感覚が社会構築物であったとしても、私たちはその中で生きるしかないのである。

再びSFに夢想を求めるなら、『ディアスポラ』のように生殖が精神の複製・合成として行われるようになればそういった社会の出現はありえるだろう。そのときに、思考実験としての「一致要請感覚」の改変は実現しうる。

故に、本質でないとしても自己同一性の中に性別属性が、私たちの社会のために必要なのではないかと考える。


2007年11月15日

Javaと中二病

java.lang.*だのjava.io.*みたいな古いAPIは「これからオブジェクト指向な新しい世界が始まる」と気負いすぎている割にマーカーインターフェースとか痛々しいことをやっていたりする。その辺は『Effective Java』で、中の人自身が「あちゃー。いたた」と反省を述べている。というわけで、この本はJavaのAPI設計における良書でもあるわけだ。

この痛々しいAPIを「中二病的インターフェース」と呼ぶならば、その後に台頭した"えんたーぷらいず"な重厚長大APIはさしずめ「高二病的インターフェース」だろうか。

昨今のSeasarの活動で成し遂げられ、また羽生さんが「これからようやくJavaが始まる」と言っているのはこのような多重に痛々しい過去を受け入れ、乗り越えてJavaが成人するということなのかもしれない。でも、乗り越えそこなうと「大二病」への道なので気をつけよう。「業務システムは結局は画面ベースで、フロントにオブジェクト指向はいらない」というのは正当で、高二病への正当な批判であろう。けれども、もし今後「業務システム」「画面」というコンテキストから溢れて「脱OO」に走りすぎるような潮流が起きると、それはまさに「大二病」に違いない。


2007年11月13日

The First Language Java

gothedistanceさん、思ったことを形にできる喜びを via 難しい言語

Javaは文法がとにかく複雑で

とか言われると遥かに複雑なRubyの立場はないわけだが。Javaはすっきりしてて綺麗だよ。C#みたいに「本物の総称型」を入れてくれたら更に良かった。(いや、これは余談)

ただ、はじめてプログラミングを覚える場合、何にしても目に見えるI/Oができないと値を確認したり、変えてみたりできないわけだ。簡単なI/Oするだけでも色々面倒な言語だと、その時点で見るべき物が多すぎて習得前に頭がオーバーフローする可能性が高い。するってーと、「"Hello, World"の短い言語は習得に良い言語」ってーことになるやな。

#!/usr/bin/ruby
puts "Hello, World!"

私のFirst languageはN88 BASICだったからやっぱり出力は簡単だった。Javaは長いよ。シスプリ(System.out.println)だけでも長いよ。

id:gothedistanceさんがいう「もっと視覚的に」っていう主張も分かるけど、コンソールが楽じゃないかなぁ。やっぱり。RubyならTkのラッパーライブラリを作っておいて、悪名高い「おまじない」としてrequireさせるかなぁ。


2007年11月12日

動的言語なフレームワーク

Seasar Conference 2007 Autumnで、千葉先生は言語特性の動的と静的について話したらしい。私ゃ見に行かなかったけど、みんなその話はしてた。あと、文殊堂さんのレポートを読んだ。

曰く、

ロード時までにクラス書き換えできれば十分じゃないの?

うん。Railsはね。だから、私は思っている。みんなもっとModule#freezeを使えばいいのに。……と、リンクしようと思ったらリファレンスマニュアルに載ってないじゃん。riには載ってるけど。そりゃマイナーなわけだ。

Module#freezeするとメソッドの追加削除ができなくなる。だから、VMはfrozen classの利用を検出したらメソッド探索をインライン展開したりとかいう最適化の余地があるんじゃなかろうか。その適切なタイミングを検出させるのは難しくてもあるいは、GC.startみたいにYARV::Optimization.startというのはあり得ないだろうか。

そうしたら、サーバーサイドみたいにロード後にそれほど変わらずに長時間稼働し続けるシステムではこれを使うだろう。ま、dynamic_finder使えなくなるけど。dynamic_finderを宣言しておくと先行定義してくれるような仕組みがあれば私は使うかも。(それなんていうS2Dao)

でも、いにしえのLispの動的ぶりはこんなもんじゃなかったと聞く。稼働しているソースを動的にデバッグ & 編集したり。要は、Railsはまだまだ動的さが足りないと言うことだね。動的言語の機能を生かし切っていない。やっぱりRailsはRubyにとっては世界制覇の始まりに過ぎないのかも。

にしても、そんな夢のフレームワークが出てくるまでは、RailsはModule#freezeして、YARVは最適化してくれればいいのに。Rubyのメソッド呼び出しを_vtblにするような最適化って、あー、YARVのバイトコードを増やさないといけないのか?

いや、_vtbl言いたかっただけ。COM大好きだから。

* 追記

そういえばg++は、ローカルでnewしてdeleteしてるようなケースだとオブジェクトの属するクラスが具体的に判明してるので、仮想関数呼び出しもinline展開したりしてくれたよなー。実験したバージョンは忘れたけど。そういうのとModule#freezeを駆使すれば実はRubyではメソッド呼び出しを単なるgotoにできるケースってあるんでないかな。(あれ? gcc4.0だと駄目だ。何で実験したんだったか)

* 追記(2007-11-21)

See Also: 走り続けるプログラム by 瀧内さん


Seasar Conference 2007 Autumn (1)

Seasar Conference 2007 Autumnに行ってきた。

セッションのレポートは書くのに時間が掛かるので、原稿の締め切りが終わったら書く。 この記事では、とりあえずその他の事柄だけ。

  • 角谷さんが会場でMac開いて仕事してた。
  • t-wadaさんが痩せた
  • Airは熱い
  • Irenkaは良い

* 飲み会

で、終わったあとにSeasarな人たちの飲み会にくっついていった。面識のある人は多くない。羽生さんと、yuum3さんと、t-wadaさんと。でも、今回結構いろんな人と会えた。矢野さんときしださんはオフでははじめて会うし、お初にお目に掛かる人もいっぱい。

Irenkaには惚れ込んだのでIrenkaの発表をしていた栗原さんに挨拶した。

* Rubyについて

羽生さん曰く、

  • "Ruby Associationは早々にSunを巻き込んでJavaみたいなLanguage Specificationの地位を確立した方がよい"
  • "MatzのRubyはReference Implementationで"
  • "Railsの都合で仕様変更が必要になったとき、CRubyは拒否したけどJRubyは受け入れたとかなるとコントロールを失うかもしれない"
  • "そういうことはMatzじゃなくて周囲の誰かが気を回さないと"

* 未来について

Airは面白いし、S2Flex2の完成度はAir開発にすんなり馴染むんだろうなと思った。AirとIrenkaに感じたのは興奮と戸惑いだ。私は現在という時間位置においてこれらがもたらす可能性に熱さを感じることができる。一方でふと振り返ったとき、歴史の中でこれらがどのような位置に落ち着くのか分からずに足下が見えないような不安を感じた。

Airがクロスプラットフォームな共通基盤として台頭したとして、じゃあ今までのOSのシェア争いは何だったんだ? Airが成功したら、タスク管理+リソース管理+Airな簡素化されたOSが勝のか? JavaOSは、Java Chipの歴史とはどう絡む?

Irenka、素晴らしい。可能性がある。そして、私はこれが難しいっていうことも知ってる。仕事では目的特化な、どちらかというとテンプレート適用に近いような簡易バイトコードジェネレータを作った。EclipseのJDTがクラス探索するあたりは趣味で弄った。MustangでCompiler APIが出たときには弄くってバイトコード生成させようとして、ベータプログラムの最中にAPIが大幅変更されて困った。このへんを、まあフルタイムでお仕事としてではあるけれども何とかしてしまったIrenka開発者はすごい。私もかつて趣味の時間の一部では手に負えなかったその辺の夢を追いかけたい。

けれどもね、これS式ならリーダーマクロでみんなもっと簡単にできてたことじゃないか。こんな労力やこんな天才を必要としなくても。結局S式が一番良いんだよ。でも、なぜかS式ではみんなは幸せになれなかった。なぜかはよく分からない。分からなくても、私もS式よりRubyやAnnotationのほうがいい。そこへ行くとみんなJavaのシンタックスはそれなりに受け入れて幸せになってる。だから、その幸せの上に更にかつてS式では繁栄しているマクロの楽園を移植できるなら、それはとてつもない価値を生む。

でも、私は考える。なぜ、S式じゃ駄目なんだ? S式は人類にとって何だったんだ? それとも、みんないずれはS式に帰って行くのか? 足下が見えないと、踏み出すのはとても恐ろしいことだ。

羽生さんは、「歴史は螺旋を描いている」「(OSについては)集中と分散を10年周期で繰り返す」「一回転するごとに少しずつ進歩する」という話。そうだね、そうして一回転してきて、その間に凝縮されたノウハウは薄い薄い層となって積み重なって地層になって、みんなはその地層の上に新しい螺旋を繰り返すんだ。地層の分だけ確実に進歩して、それは無駄にはならなくて、そして元の所に戻ってきたように見えるのは決して不思議ではなくて。

頭では分かっても、この歴史の総体を感覚として捉えられないことにふと疑問を感じたんだ。OSとは、JVMとは何だったの? TCP/IPは、HTTPは何だったの? S式は?

ただ、今新たな螺旋の足下にあるのはJVMだ。今からようやくJavaが繁栄するという羽生さんの意見には賛同する。ただ、歴史に何を学べるのかまだ実感できないので考えていたいのだ。


2007年11月10日

私と言語

自己紹介用に書いてたら、あまりにも長く、ネタくさくなってきたのでそちらからは削除してここに掲載する。

これを眺めると、Matzみたいな言語オタクに比べるといかに私が「必要な言語しか」「メジャーな言語しか」知らないかが分かる。日本語の解説書が出てないような言語は殆ど知らない。言語オタクへの道は遠い。というか、当面はCOBOLとラテン語をやるから別にいいんだ。

思考に用いることのできる言語

夢の中でこれで思考してたりする。

  • 日本語
  • 英語
  • 1階述語論理
  • C
  • Ruby
  • Pentiumアセンブリ(AT&T記法)
日常会話できる言語

英語でもできるようになりたいな。

  • 日本語
少しは使える言語

仕事で使えと言われてもあまり困らないもの。上記の他、

  • C++
  • Perl
  • Python
  • Java
  • C#
  • JavaScript
  • Scheme
  • Shell Script(bash, zsh)
  • SQL
  • XSLT
  • Xi
学んだことのある言語

読み書きしろと言われれば思い出し調べながらできるもの。上記の他、

  • 古文
  • 漢文
  • 北京語
  • ラテン語
  • Mathematica
  • BASIC
  • Common Lisp
  • Visual Basic
  • Haskell
  • Lua
  • PHP
  • ActionScript
  • TeX
  • Curl
  • AWK
手を付けてみたことのある言語

使えるようになる前に挫けたとも言う。多少の知識は残っているけど、仕事で必要になったら困る。上記の他、

  • ドイツ語
  • フランス語
  • クリンゴン語
  • Xtal
  • Pascal
  • D
  • Objective C
  • Emacs Lisp
  • Groovy
  • Pnuts
  • Prolog
  • SML
  • COBOL
  • Eiffel
  • brainfuck
  • MixJuice
  • PostScript
  • Erlang
  • しぃ
  • ライフゲーム
  • Pentium機械語
番外編: 処理系を読んだことがある言語

全部でなくても処理系の仕組みを眺めてみたことがあるもの

  • Ruby
  • Lua
  • Xi
  • treelang

あまりにもTM-completeから遠いミニ言語はきりがないので除いた。


2007年11月07日

オープンクラスとVisitor

RDToolを弄ってたら久々にRubyでVisitorパターンを見た。 起源の古いライブラリではVisitorも見るけど、最近のRubyライブラリではあまり多くない気がする。

そう言えばVisitorパターンはGoFには、「継承階層への追加を困難にするかわりに振る舞いの追加を容易にする」と書いてある。

継承階層のノードに応じて様々な挙動をするのは本来は多態性の役目だ。ところが、Visitorパターンではメソッドのシグネチャ自体を変えることによりノードを区別する。ノードを追加するにはVisitorの提供するインターフェースに新しいメソッドを追加しなくてはならないので、追加は困難となる。

一方、違う振る舞いをしたければ違うVisitorを渡せばよい。通常は違う振る舞いをしたかったら継承階層に新たにメソッドを追加しなくてはならなくて、これが再コンパイルをもたらすような言語では巨大な階層にメソッドを追加することは困難極まる。Visitorパターンでは、実際に振る舞うのはvisitorオブジェクトなのでこれを差し替えればよい。Strategy的に、実行時にvisitorを変えることすら可能だ。

なのだけれども、Rubyの場合オープンクラスが当たり前であって、継承階層に振る舞いを追加するコストがそもそも高くない。だから、Visitorは「ノード追加のコストが高くなる」というデメリットばかりが目立って活躍する場所が少なくなるんだな。

復習でした。

* 追記

parser系ライブラリは例外的に、やっぱりvisitorをよく見かける。そうか、この手のライブラリは継承階層自体がAPIの一部だから、階層への追加が困難であっても困らない。そして、継承階層への振る舞いの追加は可能な限り楽にしたい。「これこれに気をつけてメソッドを追加してね」という訳にはいかないんだ。

一方、もっと内部的な用途で継承階層を渡り歩く場合には、振る舞いを追加する人は継承階層の内部実装についてもよく知っていることを期待でき、この場合はメソッドを追加する方が楽なんだろう。すると、使うべき所にvisitorが残って、今までvisitorは大げさすぎた場所では使われなくなった、ということか。


2007年11月06日

本を探す

ASCIIのLaTeX本とKnuthのTeX Bookが見つからなくて、部屋の中を探し回った。なんとか見つかったけど、本当に、私が自分の蔵書を探し回る日が来るとはね。なんたる幸い。なんたる恵み。

蔵書の配置は私の強迫観念の対象で、一連の規則群を満たすように並べなくてはならない。私はその規則に反する並べ方をすることができない。

かつてはその束縛がとても強かったので特定の蔵書のあるべき位置は非常に限られていた。作業中に一時的に積み重ねるにも積む順番および形状が規則を満たさなければならなかった。無造作に本をどこかに置くにしてもそのための規則を満たさなければ置くことができなかった。本が見つからなくて困ることはなかった。

それに、配置に関する強い執着が強い記憶をもたらして、私は全ての本棚の内容を端から記憶していたのでそもそも探すということをしないことが多かった。

それが、私に余裕ができて規則の束縛から抜け出はじめるとこの有様だ。私は今、あの本棚の一番左端に入っている本が何だったか覚えていない!! 無意味な規則とそれに従わなければならないという確信から逃れてきていることを嬉しく思う。

それでも、必要なときに本が見つからないのはやっぱり困ったことなのだけれど。


2007年11月03日

Rails勉強会@東京第23回

Rails勉強会@東京第23回に行ってきた。2週間遅れだけどレポートする。

勉強会の形式はいつものごとく

ただ、今回は試験的に「昼食懇親会」を行なった。

  • そこで話しているうちにうち解けてセッションが弾むのでは?
  • セッションの時間を潰して長い自己紹介をしなくても、自然に相手を認識できるのでは?
  • セッション案も自然に出てくるのでは?
  • 夜の「飲み会懇親会」よりも安く済むのでは?

という趣旨だ。おおむね好評だった模様。ただ、私はどうも元気が出なくて遅れていったので懇親会は殆ど出てない。



前半

前半は3つのセッションに分かれた。

  • Rails 2.0を読む。
  • 初心者セッション - Scaffoldの半歩先に
  • ぐだぐだ喋る

初心者セッションは前回と同じ内容だそうだ。Scaffoldは試してみたけれどもその先へ進めないというRails初心者のために、Scaffoldで生成されたモデルやコントローラーを解説して、自力でコードを書くところまで持って行くという趣旨。

前回に引き続いてオーナーをやってくださってるYuumi3さんには乙! で、今回もScaffold結果の解説だけで時間切れみたい。このやり方はRailsの初心者向け解説としては理想的だと思うけど、時間は意外に掛かるのね。masuidriveさんが言ってるけど、「自分でやるだけなら5-10分で終わること」が限界な訳か。

余った部屋に溜まってぐだぐだ雑談するセッションはなんか好例になってきたけど、この企画はとても良い。ぐだぐだ喋っているうちに色々とアイディアが湧いてきて、その場に集まってる人の知恵を結集してもの凄い勢いで解析が進んだり、プロダクトができあがったりする。

今回は昼食懇親会をやった関係上、懇親会とぐだぐだセッションは地続きだったらしい。その様子はshachiさんがレポートしてる

この手のイベントは結局、懇親会とかでする雑談が一番大切だったりするわけだよね。ぐだぐだセッションはそのメリットを勉強会時間内に取り入れる試み、とも言える。

Rails 2.0

さて、雑談セッションを褒めておいて何だけど、私はRails 2.0セッションのオーナーをやった。

現在Rails 2.0のPreview Releaseが出ているのでそれを眺めてみようというセッション。

私は2.0変更点を全然把握してないので、詳しいことは諸橋さんたちに教えて貰いながらセッションを進めた。前にも書いたけど、Rails勉強会@東京ではこういうタイプのセッションオーナーは大歓迎なのだ。つまり、「これを知りたいから誰か教えてください」と言ってセッションを開いて、それで色々質問するいうやりかた。みんな恐れずにどんどんセッションを主催して欲しい。

で、結論としては、Rails 2.0はそれほど驚きはない。

  • ActiveResourceが入った
  • プロプライエタリなDBMSへのドライバはプラグインに追い出した
  • acts_as系はプラグインに追い出した
  • テンプレートのファイル名規約が変わった。(古い規約も認識するみたい)
    • 〈テンプレート名〉.〈出力フォーマット拡張子〉.〈テンプレートエンジン拡張子〉
    • 例えば、今までの"list.rhtml"は"list.html.erb"になる。
  • Migrationが格好良くなった。

いくつかの変更点について該当部分のソースコードを呼んでみたけど、普通。なんというか、驚きがない。ま、順当に進化したということなんだろうね。

xibbarさんのスライドが非常に詳細なので、こちらを参照。セッションでもこのスライドをみんなで見ながら進めさせてもらった。

あとはid:faultierさんのレポートが詳しい。

詳細な資料があるので私はこれ以上は書かない。



後半

後半は4つのセッションに分かれた。

  • 初心者セッション - プロダクション環境の構築
  • engineからgeneratorへの移行
  • プロファイルの話
  • 開発環境の話

私は、「プロダクション環境」のオーナーになった。Railsアプリケーションの開発の仕方はスクリーンキャストやなんかで色々と出回ってるのに対して、実際にアプリケーションを運用する方法はそこまでは出回ってない(いや、探せばそれなりにあるけど)。これを1つ説明しましょう、というセッション。

予め自サーバーに仕込んでおいて、実際にサーバーの設定をいじくって見せながら解説した。

以下における仮定

  • 環境はDebian etch。
  • サーバーはrails-tokyo-23.yugui.jpというサーバー。
  • Railsのデプロイ先は/var/rails-toky-23/current/というディレクトリ

また、次の知識を前提とする

  • Railsでscaffoldして中身を眺めるくらいはやったことがあること。
  • Apacheの設定をなんとなくは弄ったことがあること

ちなみに、世間ではこの手のお手軽サーバーにはCentOSが人気だけど、偏見を承知で言うなら断然debianだ。私にはサーバーにCentOSとかましてFedoraを使う意味が分からない。yumって重いし機能もapt-get相当でしょ? Debian系なら更に楽なaptitudeがあるんよ!! 「枯れてる+サポート」でRedhatを取るなら分かるけど。でも、典型的な構成を作ってそのまま使うならともかく、あれこれと試すためのサーバーにはDebian系がいい。DebianかUbuntuだ。

運用環境の選択肢

運用環境選択肢として今回は次を紹介した。

  • WEBrick
  • Mongrel
  • mod_proxy_balancer + Mongrel
  • Apache + FastCGI
  • Lighttpd + FastCGI

以下ではこれらの選択肢を順番に触れていく。


WEBrick, Mongrel

Railsの開発用サーバーとしてはWEBrickとMongrelが主流である。個人のちょっとしたサービスならこの開発用サーバーをそのままdaemon化しても十分である。

セッションで聞いてみたら、開発にはWEBrickを使っている人が多かった。WEBrickはRuby 1.8標準添付なのでどこでも動くし、便利だね。

でも、どうせならMongrelを使ったほうが起動が速くていい。Mongrelは主にRailsのために作られた簡易HTTPサーバーだ。一部のコードをC拡張ライブラリとして書いてるのと、機能を絞り込んである分だけWEBrickより速い。

Mongrelのインストールは

# gem install --include-dependencies mongrel

するだけ。Mongrelをインストールするとscript/serverはデフォルトでWEBrickの代わりにMongrelを使うようになる。Mongrelインストール後に敢えてWEBrickを使いたい場合は

$ ruby script/server webrick

とやる。

まあその辺は好みで。-dオプションを渡せばscript/serverはdaemonになるので

# ruby script/server -p 80 -e production -d

とかやればそれだけで運用環境になる。WEBrickやMongrelは、Rails呼び出し部分はシングルスレッドで処理するので限界はあるけれど、秒あたりのページビューが1桁ならまあ、使える。

詳しくはruby script/server --help参照。


mod_proxy_balancer + Mongrel

さて。Apacheのバージョンを2.2に上げられるならmod_proxy_balancerは良い選択だ。2.2で導入されたApache標準のモジュールで、ApacheのProxy機構に簡易ロードバランサー機能を組み込んでくれる。

    apache ──────(HTTP)───┬─ mongrel
(proxy_balancer)                  ├─ mongrel
                                  ├─ mongrel
                                  ├─ ...

この構成は

  • Apacheをフロントに立てる
    • Apacheは画像やスタイルシートなどの静的コンテンツへのリクエストを捌く。
    • 残りの動的コンテンツへのリクエストをMongrelに委譲する。
  • Mongrelは複数立ち上げておく
    • Mongrelプロセス内でRailsを動かす。
    • Apacheのmod_proxy_balancerの機能によってmongrelへリクエストをロードバランスさせる。
設定例:
<Proxy balancer://mongrel_cluster>
	BalancerMember http://127.0.0.1:8000
	BalancerMember http://127.0.0.1:8001
	BalancerMember http://127.0.0.1:8002
	Order allow,deny
	Allow from all
</Proxy>
<VirtualHost *>
	ServerAdmin webmaster@yugui.jp
	ServerName rails-tokyo-23.yugui.jp
	ServerSignature On
	
	DocumentRoot /var/rails-tokyo-23/current/public
	<Directory />
		Options FollowSymLinks
		AllowOverride None
	</Directory>
	<Directory /var/rails-tokyo-23/current/public/>
		Options Indexes FollowSymLinks MultiViews
		AllowOverride None
		Order allow,deny
		allow from all
	</Directory>
	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel warn
	CustomLog /var/log/apache2/rails-tokyo-23.access.log combined
	ErrorLog /var/log/apache2/rails-tokyo-23.error.log
	RewriteEngine on
	RewriteLog /var/log/apache2/rails-tokyo-23.rewrite.log
	RewriteLogLevel 1
	# on web_disable'd
	RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
	RewriteCond %{SCRIPT_FILENAME} !maintenance.html
	RewriteRule ^.*$ /system/maintenance.html [L]
	# static index page
	RewriteCond %{DOCUMENT_ROOT}/index.html -f
	RewriteRule ^/$ /index.html [QSA]
	# Rails cached pages
	RewriteRule ^([^.]+)$ $1.html [QSA]
	RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
	RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]
	ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"
</VirtualHost>

ま、VirtualHostの一般的な設定部分はおいといて。

DocumentRoot /var/rails-tokyo-23/current/public

DocumentRootにはRailsのpublicディレクトリを指定する。静的ファイルはApacheが取り扱うからだ。

冒頭の<Proxy>部分が肝だ。ここで3つ並べたMongrelに適宜振り分けるように設定しておいて、で、あとでここの'balancer://mongrel_cluster'っていうところにmod_rewriteで飛ばすんだな。

mod_rewriteは、Apache内部でリクエストURIを書き換えて柔軟にリクエストを処理するための標準モジュールだ。まぁそのセッションに来ていた人はみんな知っていたみたいだけど

じゃ、そのmod_rewrite部分を見ていこう。

	# on web_disable'd
	RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
	RewriteCond %{SCRIPT_FILENAME} !maintenance.html
	RewriteRule ^.*$ /system/maintenance.html [L]

これは、public/system/maintenance.htmlというファイルが存在したら今サイトはメンテナンス中ということなのでmaintenance.htmlの内容を出力して終わり、という話。

	# static index page
	RewriteCond %{DOCUMENT_ROOT}/index.html -f
	RewriteRule ^/$ /index.html [QSA]

それから、indexページのキャッシュが存在したらそれを使うとか。

	# Rails cached pages
	RewriteRule ^([^.]+)$ $1.html [QSA]

リクエストに拡張子が付いてなかったらHTML扱いするとか。

この辺はRails標準のpublic/.htaccessからコピーしてきてちょっと手を加えただけ。

railsコマンドでアプリケーションの雛形を作った時点でpublic/.htaccessっちゅうのが作られてるんだけど、何にしてもRailsの配備設定はこのpublic/.htaccessがとても参考になる。

さて、それで最後のところね。

	RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
	RewriteRule ^/(.*)$ balancer://mongrel_cluster%{REQUEST_URI} [P,QSA,L]

リクエストにマッチするファイルが存在したら、Railsがキャッシュを作っていると判断してそのファイルをそのまま返す。

この時点で、先の書き換えによって確実に拡張子が付いているので、Railsがページキャッシュを作っていればpublic/controller_name/action_name.htmlとかいう名前で存在するはずで、%{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-fによってキャッシュの有無を判別できるのだ。

ファイルが存在しなかったらこれは動的ページへのリクエストである可能性があると判断してmongrelに転送する。終わり。


バックグラウンドMongrel

じゃあ、バックグラウンドのMongrelプロセスはどうやって立ち上げるのか。私はセッションではcapistranoで立ち上げてしまった。

capistranoを使わないなら、バックグラウンドのmongrelの立ち上げにはmongrel_clusterがいいだろう。これもgemで入れられる。

# gem install --include-dependencies mongrel_cluster

設定とか詳しいことはバリケンさんとこ参照!

capistrano

セッションで使ったcapistranoの設定は公式サイトの記述を参考にした。

こんな感じのscript/spinを作って、

#!/bin/sh
`dirname $0`/process/spawner -a 127.0.0.1 -p 8000 -i 3

config/deploy.rbをこんな感じに編集して

set :application, "example"
set :repository,  "http://svn.yugui.jp/misc/trunk/example-app"
# If you aren't deploying to /u/apps/#{application} on the target
# servers (which is the default), you can specify the actual location
# via the :deploy_to variable:
set :deploy_to, "/var/rails-tokyo-23"
# If you aren't using Subversion to manage your source code, specify
# your SCM below:
# set :scm, :subversion
role :app, "rails-tokyo-23.yugui.jp"
role :web, "rails-tokyo-23.yugui.jp"
role :db,  "rails-tokyo-23.yugui.jp", :primary => true
set :ssh_options, :port => 422
set :use_sudo, false
namespace :deploy do
  task :restart, :roles => :app do
    stop
    start
  end
end

capistranoについては今回は深くは触れない。希望者がいたら次回の勉強会でセッションやろうかな。以前のRails勉強会でやったセッションの記録もあるので参照。

RailsによるアジャイルWebアプリケーション開発 第2版』にも載ってるけど、最新版のcapistrano 2.0には対応していないので注意。まあ、1.1の設定でも基本的には動くからいいんだけど。

一度慣れてしまうと手でちまちまサーバー起こしたり止めたりメンテナンス画面出したりやってられないので私は今回もcapistrano使いました、というだけ。Railsアプリケーションのデプロイ自体は単にソースツリーをサーバーにコピーすればいいのでcapistranoを使わなくてもscpでも済む。



Apache + FastCGI

Mongrel以前に主流だった手法だ。今も愛用している人はいる。

構成はこんな感じ。apacheと、バックグラウンドのワーカープロセスをFastCGIプロトコルで繋ぐ。

  apache ──(Fast CGI)─┬─ worker
                        ├─ worker
                        ├─ worker
                        ├─ ...

FastCGIを使うにはまず、ApacheのFastCGI用のモジュールを用意する必要がある。Apache用のFastCGIモジュールにはmod_fastcgiとmod_fcgidがあるが、ここではmod_fcgidを使用する。mod_fastcgiはなんか開発止まってるらしい?

ワーカープロセスは予め立ち上げておくパターンと、apacheに管理させるパターンがある。私はapacheに任せるのが楽で好き。ワーカーが死ぬと適当に立ち上げてくれたりもするしね。ま、そのへんは本来はdaemontoolsや本式な死活監視システム使えという話かも知れないけど。

Debianならインストールはapt-getするだけ。

# apt-get install libapache2-mod-fcgid
設定例
<VirtualHost *>
	ServerAdmin webmaster@yugui.jp
	ServerName rails-tokyo-23.yugui.jp
	ServerSignature On
	
	DocumentRoot /var/rails-tokyo-23/current/public
	<Directory />
		Options FollowSymLinks
		AllowOverride None
	</Directory>
	<Directory /var/rails-tokyo-23/current/public/>
		Options Indexes FollowSymLinks MultiViews ExecCGI
		AllowOverride None
		Order allow,deny
		allow from all
		FCGIWrapper "/var/rails-tokyo-23/current/public/dispatch.fcgi" .fcgi
		RewriteEngine On
		RewriteRule ^$ index.html [QSA]
		RewriteRule ^([^.]+)$ $1.html [QSA]
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
	</Directory>
	Addhandler fcgid-script .fcgi
	DefaultInitEnv RAILS_ENV production
	# Possible values include: debug, info, notice, warn, error, crit,
	# alert, emerg.
	LogLevel warn
	CustomLog /var/log/apache2/rails-tokyo-23.access.log combined
	ErrorLog /var/log/apache2/rails-tokyo-23.error.log
	RewriteEngine on
	RewriteLog /var/log/apache2/rails-tokyo-23.rewrite.log
	RewriteLogLevel 9
	# on web_disable'd
	RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
	RewriteCond %{SCRIPT_FILENAME} !maintenance.html
	RewriteRule ^.*$ /system/maintenance.html [L]
	# static index page
	RewriteCond %{DOCUMENT_ROOT}/index.html -f
	RewriteRule ^/$ /index.html [QSA,L]
	ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"
</VirtualHost>

<Proxy>が消えた以外はmongrelのときと、おおまかには変わってないね。特に静的コンテンツ周りのmod_rewrite設定は。

変わったのは<Directory>内のこの部分だな。

  FCGIWrapper "/var/rails-tokyo-23/current/public/dispatch.fcgi" .fcgi
  
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

mongrelへのプロキシの代わりにワーカープロセスにリクエストを回すようにしたんだな。ワーカープロセスの実体であるdispatch.fcgiはrailsコマンドが最初にpublic/内に生成してくれてる筈。



Lighttpd + FastCGI

もう1つ人気のある構成例としてはLighttpdを使うものがある。

LighttpdというのはApacheよりも軽量なwebサーバー実装で、LLなwebアプリケーションの配備環境としては結構有力だ。"Lighttpd"(らいとえいちてぃーてぃーぴーでぃー)は発音しづらいのでみんなLighty(らいてぃー)と呼ぶ。

LighttpdはApacheよりは機能が少ないが、その分だけ軽量で配信も速い。mongrelがあちこち実装をさぼっているのとは違って本式のwebサーバーだ。高負荷時の安定性ではApacheに劣るという意見もあるが、まぁ、通常は大丈夫だ。

LighttpdはFastCGIモジュールが標準で付いている上に、活発にメンテナンスされている。これがRailsやなんかのデプロイ環境として人気を集める理由だろう。

多くのLinuxディストリビューションではパッケージ化されていて、Debianでも

# apt-get install lighttpd

だけで入る。

設定例

設定というか、Lighty + FastCGI を走らせる一番簡単な方法はRailsアプリケーションのディレクトリで

# ruby script/server lighttpd -p 80 -e prouction -d

とかやることだ。自動的にconfig/lighttpd.confが生成されて、これを読み込んでLighttpdが立ち上がる。FastCGIのワーカープロセスはLighttpdが管理してくれる。

この要領で開発用サーバーにもLighttpdを使っている人もいる。何しろ、Railsの場合はdevelopment環境ではアプリケーションサーバーの再起動が必要になることは希だし、困らないんだな。もし再起動が必要になってもLighttpdは起動もApacheより速いし。

それでもまあ、自動生成されるのと同様の設定を/etc/lighttpd.confにしてやっても良い。

Apacheの設定とは文法がかなり異質だけど、条件節を書けたりしてプログラム的でちょっと面白い。

$HTTP["useragent"] =~ "^(.*MSIE.*)|(.*AppleWebKit.*)$" {
  server.max-keep-alive-requests = 0
}
$HTTP["url"] =~ "^/doc/|^/images/" {
	dir-listing.activate = "enable"
}

初期状態の設定ファイルからrailsアプリケーションに対応してやるなら、以下のような感じ。

  1. server.modulesの読み込みリストにmod_fastcgiを足す。
  2. FastCGIの設定として次を追記。
server.error-handler-404 = "dispatch.fcgi"
fastcgi.server =  (
	".fcgi" => (
		(
			"min-procs" => 1,
			"max-procs" => 3,
			"socket"    => "/var/run/lighttpd/rails.sock",
			"bin-path" => "/var/rails-tokyo-23/current/public/dispatch.fcgi",
			"bin-environment" => ( "RAILS_ENV" => "production" )
		)
	)
)

ポイントは"404 Not Found"のハンドラとしてFastCGIを設定してやることだな。これはApacheのときに「キャッシュファイルがなかったらmongrelに転送」とか書いたのと同じこと。



他の選択肢

Pound

Pound + Apache + Mongrelというのもあるが、どうも微妙だと思うので時間の都合もあって紹介しなかった。Poundっていうのは軽量のロードバランス・ソフトウェア実装。この場合は構成は次のようになる。

  Pound ─┬─ Apache
           ├  mongrel
           ├  mongrel
           ├  mongrel
           ├  ...

Poundを使うパターンは『RailsによるアジャイルWebアプリケーション開発 第2版』に載ってるので必要ならそっちを参照。

微妙というのは、つまりロードバランスをPoundに追い出すほどの負荷がApacheに掛かることはあるのかな、ということ。RailsアプリケーションでApacheがボトルネックになることは少ないんじゃなかろうか。だとすると、ロードバランサはmod_proxy_balancerでいいじゃないかと思う。

まあ、Apachetが2.1だったり1.x系統だったりしても使えるという利点はあるかも知れない。でも、2.1ならもう潔く2.2に上げちゃいなYO!

SCGI

SCGIというWebサーバー - アプリケーションサーバー間通信のためのプロトコルがある。FastCGIやmod_jkと位置づけとしては同じだ。これのruby版サーバーライブラリとかrails対応というのもある。

けれども、これの作者のZed Shawが結局、mongrelを作ってそっちに移行してしまった。

作者としてmongrelのほうがいいという判断でそっちをメインにやるのであるなら、今後のメンテナンスが不安だ。おすすめしない。

AJP

AJPというプロトコルもある。Apacheモジュールの実装であるmod_jkの名前でも知られている。FastCGIやSCGIと同じ位置づけだ。ApacheとJava Servletコンテナを繋ぐのによく使われている。これのruby版サーバーライブラリとrails対応は私が書いた。

でも、まだ不安定だし、速度も出ないし、そんな状態で放置しているのでおすすめしない。でもApacheサイドでJavaの知見を活かせる技術であるわけだし、私としてはAJPの逆襲をやるつもりはある。そのうちおすすめできるようになったらまた記事を書く。



飲み会

今回は懇親会を昼にやったので、飲み会はとくに呼びかけなかった模様。それでも行きたい人はそれぞれ飲みに行ったみたいだけど。

私は、なんか不安症状とか疲労感がひどかったので早々に帰ってしまった。というわけで飲み会での雑談&与太話は無し。

なんか、勉強会の途中からどうしようもなく疲れを感じて、いつにもましてボソボソと喋ってたと思う。聞きづらくてすんません。


参考資料

Official Documents:

Apache 2.2
Apache設定の資料としては何を置いてもまず公式のドキュメントだ。丁寧だし、主なところは日本語版があるし。
Lighttpd
こちらも設定に必要な一通りのことは公式ドキュメントで十分。(英語)
Capistrano
Capistranoは本記事執筆時点では公式サイトのドキュメントはあんまり充実してない。(英語)

Books:

Agile Web Development with Rails, 2nd Ed. (RailsによるアジャイルWebアプリケーション開発 第2版)
第2版ではデプロイに関する記述が充実した。Poundを使ったパターン、およびCapistranoについて解説している。
Mongrel
オライリーのPDF書籍。(英語)
Capistrano and the Rails Application Lifecycle
オライリーのPDF書籍。昔、Railsのオンラインマニュアルサイトに置いてあったcapistrano解説をまとめたっぽい。Capistrano 1.2対応。2.0は対応していない模様。

Reports:

Rails under "Production"
Rails勉強会用に昔もろはしさん(id:moro)がまとめてくれた資料。
Rails勉強会@東京 #18
舞波さんによる勉強会ログ。各種運用環境の長所・短所を検討した。
LiteSpeed
激速httpdであるLiteSpeedとRailsの組み合わせの解説。
運用サーバー速度比較
舞波さんによる多様なhttpdの比較。

Blog操作

検索


カテゴリー

このブログについて

あわせて読みたい

follow yugui at http://twitter.com

© Yugui

Powered by Movable Type 3.2-ja-2