2011-10-15

WEB+DB PRESS 総集編 / I told my code to sing

"わたしはじぶんのコードにうたえと命じた" と題して WEB+DB PRESS 総集編 に小話を 書かせていただきました. レビューしてくれたひとありがとう. 表題は モンキービジネス 14 号 に載っていた 柴田元幸訳 ディキンスン の "わたしはじぶんの魂にうたえと命じた" から.

小話はさておき, 私にとって一番面白かったのは...目次だった. 時代の移りかわりを感じられていい. 記事本体は古い方から読んでいくと楽しい. 私はふだんテクノロジの世代交代が進まないもどかしさを感じているけれど, JSP と ASP (ASP.NET ではなく) を説明した記事のおかげで 無事に滅びたテクノロジもそれなりにあったことを思いだした. そういえば SOAP もだいたい滅びたよね. 時代はちゃんと前にすすんでいる. めでたい. いま必要な新しいテクノロジーを調べるだけでなく 消えてしまったテクノロジーを偲び世界平和に思いをはせるのも総集編の楽しみだと思う.

要するにプログラミングって

他の人の小話を読むとキャリアの話をしている人が目立った. そうかそういう話が期待されていたのか... 自分のやつは空気を読めてなかったと反省し, 空気を読んだバージョンを書いてみることにする:


西海岸の同僚に, ある若い WebKit の開発者がいる. 彼の書く一連のコードを見たとき、自分とは何かが決定的に違っており気になっていた. あるとき彼の最初のプログラミング言語が JavaScript だと知って腑におちた. 頭の中にある第一の抽象が私とは違うのだろう.

これは一般的なプログラミング能力の話とはちょっと違う. すごくコードの書けるプログラマが書くコードを読んだところで必ずしも違和感はない. 仕事は速いし難しいことをやってのけるけれど, それは単に能力の違いだと思える. 先のプログラマはもっと異質な感じがする.

プログラミング = ツリートラバーサル

私が会社員になって最初にやった仕事はブラウザのようなものの開発だった. 学生のころは大してコードを書いていなかったので, その仕事が本格的に書いた最初のコードだった. ブラウザ的プログラミングとは要するに複数のツリー構造 (いわゆるブラウザだと DOM, Rendering Tree など)を 整合性のある状態に保つ仕事であり, 日々頭の中にあるのはいつもツリートラバーサルのことだった. とにかくツリートラバーサルばかりやっていた. このノードから DFS をはじめてこの条件の時には子を skip して, このノードはまだ準備ができていないからキューにつめてあとまわし, こいつは prune して, このサブツリーは作りなおしたいが子は再利用できそう. でも二回トラバーサルするのは遅いからなんとかワンパスにしたいのでマークでもつけとくか... みたいなことを延々考えていた記憶がある.

インハウスのツリートラバーサル用ライブラリの影響はうけたと思う. そのライブラリに乗って書くコードはツリーを意識せざるを得ない, そんなライブラリ. 今思えば変わったコードだった. たとえば WebKit のデザインではツリーの存在を全面に押し出していない. だから書かれるコードでもトラバーサルは目立たない.

ツリー構造, ツリートラバーサルはよく使われる抽象なのに, それを強調した抽象が広く使われていないのは不思議といえば不思議だ. Adobe の Forest なんかは割とうまくやっている.

プログラミング = 状態遷移

プログラミングって要するにツリートラバースだよね. あるときそんな話を友達にしたら, いやそれはちがうと諭された. その友人は当時 Ajax なウェブアプリケーションを開発しており, 彼にとってのプログラミングとはいかに状態遷移をうまく表現して破綻をふせぐかの戦いだった. XHR を並列に発行し, 非同期に結果をうけとりながら状態を遷移していく. その間にもユーザが UI を操作するかもしれない. UI もまた状態遷移をおこす. 画面も遷移する. 非同期に巻き起こるイベントの中でいかに堅牢かつ高速な UI をつくるか. そんな戦いなのだと友人は説いた.

その数ヶ月後に "俺はついに究極のデザインパターンに辿りついた" みたいな話をきいた気がするけれど その内容は覚えていない. そういえば数ヶ月毎に似たような話を聞いていた気がする. 要するにそのときの友人にとってプログラミングは状態遷移だったのだろう.

プログラミング = ページング

ツリートラバーサルに飽きて移った新しい職場では隣の同僚が BTree を書いていて, 私の仕事はその上のレイヤであれこれやることだった. 同僚は RTree (じゃないけど似たようなもの)も書いていた. BTree にしろ RTree にしろツリー構造を扱うところはブラウザに通じなくもない.

一方, そのとき私はちょうど Database Management Systems を読んでいた. そして保守の予感を感じていた BTree と RTree を読みながら, これって結局ページキャッシュをどうするかって話だよね, なんてことをぼんやり考えていた. どのページを捨て, どのページを読み, 何ページぶんプリフェッチしようか, あとこのページはフラッシュしなければ... 件の BTree と RTree もキャッシュの扱いには苦心していた.

比較的大きなデータファイルを読み書きすることが多い仕事だったせいもあり, 私は "プログラミング = ツリートラバーサル" 派から "プログラミング = ページング" 派に宗旨がえしかかっていた. ただその仕事は割とすぐにおわってしまったためページング派になりきることはなった.

プログラミング = 直列化とルーティング

次に記憶にのこっている大きな仕事では, RPC を使ったマルチティアなネットワークベースのサービスを開発した. アプリケーションが比較的とシンプルなものだったのと, RPC ライブラリ自体のメンテナンスに結構な時間を割いていたせいもあり, その仕事でのプログラミングは要するに届いたバイト列をパースして中身を見て 新しいデータをつくって直列化して送信/返信することだと感じていた. ヘッダの何バイト目に何を押し込むか, そんなことに悩みつづける時期があった.

RPC の他に苦労したのはメッセージのルーティングだった. そのつくりも自分の脳内資源を占有していた. ルーティングといっても Internet Protocol の皆様みたいに大袈裟なものではなく, Rails の routing や Apache の mod_rewrite に近い. フロントエンドに届きバックエンドに転送する必要のあるメッセージに対し, その転送指定をどれだけ宣言的かつ柔軟に書けるか. 使いもしない Apache のマニュアルを読みながらよく考えていた.

プログラミング = テキスト整形

余暇にはじめて Rails をさわった時, ウェブのプログラミングは要するにテキスト整形なのだと思った. たぶん今時のウェブ開発は違うだろうけれど, 私がそのとき作ろうとしていたのは凝った動きがいらない簡単なサイトだった. プログラミング中は主に erb のテンプレート書きに時間を使っていた記憶がある. Ruby まじりの HTML を書きながら, PHP が生まれるのもわかると納得していた. (素人の話なので専門家は聞き流してくださいね...)

プログラミング = innerHTML 仮説

冒頭の JS 出身 WebKit 開発者にとってプログラミングとは何なのだろうとよく考える. JS でさわる DOM はツリーだから, 結局はツリー操作だというかもしれない. 私もそう思っていたけれど, 最近は気が変わりつつある.

DOM には innerHTML があり, innerHTML がプログラミングモデルに与えている影響は大きい. jQuery を見てもわかるように, HTML 断片と DOM の変換は一部の JS プログラマにとって 欠くことのできない重要なプリミティブになっている. Rails の partial update など サーバ側のフレームワークも innerHTML を前提に作られている. 私の感覚だと innerHTML はものすごい大技で, できれば近づきたくないものに見える. でも HTML フラグメントと DOM の上で育ったプログラマにとっての innerHTML は, 私にとってのポインタ演算みたいなものかもしれない. ポインタに "*" や "&" をつけるとき私がいちいちキャッシュミスやアラインメントを気にしないように, innerHTML を使う彼らの脳裏に HTML パーサの字句解析や文字列連結がよぎることはない, 気がする.

そんな彼らにしてみれば, 私にとってアクロバティックな DOM の操作も jQuery のワンライナーに毛がはえたようなもの. そう考えると件の WebKit 開発者による怒涛の変更も納得できる. 彼は DOM まわりで色々なバグを直している. そして WebKit のややこしい部分では DOM と文字列の往復がたびたびおこる. 彼はまず頭の中で JavaScript を書き, それを C++ に変換しているのかもしれない. その境地からほど遠い身には憶測しかできないけれど.

技術的面倒のデザイン

ドメイン駆動設計 は <プログラミングって要するに何なの?> という疑問に一歩下がった視点で答えた: プログラミングとは <あるソフトウェアが要するに何なのか> を説明する試みである. Eric Evans の主張を私はそう理解している.

Eric Evans の言うことは的を射ている. 一方で不満もある. 彼の選ぶ題材はエンタープライズ寄りなドメインの複雑さに偏りすぎていて, 技術的な面倒くささは, 宇宙飛行士的な無茶はしないにせよ, 隠すべきものとして扱われている. でも技術的な面倒くささを隅に追いやるのは常に正しいのだろうか? それはいつも押入に押し込みきれるのか?

私は会社員になってからエンタープライズなシステム開発をしたことがないので, 顧客企業が扱うビジネスモデルの複雑さ, みたいなものに苦しんだ経験がない. どちらかというと技術的な面倒をなんとかすることがプログラミングのむずかしさの中心にあった. 技術的面倒とは必ずしもハイテク的な難しさではない. むしろ事前のまずい意思決定やレガシーからやってくる.

そんな仕事では, どんな技術的制約が問題をややこしくしていて, コードの上でそれをどう解釈し折り合いをつけるかが本題になりうる. 会話に使う語彙も技術寄りになる. 技術的面倒をとりあつかうソフトウェアは Eric Evans のパターンだとカバーしきれない. テクニカルな面倒に対するドメイン駆動設計世代のアプローチが, ほんとはあっていいと思う.

板挟みとのたたかい

アプリケーションのドメインと技術的面倒のドメイン. いつも一方が支配的とは限らない. 二つは混ざりあう. その混在がソフトウェアをややこしく, 同時に興味深いものにする.

ある QCon の講演 で, Facebook の Nick Schrock が Facebook コードベースの進化を, Eric Evans の言葉を借りるなら "しなやか/supple" になる様を紹介している. 技術的面倒とアプリケーションの面倒の双方をねじふせるデザイン, そして理解にいたるプロセスをよく伝えている.

Facebook の技術的面倒はまずなんといっても scalability だろう. 巨大かつ多様なデータをかきあつめて一刻も早くページを返したい. データベースは当然のように分割されており, live なデータが多いのでキャッシュの効き目は弱く, クエリーは並列に投げなければならず, けれどよりよって PHP なので非同期のコードを書きづらい.

アプリケーションの難しさはデーターソースの数と細かなプライバシ指定に由来する. 誰に何を見せていいのかを常に気にしなければいけない. きわどいデータを扱う割に機能はガンガン増えていく.

技術的制約が厳しいのでナイーブなモデリングはできない. ザッカーバーグ先生のひどいレガシーを何とか立てなおす必要もある. PHP はうんざりだけどユーザも開発者も機能も増えすぎちゃった上に サーバがモジュラーじゃないせいで違う言語に書き直す暇もない. (半分くらい誇張なので正確な内容はビデオで確認ください.)

そんなハードコアデスマの中から Preparable と呼ばれる擬似非同期プログラミングフレームワークと プライバシーを組み込んだオブジェクトグラフトラバサール DSL の Ent が生まれる. どうみても Facebook 以外では使い道がなさそうな API にしびれる. それは少しずつ問題を理解し, 無念なコードを飼い馴らしてきた獣使いの証だ.

質疑応答の中で "なんで PHP なんですか?" なんて聞いてるやつがいたので, おもわず "おまえは何もわかってない! Twitter で Scala でも書いてろ!!" と 恫喝したくなったが個人の見解ですし私も Scala の方がいいですがそういう話じゃねーんだよ!

半年くらい前に投稿された Facebook Engineering の Note が説く残念なコードに対する心構えも Nick Schrock のストーリーに符合している. 彼らのたたかう問題が垣間みれるようで面白かった.

Primary Abstraction

だいぶ話がそれた.

プログラミングが要するに何なのか, いちばん自在に扱える抽象は何か. 私はプログラマの Primary Abstraction (PA) と勝手に呼んでいるけれど, それはたぶん人によって違うとおもう. 技術的側面の PA を持つひともいれば, アプリケーションドメインの PA を持つ人もいる. 間にある人もいる. 仕事の数だけ抽象がある. 人々はどんな抽象を背にコードを書いているのだろう.

私は最初の就業体験が尾を引き, いまだにツリートラバーサルから抜けだせていない. 他の PA に近づいたこともあったけれど, 結局切り替わることはなかった気がする. マークアップ言語処理系開発者の PA としてツリートラバーサルは悪くないと思うけれど, JavaScript な開発者がもっている innerHTML の PA を 少しでも理解できれば見える世界が変わる気がして, あとツリートラバーサルはいまいち潰しがきかない気もしていて, たまに JS をさわってみたりする. でもまったく板につかない.

このさき自分は PA をリセットできるのか. あるいは PA を複数もつことはできるか. あまり楽観はしていない. 必要性もはっきりしない. PA は母国語のようなものだと思う. 世の中にはバイリンガルもいるので, PA を複数持つ人がいても不思議はない. スーパーハカーとかはそういう人なのかもしれない. 母国語...というか第一言語を変えるのは大変そうだ.

一方 PA は母国語ほど大仰でないとも思う. 文化的適応の方が近いかもしれない. 違う国にひっこして何年も暮らせば, 段々とその土地に馴染んでいく. いきつけの食堂ができて, テレビに流れるジョークを笑えるようになって, すれちがう隣人と世間話だってできる. そんな新しい暮らしを空想することはある. 空想上の自分が独りでいるのに気付き, そのさびしさに震えることもある.