setter と getter

カプセル化カプセル化と考えていると、メンバ変数について無闇に取得させないほうが良いだろうかと
そんな風に思って setter は用意したのに getter を作らなかったりしていた時期がありました。
あるクラスのクライアントが何か値をセットするときにはその状態を把握できているはずなんだから
ゲットしなくても分かるでしょ。と考えたのですが、実際に自分がクライアントになってみるとやはり
getter が無いのは非常に使いにくいし、かえって不自然な状態になったりします。たとえば

// クラス Camera は行列計算し、Setup で描画コンテキストにこれを渡す
void Camera::Setup(GraphicsContext * gc) {
  gc->SetProj(projType, projMtx); // 射影行列
  gc->SetViewMtx(viewMtx);        // ワールドビュー行列
}
// クラス Billboard は常にカメラに正対するポリゴン
void Billboard::Draw(GraphicsContext * gc) {
  // 現在のワールドビュー行列の回転部分の逆行列を先に適用してから自分のローカルワールド行列を適用したい
  gc->SetModelMtx(modelMtx * InverseRot(gc->GetViewMtx())); // 行列の乗算は OpenGL と同じ方向
  // 描画コンテキストに頂点配列を渡して描画
  gc->Draw(vertexArray);
}

こんな風にしてビルボードを描画する場合に GraphicsContext から行列が取得できなかったら
別にどこかに「現在の行列」ってのを控えておく必要があります。それをどこにおくのか、
たとえば Camera に static Mtx GetCurrentViewMtx() なんてのを作るのか。それはなんだか
カメラの仕事じゃないし Camera 以外が GraphicsContext に行列をセットしたらどうすんの?
じゃあ Camera に static SetCurrentViewMtx(Mtx viewMtx) を用意して…と段々余計なメンバが
増えていきそうです。同じ情報(この場合現在のワールドビュー行列)を2箇所以上で管理する形にもなり
その不一致が元となりバグを生むことにもなります。


そんなわけで、 setter を付けたら getter も用意しておくのが良さそうだと思い至るのであります。