読者です 読者をやめる 読者になる 読者になる

「ゲームプログラマのためのコーディング技術」を読んだ

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

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

ゲームプログラマではないけど...
読んでみた。

ゲームと唄っていますが、またコード例はC++ですが、
例なだけで、より汎用的なコーディング技術をざっと学べる本。(リーダブルコード、リファクタリング本と同様の切り口)

TL;DL

  • コードの意図を伝えよう
    • 問題を深く理解し、小さく分割
    • 対象となるものの本質を掴み、わかりやすい名前を付ける
  • 凝集度(1つの事を行う)は高く、結合度(他のクラスとの関連)は低く
  • "いかに書くのか"ではなく"いかに書かないか"が重要
  • 難しいことをいかに簡単にやれるか

わかりやすいコード

  • 可読性が高いコードはわかりやすく、保守性が高い
  • 他のプログラマーに明確な意図を伝えるのが、わかりやすいコードを書く目的
  • わかりやすいコードを書くコツは、「複雑なコードの問題を小さく分割しながら、わかりやすい名前を付けて整理する」

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

  • 1つの意味を表すコードであれば、たとえ1行でも関数化する
  • 条件が連なるなら、早期returnを活用する
  • ループの中では一つの事だけを行う
  • 不正な状態は、assert(表明)を使って表現する
  • 関数を2種類に分類する(計算などを実行し実作業する関数/実作業する関数を複数組み合わて大きな仕事をする関数)
  • 小さな関数の必要性(コードの最小単位を関数とする) *1
    • 細かく関数化すると自己説明的なコードになる、テストがしやすい
    • 小さい方がコンパイラの最適化の恩恵を受けやすい
  • 関数名からクラスの候補を見つける
  • 継承よりも委譲
  • ユーザ定義形(typedef)を使って適切な名前を与える

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

  • クラスを利用する側から考えると、どのようなメンバ変数があってなどは知る必要はない > 適切に動作することが保証されているならブラックボックスのまま利用できる方が望ましい
  • オブジェクトの内部の状態を保護し、実装の詳細を隠す
  • DIP(依存性逆転の原則)を使用し、具象ではなく抽象に依存する
  • 呼び出す側は命じるだけ*2
  • 複雑なswitch文が出てきたらStrategyパターンで解決できないかを考えること
  • データ構造とアルゴリズムはオブジェクトを動作させるための手段でしかない
    • 利用者はクラスがどんな役割を持っていて、どのような責任を果たすのかが重要
  • クラス間の結合度を下げる
    • 仲介者(Mediator)を使って依存関係を単純にする
    • 窓口(Facade)を使って外部とのやり取りを隠蔽、単純化する
  • 複雑なオブジェクト生成はFactoryで行う
  • 利用者が楽できるように担当クラスに責任を完全に委譲する
  • 実装手段からボトムアップで考えるより、クラス利用者視点からトップダウンで考えた方が抽象度が上がる
  • 実装手段の交換ができるようにinterfaceを使ってプログラムを組み立てる(Strategy)
  • 問題領域は特定の環境に依存しないように設計する/実装領域は動作環境に依存する
    • 問題/実装領域を分離しておけば実装領域を交換することで他の環境にも移植可能
    • 問題領域を中心に設計すること

See also

*1:小さな関数もコンパイラによってインライン展開 されれば、パフォーマンスのオーバーヘッドはそこまで意識しなくてもよい

*2:そのクラスが管理するデータについてはそのクラスが妥当性のチェックも行う => 利用側からはそのクラスの値についてのチェック(Ask)はしない