コマンドクエリ分離(コマンドクエリぶんり、)は命令型プログラミングにおける原則。Eiffel言語における先駆的な仕事の一環としてバートランド・メイヤーによって考案された。

この原則は、全てのメソッドはアクションを実行する「コマンド」か、呼び出し元にデータを返す「クエリ」のどちらかであるべきで、その両方を行ってはならないということを述べている。これは「質問をすることが答えを変えてはならない」とも表現される。

形式的には、メソッドは参照透過性を持ちかつ、副作用を持たない場合のみ値を返すべきだと表現される。

契約プログラミングとのつながり コマンドクエリ分離は、契約プログラミング(DbC)の手法によく適している。DbCでは、プログラムの設計はソースコードに埋め込まれた表明(アサーション)によって表現され、特定の時点においてのプログラムの状態を記述する。

DbCにおいて、表明はプログラムロジックでなく、設計のアノテーションと見做されるため、その実行はプログラムの状態に影響を与えてはならない。CQSでは値を返すあらゆるメソッド(=クエリ)はプログラムの状態を変更する心配なくどの表明からも呼び出すことができるため、DbCにとって有益であるとされる。

理論的には、健全性の尺度を確立するものであり、これによりプログラムの状態を変更することなくその状態について推測することができる。実際の利用においては、CQSは動作中のシステムにおける全ての表明チェックを、システムの振る舞いを意図せずして変更することを防ぎながら、パフォーマンス向上のためにスキップすることを可能にする。CQSはまた、特定の種類のハイゼンバグの発生を防ぐこともある。

契約プログラミングとのつながりを超えて、CQSはその信奉者によって、プログラムをシンプルにする効果があり、クエリを通じてプログラムの状態を、コマンドを通じて状態の変更をさらにわかりやすくすることができると考えられている。

コマンドクエリ責任分離 コマンドクエリ責任分離 (CQRS) はCQSの概念をサービスのアーキテクチャのレベルにまで拡張したものであり、「クエリ」と「コマンド」でそれぞれ異なるインターフェースとデータモデルを用意し、データ取得にはクエリを、データ変更にはコマンドを用いるという形でCQS原則を適用している。

制約 CQSでは再入可能性やマルチスレッドを正しく実装する場合に複雑になる場合がある。これは通常、コマンドクエリ分離を実装する際にスレッドセーフでないパターンが用いられている時に発生する。 以下はCQSに従っていない簡単な例である。この関数は状態を変更し、かつ値を返しているため、CQSには従っていない。マルチスレッドソフトウェアにおいては、このような関数を用意することでプログラムの他のすべての部分での排他制御の問題を解決することができる。private int x; public int incrementAndReturnX() { lock x; // by some mechanism x = x + 1; int x_copy = x; unlock x; // by some mechanism return x_copy; }以下はCQS完全な例である。注意すべきは、これはシングルスレッドなアプリケーションでのみ安全に利用できるということである。マルチスレッドなプログラムにおいては、呼び出し元において increment() と value() が呼び出される間に競合状態が発生する。private int x; public int value() { return x; } void increment() { x = x + 1; }シングルスレッドのプログラムにおいても、クエリとコマンドが一体化したメソッドが非常に便利である場合がある。マーティン・ファウラーはその例として、スタックに対する pop() メソッドを挙げている。

関連項目

冪等 ドメイン駆動設計 Create, read, update and delete (CRUD)

脚注

参考文献

外部リンク

Explanation on Martin Fowler's Bliki