2010年2月10日水曜日

Wiki ページとリファクタリング

パターン、Wiki、XP』に、オリジナル Wiki の設計思想のひとつとして「ドキュメントはプログラムのように記述されるべきだ」(p145, 153) という言葉が挙げられている。しかし、現在主に使われている Wiki エンジン (ここでは主に Trac と Redmine の Wiki 機能を想定している) に至っても、そのページ編集におけるユーザエクスペリエンスは、例えば Java コードを Eclipse でリファクタリングするときのような自在な感覚からはほど遠い窮屈なものだ (あえてそこに制限を加えることで得られる何かがあるか ? という点についてはとりあえず問わないことにする)。

手始めに、一定以上の規模の開発プロジェクトなら必ず発生する、複数ページの用語の一括置換について考えてみよう。現状では以下のような手段がある。

バックエンドデータベース内容の置換
Trac や Redmine で Wiki ページの実データがどのような形式で保存されているかは比較的簡単に確認することができ、置換 SQL をその場限りで実行すれば一応目的は達成される。が、変更履歴は残らないし、変更履歴を残すようにするにはより複雑なデータ操作が必要だ。さらに、こうした対処を実行できるのは、(置換処理をプラグイン化でもしない限りは) データに直接アクセスできる権限を持つ者に限られる。
Web クライアントライブラリによる置換
Ruby の Mechanize や Watir のような Web クライアントライブラリを使えば、人のブラウザ上での操作をなぞるようにして、複数ページの置換を自動化することができる。が、処理速度や、履歴の各ページへの散逸や、排他制御などの問題は残る。

いずれにしても目的に対しての手順が不必要に煩雑であるし、用語の一括置換より複雑なレベルのリファクタリング (ページのマージや項目の階層移動) になるともう対応しきれない。

ここで前提条件をひとつ変えてみよう。Wiki エンジンのバックエンドデータベースが、Trac や Redmine のそれのような RDBMS ではなく、Subversion などのバージョン管理システムであったらどうだろうか。

バージョン管理システムベースのページソースの置換
1 ページにつき 1 個のソースファイル (例えば、reStructuredText 形式のファイル) がまとめて checkout / commit できれば、あとは一括置換なりページのリネームなりは自由に実行できる。さらに、複数ページの置換がばらばらの操作ではなくアトミックで意図の明確な一つのリビジョンアップとして記録されるし、排他制御における競合への対処はバージョン管理システムが得意とするところだ。

これは自然な選択肢であるように思える。単純なリファクタリングにとどまらず、(ページの名前空間がフラットである制約を外せば) 安定版バージョンのページを trunk で、開発版バージョンのページを branches で、それぞれ並行運用し時期を見てマージするといった、まさにソースコードと同じライフサイクルでのページ編集を実現できる。用語の一括置換より複雑なレベルのリファクタリングについても柔軟に対応可能だ。

パターン、Wiki、XP』にも、初期の Wiki クローンがバージョン管理システムをバックエンドにしていたとの記述がある (p156) し、例えば Hiki には Subversion をバックエンドとするモードがあるようだ。しかし、現在多く使われている Wiki エンジンでは、なぜこうしたアーキテクチャが採用されていないのだろうか ?