コマンドクエリ分離

2005年12月5日

「コマンドクエリ分離」という用語は、バートランド・メイヤーによって著書「オブジェクト指向ソフトウェアの構築」の中で作られました。この本は、オブジェクト指向誕生初期に最も影響を与えたオブジェクト指向関連の書籍の1冊です。(第1版が影響力を持っていましたが、第2版は優れていますが、持ち上げるには数か月ジムに行く必要があります。)

この原則の基本的な考え方は、オブジェクトのメソッドを2つの明確に分離されたカテゴリに分割する必要があるということです。

  • クエリ: 結果を返し、システムの観測可能な状態を変更しません(副作用がありません)。
  • コマンド: システムの状態を変更しますが、値を返しません。

「コマンド」という用語は他のコンテキストで広く使用されているため、「修飾子」と呼ぶことを好みます。また、「ミューテーター」という用語もあります。

この原則の中で本当に価値のある考え方は、状態を変更するメソッドとしないメソッドを明確に分離できると非常に便利なことです。これは、多くの状況でより多くの自信を持ってクエリを使用し、任意の場所に導入したり、順序を変更したりできるためです。修飾子には注意する必要があります。

この原則における考え方は、戻り型が違いを示すということです。ほとんどの場合にうまく機能するため、優れた規約です。コレクションを反復処理するためのJavaの慣用句を考えてみてください: nextメソッドは、コレクション内の次のアイテムを返し、イテレーターを進めます。個人的には、独立したadvanceメソッドとcurrentメソッドを持つスタイルの方がはるかに気に入っています。

メイヤーはコマンドクエリ分離を絶対的に使用したりますが、例外があります。スタックをポップすることは、状態を変更するクエリの好例です。メイヤーは、このメソッドを使用しないようにする場合があると正しく述べていますが、便利な慣用句です。そのため、できる限りこの原則に従うことを好みますが、ポップするためには破る覚悟があります。

言語自体がこの概念をサポートしてくれるとよいでしょう。私は状態変更メソッドの検出、または少なくともプログラマーがそれらをマークできるようにする言語を想像できました。言語がそれらを自動的に検出できない理由の1つは、状態を変更しないというルールは、実際にはシステムの観測可能な状態にのみ適用されることです。プログラマーのマーキングを使用することはより理にかなっているようですが、稀です。私が実際に遭遇した唯一のケースは、C++でのconst修飾子です。私は何年もC++を使用していないので、実際にはどれほど便利かを評価するのは難しいです。優れたC++プログラマーはconstを多用し、気に入っていると思います。