A Day In The Life

とあるプログラマの備忘録

質問をすることで答えは変更されない原則

メイヤー著「オブジェクト指向入門 第2版 方法論・実践」でクラス設計の面白い原則があったのでまとめてみました。

前提

クラスの特性にはクエリとコマンドがある。

  • クエリ
    • 属性
    • ファンクション(戻り値のあるメソッド)
  • コマンド

ファンクションに副作用があってはならない

ファンクションの副作用とはファンクション呼び出しによって属性の値が変更されること。
たとえばNumberというクラスがあって
Numberクラスにvalue属性とmultiplyメソッドが定義されている場合
multiplyメソッドを呼ぶとvalue属性の値が変わる場合、副作用があるという。
ファンクションに副作用があると

  • 数学におけるファンクションと意味が違う
  • 参照透過性が消失する

という問題が発生する。このことからファンクション設計時には以下の行為は避けるべきである。

プロシージャでは積極的にオブジェクトの内容を変更せよ

ファンクションに副作用があってはならないが、逆にプロシージャでは積極的にオブジェクトの内容を変更するべきである。むしろ副作用のないプロシージャに意味はない。

ファンクションに副作用があっても良い場合

以下の場合は例外的に副作用を認める

  • ファンクション内で一時的にオブジェクトを変更するがファンクション終了時に状態が元に戻る場合
  • ファンクション内で外部に公開されていない属性(プライベート属性)を変更するとき。ただしゲッターのあるプライベート属性はもちろん例外に含まれない
  • インスタンスを生成して返すだけのメソッド

まとめ

この原則に本気で従うとかなりしんどいような気がしますが、クラス設計で迷った時の一つの指針になると思います。Rubyでは副作用のあるファンクションのことを破壊メソッドと呼びメソッド名の前に「!」をつけるのが習慣になっています。JavaやC♯なんかでプログラムするときはほとんど意識することがなかったので今後気をつけたいと思います。