本シリーズについて
これまでの10年弱のC++ゲームプログラミング業務で設計について学習・実践を通して得た知見について、ある程度体系的にまとめてみようと思い筆を執りました。
特定のゲームエンジンに依存した内容は基本含まれません。「ゲームプログラマのための設計」と銘打ってはいますが、ほとんどの内容は一般的なソフトウェア実装にも当てはまるでしょう。ただ、筆者のバックグラウンドの都合ゲームプログラミング特有の事情(後述)が想定されていることがあります。
対象読者としては、「言われた通りの仕様は実装できるようになったけど、これからさらにプログラムをきれいにしていくにはどうしたらよいのだろう?」と考え始めたような方をイメージして書いていきます。
特に断りがない場合、バージョンはC++20を想定します。
ゲームプログラミング特有の事情とは?
- パフォーマンスが重視されることが多い
- 動的なメモリ確保に制限があることが多い
- プログラム内の状態が非常に多いうえ、常に更新され続ける
- 制作中の仕様の変更の回数・規模ともに大きい
- テストプレイのためリリース前にも継続して安定して動作する状態をキープする必要がある
- リリース後も、数年間継続的なアップデートが求められることがある
- 続編やリメイクの制作で、終了したプロジェクトのコードが閲覧・再利用されることがある
などがあげられそうです。
参考文献
本シリーズの記事はいろいろな書籍やネット上の情報の集積ですが、中でも下記の書籍は何度も読み返しており色濃く影響を受けているので紹介します。
- Effective C++
- Effective Modern C++
- Game Programming Patterns ソフトウェア開発の問題解決メニュー
- C++ソフトウェア設計 ―高品質設計の原則とデザインパターン
- リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック
- Clean Code アジャイルソフトウェア達人の技
お品書き(予定)
重要ではあるがすでに広く知られており、筆者にも特に追加で言いたいことがないものについては 前提知識 としてマークしておきます。
原理・原則編
対象とする構造の大小を問わず活用可能なテーマ
- 変数のスコープ再考①(変数編)
- 変数のスコープ再考②(関数編)
- カプセル化再考
- GRASP
- 事前条件・事後条件・普遍条件
- DRY再考
- YAGNI再考
- CQSとCQRS
前提知識:
- SOLID原則
- 循環的複雑度
- リーダブルコードに載っている命名やコメントに関する事項
アーキテクチャ編
プログラム内で一番大きい構造にかかわる話題
- クリーンアーキテクチャとゲーム
- コンポーネント指向
- データドリブン・データとの境界は共通化しよう
- エンティティと値オブジェクト
デザインパターン編
いわゆるGoFのデザインパターン自体の話題や、その他それが対象としている領域に関するもの
- 直和の表現にはVariantか継承か
- Visitorパターンにはstd::variant
- 高階関数で置き換えられるもの
- DI
- 継承との付き合い方
- NVI
- 事前処理・事後処理の強制方法比較
- Adapterパターンと、その先のExternal Polymorphismパターン
- 型消去
前提知識:
- Gofのデザインパターンの概要ざっくり
実装詳細編
C++言語機能や標準ライブラリなど、C++固有の話題
- C++における抽象化の手段比較
- RVOでサイズの大きいインスタンスを返す
- ユーティリティ関数の置き場所
- 指示付き初期化
- 高階関数
- variant
- function
- 関数型プログラミングとC++
前提知識:
- C++14以前の言語機能・ライブラリの多く(スマートポインタ、ラムダ式など)
- RAII