ゲームプログラマのためのコーディング技術

書籍の概要

この本の概要

多くの機能を持つゲームのプログラムは,巨大で複雑になりがちです。また,コードの保守,機能追加などの工程には複数のプログラマが関わることになります。そのため,ゲームのプログラムには「わかりやすいコード」と「効率よく機能を追加できる設計」が求められます。これはゲームに限らず,職業プログラマとして必要なコーディング技術です。本書ではC++のサンプルコードをもとに,すぐに実践できるコーディング技術を解説していきます。まず,コードの抽象化を理解するため,複雑なコードを単純にして小さくするテクニックを紹介します。続いて,オブジェクト指向設計の原則とパターンにふれながら,シンプルでより良いクラス設計とは何かひも解きます。

こんな方におすすめ

  • 脱プログラミング初心者,新人ゲームエンジニア,ゲーム開発初心者

この書籍に関連する記事があります!

ゲームプログラマのためのリーディング(読書)技術
プログラマであれば,多かれ少なかれ技術書を読む機会があると思います。

目次

  • はじめに

第1章 わかりやすいコードを書くためのテクニック

1.1 わかりやすいコードとは

  • コードの保守性
  • わかりやすいコードを書くコツ
    • 簡単にできることからはじめる

1.2 変数と定数

  • 意味が伝わる変数名を付ける
  • マジックナンバーに名前を付ける

1.3 計算式と条件式

  • わかりやすい条件式を書くコツ
    • 説明用変数を使う
    • 条件式を関数化する
  • わかりやすい計算式を書くコツ
    • 説明用変数を使う
    • 計算式を関数化する

1.4 assertの活用

  • assert(表明)の使い方

1.5 制御文

  • if文の削減と単純化
    • 下限値・上限値チェックの関数化
    • ラップアラウンドの関数化
    • 早期リターンへの書き換え
    • 重複した条件式の統合
    • 重複した複合条件の統合
    • 条件式が直接関係する部分を局所化
    • 配列の活用によるif文の削減
    • 決定表によるif文の削減
    • nullオブジェクトの導入
  • for文の削減と単純化
    • STLのアルゴリズム関数への置き換え
    • 検索ループの分離
    • ループ内の不要な条件の分離
    • ループの分割
    • ラムダ式によるループの一般化
  • switch文の削減と単純化
    • case内の関数化
    • defaultにassert
    • ポリモーフィズムに置き換え

1.6 関数

  • 関数の基本原則
    • 1 つの関数につき1 つの仕事
    • 関数を2 種類に分類する
  • 関数化のパターン
    • 条件式の関数化
    • 計算式の関数化
    • 条件分岐のブロック内の関数化
    • ループの関数化
    • ループのブロック内の関数化
    • データ変換の関数化
    • データ確認の関数化
    • 配列アクセスの関数化
    • コメント部分の関数化
  • 多過ぎる引数の問題
    • 欲張りな関数
    • クラス化が不適切
  • 小さな関数の必要性
    • 自己説明的なコードになる
    • 単体テストが可能になる
  • 小さな関数による実行速度低下
  • 関数化の目的は再利用だけではない
  • 関数を書くときの心得
    • まずは書いてみる
    • 最初に書いた関数は下書き
    • 問題の本質を理解する
    • 読み手の視点で確認する

1.7 クラス

  • クラス化のコツ
    • 大きな関数を分割する
    • 関数名からクラス候補を見つける
  • クラス化のパターン
    • 重複部分のクラス化
    • 組込型メンバ変数のクラス化
    • 関数の引数のクラス化
    • コンテナのクラス化

1.8 小さなクラス

  • Timerクラスの例
  • Scoreクラスの例
  • 範囲クラスの例
  • 2Dベクトルクラスの例
  • 整数型の2Dベクトルクラスの例
  • 矩形クラスの例
  • そのほかの数学系クラス
  • typedefの活用

1.9 まとめ

第2章 シンプルな設計のための原則とパターン

2.1 オブジェクト指向設計の基本

  • カプセル化,凝集度,結合度
    • カプセル化
    • 凝集度
    • 結合度
  • 継承と委譲の関係
    • 継承よりも委譲を好む
    • 機能の継承と抽象インターフェースの実装
  • オブジェクト指向設計の原則
    • 単一責任の原則(SRP:Single Responsibility Principle)
    • 開放・閉鎖の原則(OCP:Open-Closed Principle)
    • リスコフの置換原則(LSB:Liskov Substitution Principle)
    • インターフェース分離の原則(ISP:Interface Segregation Principle)
    • 依存関係逆転の原則(DIP:Dependency Inversion Principle)
    • デメテルの法則
  • デザインパターン
    • Template Methodパターン
    • Strategyパターン
    • Stateパターン
    • Compositeパターン
    • Iteratorパターン
    • Observerパターン
    • Singletonパターン
    • デザインパターンには複数の実装例がある
    • デザインパターンを活用する
    • デザインパターンを乱用しない

2.2 クラス設計のコツ

  • クラス設計の基本
  • クラスの役割を考える
    • 作業役クラスと管理役クラス
    • 仲介役クラス
    • 窓口役クラス
    • 生成役クラス
    • 専用クラスと汎用クラス
  • クラスの責任を考える
  • クラスの抽象度を考える
  • クラスの結合を考える
  • 抽象インターフェースの利用方法
    • クラスの共通化
    • 実装手段の交換
    • 変化しやすい部分の分離
    • 不適切な結合関係の分離
    • パッケージ境界の分離
    • 抽象インターフェースは利用者側に持たせる
    • 抽象インターフェースは分離と交換をするための道具
  • そのほかの注意点やテクニック
    • コンストラクタで完全な状態にする
    • メンバ関数の呼び出し順番の対処法
    • 初期化はコンストラクタ,後始末はデストラクタで行う
    • 実装の詳細を隠蔽する名前を付ける
  • クラス設計初級編
    • 大まかにクラスを洗い出す
    • 利用者の視点でメンバ関数の仕様を決める
    • メンバ関数を実装する
    • 役割と責任を考えながらクラスを分割する
    • 結合を考える
    • カプセル化,凝集度,結合度の確認
  • クラス設計中級編
    • 問題領域と実装領域を分離させる
    • 問題領域を中心に考える
    • 抽象インターフェースで分離する
    • より複雑なものは複数の階層に分割する
  • クラス設計上級編
    • コンセンプトとコンテキストが重要
    • 規模に合わせた設計をする
    • コードの寿命を考える
    • 作業のしやすさを優先する
    • 1つの手段にこだわり過ぎない
    • いかに書くかではなく,いかに書かないか

2.3 まとめ

第3章 ソースコードの品質計測

3.1 メトリクス計測

  • ファイル,関数単位のメトリクス
    • コード行数
    • コメント行数
    • ステートメント数
    • 最大ネスト数
    • サイクロマティック複雑度
    • Halstead複雑度
    • 保守性指標
  • オブジェクト指向のメトリクス
    • 凝集度
    • 結合度
    • 継承の深さ,子クラスの数
    • クラスの重み付けメソッド数

3.2 コードクローン検出

3.3 静的コード解析

3.4 メトリクスの活用法

  • コーディング規約として活用する
  • コードレビューの優先度として活用する
  • メトリクス計測を目的にしない
  • メトリクス計測でプログラマの評価をしない

3.5 ツールの紹介

    • SourceMonitor
    • Cppcheck

3.6 まとめ

次のステップへ~参考文献の紹介

    • プログラム設計,コーディング技術
    • C++
    • メトリクス計測