2006-07-22

可搬性の話のつづき

"Write Portable Code" を読んで色々思うところがあったので書いておく.

可搬性のある C/C++ コードを実現するプローチの中心は, プラットホーム/OS の差異を吸収するライブラリを作ることだろう. たとえば Apache Portable Runtime, SDL などはよく知られている. これらに限らず, でかいクロスプラットホームなプロジェクトにはだいたいサブプロジェクトで プラットホーム抽象化レイヤがある. 他には Mozilla の NSPR, Eclispe の SWT, GIMP/GTK+ の GDK など 探せばきりがない. これらは環境依存のコードをライブラリの "下" に隠そうとする.

可搬性の IoC

別の(排他でない)アプローチがある. 環境依存のコードをライブラリの上...だと自分のコードから見えてしまうから, もっと上, 自分のコードの上に持っていく方法. イメージとしては, 自分のコードの大半が可搬で巨大なライブラりになり, そのライブラリを使う可搬でないコードを環境毎に少し書く, というかんじ. 典型的には MVC の M (と場合によっては C) を可搬に作って, V は環境毎に書く. そんなアプローチもけっこうある.

当たり前の話.

ただ portability に執着しすぎた結果, 無闇に "main 以外は全部ポータブル" と可搬性原理主義に走ってしまう人もいる. その結果, 可搬性を実現する("下" を作る)コストが "上" を作る手間を超えてしまうことがある. (cygwin をその最たる例と見ることもできる.) 自分の書くコードがそうなると面倒が多い. だから私は積極的に "上" に押しだす路線を好む. 私はこれを勝手に "可搬性の IoC" と呼んでいる. (名前をつけるほどのものじゃないかもしらんけど.) 対象によっては, モジュールのの主従関係を割と柔軟に選べることがある. そのへんの手口については 前に書いたとおり.

"上" のコードにはなんとなく書き捨てっぽい印象をうけるかもしれない. けれど, 環境の差異を吸収するという意味で "上" も "下" もコードの役割は同じだ. 無理に書き捨て感を紛らわそうとすると抽象クラスだらけでかえって複雑になってしまう. 私の感覚だと UI のコード, リソースの寿命管理のコードは上に書いた方が融通が効く. 一方向の抽象化に囚われず全体の単純さを保てるよう工夫したい.

可搬なビルドプロセス(が欲しい)

以下愚痴.

可搬なことになっているプロジェクトをビルドしようとすると, 大抵苦労する. オープンソースの場合, 可搬にするくらい頑張っているプロジェクトは 大規模なものが多いから複雑なのは仕方ない面はある. それにしても辛い. たとえば mozilla や OpenOffice を Windows 用に build するのは苦行だ. APR もけっこうコンパイラを選ぶ. ビルドプロセスは一つの環境向けに作られていることが多く, 他の環境では移植者の "がんばり" が期待されている. 私はそうしたプロジェクトのビルドに挫ける事が多い. 挫けた相手を可搬と呼ぶのは歯がゆい.

私のように趣味で一旦ビルドしたいだけの場合はまだいい. 仕事の上でよくあるケース: コードを書く開発者と移植担当がわかれており, かつメインのビルド環境はコードを書く側が管理している場合, 事態はより辛くなる. たとえば Makefile の同期に漏れがあって謎のリンクエラー, ビルドスクリプトが環境依存のツールを呼び出している, など.

サードパーティの "可搬な" ライブラリに依存しているプロジェクトも厄介だ. たとえば, ある日メイン環境でのトラブルを解決するため 外部ライブラリのバージョンを更新したとする. 移植担当者が別の環境でビルドする差異にバージョンの更新に気付き, その環境でもライブラリを更新しようとするがうまくいかない. よく調べると前のバージョンは前任者が苦労してビルドしたもので, もともとそのライブラリを件の環境でビルドする公式な Makefile は存在しないことがわかった. しかも謎のパッチがあたっている. ああ... ということもある.

他のパターンとしては, あるところに Windows 上で 複数の可搬ライブラリを使った開発をしているプロジェクトがあったとする. 移植担当者はいつものように linux 上でビルドをしていたが, ある日ビルドができなくなる. あるいはテストに失敗する. コードは変わっていないのにおかしいと思ったら, 毎夜実行している apt-get でライブラリのバージョンがあがって そのバージョンの非互換性/バグを直撃していた. もういや... ということもある. (なんで unstable つかってんだよ!)

プロジェクトの構成が複雑になってくると, 可搬であるための困難はコードそのものから構成管理に移ってくる. (いんてぐれーしょんというやつですね.) そういう問題の解決に挑む人はあまりいない. 楽しくないからだろうか. ただ, ビルドプロセスも含めて可搬になっていないと可搬性の有難味は薄れてしまう. たとえコードがオープンソースでコードが公開されていても, ビルドが大変だと availability は下がる. ビルド済バイナリもコードも簡単に手に入るのに, 自分でビルドするのが難しいという状況はオープンさを損ねていると思う. 情報公開はしているけれど整理はされず, 倉庫に山積みされたままの自治体の資料のようになりかねない.

公開する側の視点から見ると, 構成管理が複雑になるとコードをオープンにするコストが負担になるとも言える. もう面倒だから Java や ruby でいいか, という気分になってくる. それもありなんだろうけれど C++ 好きとしては悲しい. 世の中の C/C++ コミュニティは可搬な構成管理のコストをなんとか分散して負担し, 可搬性を含めてプロジェクトをオープンに保ちつづけて欲しい思う.

たとえば可搬な apt-get が欲しい. たとえば GNU-Makefile も .vcproj も .xcodeproj も出力できるメタ autoconf が欲しい. そんな一式を揃えた可搬な環境が欲しい. 皆にそれを使ってほしい. まあ有り体にいうと, オープンソースのライブラリをじゃんじゃか使ったコードを windows 上の VC++ で書きたいなーってことなんだけど. どこかにないかなあ.