バスケットボールやサッカーの選手が、あまりにシンプルで効果的なプレーをしているのを見て、「なぜ誰もが同じようにプレーできないのだろう?」と思ったことはありませんか?その選手は、単純な技術だけを使っているように見えます。
C++プログラマーである私も、John Carmackのソースコードを調べたときに同じことを考えました。コードがあまりにシンプルで、なぜ私たちが彼のようにソフトウェアを書けないのか不思議に思うほどです。
ここでは、Doom 3のソースコードにおけるいくつかの設計上の選択を見ながら、シンプルでありながら非常に効率的なコードがなぜ生まれたのかを探ってみましょう。
2011年11月23日、id Softwareはこれまでの伝統を守り、前世代エンジンの ソースコード を公開しました。このソースコードは多くの開発者によってレビューされました。以下は、Fabien SanglardによるDoom 3へのフィードバックの一例です(原典):
Doom 3 BFGはC++で書かれています。C++は非常に広大な言語であり、優れたコードを生み出すことも、目を背けたくなるようなひどいコードを生み出すこともできます。幸い、id Softwareは「クラス付きC」に近いC++のサブセットに落ち着き、頭にすんなり入ってくるコードになっています:
- 例外を使わない。
- 参照を使わない(ポインタを使用)。
- テンプレートの使用は最小限。
- constを随所に使用。
- クラス。
- ポリモーフィズム。
- 継承。
要約すると、使用されているのはC++98標準のサブセットだけです。以下はDoom 3の設計上の選択です:
1. 有用なサービスを提供する共通の基底クラスを用意する
多くのクラスがidClassを継承しています:

idClassは次のサービスを提供します:
- インスタンス生成。
- 型情報の管理。
- イベント管理。

2. 文字列操作を容易にする
一般に、文字列はプロジェクトで最も広く使われる型の1つであり、文字列に対して多くの操作が行われるため、それらを操作する関数が必要です。
Doom 3では、文字列を操作するための有用なメソッドのほぼすべてを備えたidStrクラスが定義されています。他の多くのフレームワークが提供する文字列クラスのように、独自のメソッドを定義する必要はありません。
3. ソースコードはGUIフレームワーク(MFC)から強く分離されている
MFCを使う多くのプロジェクトでは、コードがMFCの型と強く結合しており、コード内の至る所でMFCの型を見つけることができます。
Doom 3では、コードはMFCから強く分離されており、GUIクラスだけがMFCに直接依存しています。これは次のCQLinqクエリが示すとおりです:

この選択は生産性に大きな影響を与えます。実際、GUI開発者だけがMFCフレームワークに対処すればよく、他の開発者はMFCに時間を浪費せずに済むからです。
4. 非常に優れたユーティリティライブラリ(idlib)を提供する
ほぼすべてのプロジェクトで、最もよく使われる型はユーティリティクラスです。次のクエリ結果が示すとおりです:

ご覧のとおり、最もよく使われているのはユーティリティクラスです。C++開発者が優れたユーティリティフレームワークを使わないと、開発時間の多くを技術レイヤーの処理に費やすことになりかねません。
idlibは、文字列、コンテナ、メモリを扱うために必要なすべてのメソッドを備えた有用なクラスを提供します。これにより開発者の作業が容易になり、ゲームロジックにより集中できるようになります。
5. 実装が非常に理解しやすい
Doom 3には独自実装のコンパイラが含まれています。C++開発者ならご存じのとおり、パーサーやコンパイラの開発は容易な作業ではありません。それでもDoom 3の実装は非常に理解しやすく、コードも非常にクリーンです。
コンパイラが使用するクラスの依存関係グラフは次のとおりです:

以下は、コンパイラのソースコードからの抜粋です:

これまで多くのパーサーやコンパイラのソースコードを調べてきましたが、これほど理解しやすいコンパイラのソースコードに出会ったのは初めてです。Doom 3のソースコード全体にも同じことが言えます。まるで魔法です。Doom 3のソースコードを読み進めると、思わず「WOW、美しい!」と言ってしまいます。
要約すると、Doom 3のソースコードは非常にクリーンで、理解しやすく、保守も容易です。そして、標準のサブセットだけを使用しています。高度なテクニックは使われておらず、コード設計、命名、書式設定の基本的なベストプラクティスに従っています。
John Carmackの秘訣は、Wikipediaで定義されているKISS原則だったと言えるでしょう:
KISS is an acronym for "Keep it simple, stupid" as a design principle noted by the U.S. Navy in 1960.[1][2] The KISS principle states that most systems work best if they are kept simple rather than made complicated; therefore simplicity should be a key goal in design and unnecessary complexity should be avoided. The phrase has been associated with aircraft engineer Kelly Johnson (1910–1990).[3] The term "KISS principle" was in popular use by 1970.[4] Variations on the phrase include: "Keep it simple, silly", "keep it short and simple", "keep it simple and straightforward",[5] "keep it small and simple" and "keep it stupid, simple".[6]この定義で興味深いのは、次の一文です:
KISS原則によれば、ほとんどのシステムは複雑にするよりもシンプルに保つ方が、より良く機能します。新しいC++標準を採用する際、私たちはどのような教訓を得るべきでしょうか?
新しい標準では、興味深い新機能が多数導入されました。しかし、これらの機能をすべて使えばコードが自動的に効率的になると考えるのは誤りです。多くの新機能は、特にジェネリックプログラミングに関連する機能など、汎用ライブラリを開発する場合により役立ちます。
すべての新機能を無理に使おうとしないでください。機能は、本当に必要で、コードをより良く、より効率的にする場合にだけ使いましょう。たとえば、こちらの興味深い 記事 では、autoキーワードの使いすぎによる欠点が説明されています。
