あいかわらず家から日記を更新することができない状況なので、しばらく前に書いたけどうまくまとまらなくてこの日記には載せずに置いておいた文章をそのまま上げてみることにしてみる。
■ [開発][プログラミング]プログラマからみたゲームプログラミングの本質的複雑さ(1)
「なぜアプリケーションのコードはあんなに汚くなるのだろう?」というのはずっと昔からの疑問だった。最近C#やPhisyXのSDKを触りながらなんとなく考えていることを整理することで、ほんの少しではあるけれど、その答えに近づけるような気がしている。まだ今ひとつ上手くまとまらないのだけど、今考えていることを整理するために、いったん文章に起こしてみることにする。
最近C#でWindowsアプリケーションを作っていて、良くも悪くも「便利すぎる」と感じることが多い。
昔はMFCは大嫌いだったのだけど、.NET Frameworkも基本コンセプトはMFCと似たようなものはずなのに、こちらにはあまり嫌悪感を感じない。使いやすくなったリソースエディタや洗練された設計、高度なインテリセンスなどの補助機能のおかげで、以前はけっこうな手間がかかっていたGUIプログラミングがとても簡単なものになった。低レベルの複雑さを持った部分を可能な限り隠蔽し、クラスへのプロパティの追加やリファクタリングなどの面倒な部分を自動化してくれているために、自分がやりたかった本質部分のみを簡潔にソースに記述するだけで、今までと比較すればごくわずかな手間だけで作りたかったアプリケーションが作成できてしまう。この便利さは「人をダメにするタイプの便利さだ」、と感じるくらいに便利になっている。
また、プログラミングは高レベルな言語になればなるほど、実装の複雑さの詳細をブラックボックスに隠蔽して抽象化して簡単に扱うことができるようになる。
仮にあるゲームのプログラムを本当に極限まで抽象化したすると、最後にはmain()関数の呼び出しだけが残る状態になるのだろう。しかし、「main();」と書いただけではプログラミングしたとはいえないだろうから、プログラマはその中に何らかのやりたいことを関数や処理として記述することになる。しかし、たとえば画面に線を引きたいからといって、いまどきCPUが直接VRAMにガリガリと書き込むようなコードを書くことはまずない。GPUを抽象化したライブラリを通して「線を引け」と命令をだすだけでよく、その命令が実際にどのような形で実装されているのかは考える必要はない。このような形で低レベル部分の抽象化が進めば進むほど、プログラマが直接記述しなくてはならない残りの部分は「アプリケーションの本質」そのものに近づいていくことになるのだろう。
では、「アプリケーションの本質」とは何なのか?
とりあえずこれを「アプリケーションの本質以外の部分を完全に排除したときに、残っているもの」と定義すれば「アプリケーションの本質以外の部分」とは何なのか、ということを考えていくことで答えに近づけるかもしれない。
仮に、「アプリケーションの本質以外」の部分、具体例でいうとゲーム制作において企画側からのネタが全く来ない状態でプログラマ側だけで準備できるもの、を「ミドルウェア」と呼ぶとして、それが「どんなゲーム企画が来ても使用できるような自由度を持ったミドルウェア」であるためには、事前に用意できるのはDirectXで用意されている程度の最低限のモデル表示部分やキー入力受付などの低レベルな部分にとどまってしまうのではないだろうか。
しかし、その企画の前提を「ありとあらゆるゲーム」ではなく「縦スクロール型2Dシューティング」とか「サウンドノベル」みたいな形に限定して範囲を絞れば、用意するミドルウェアの抽象度をさらに上げることができる。作らなくてはならないものの自由度が狭まれば狭まるほど、プログラミング的な抽象化は楽になる。
.Net FrameworkはGUI部品によるWindowsプログラミングを高度に抽象化した、GUIアプリケーションに特化してそれを効率的に作るためのフレームワークでしかないため、これを利用してアクションゲームを作ったり、3Dグラフィックを表示するような使い方は想定されていない。このようなフレームワークは、目的としているものを効率的に作れるようにしてくれる代わりに、そのフレームワークを利用して作られるアプリケーションの幅を狭めてしまう。
高度な抽象化は、利便性と引き換えにそれを使ってできることの自由度を下げる。