コマンドクエリ分離の原則とは
メソッドでコマンド(副作用)とクエリ(主作用)を分離することが大事という原則です。
値を変えない作用が主作用で値を変える作用が副作用みたいな認識で大丈夫です。
- クエリ(主作用)…値を取得する操作
- コマンド(副作用)…値を変更する操作
以下のように例を見てみましょうー
コマンドの例(値を変更する)
public class CommandExample {
public static int increaseNumber(int number) {
this.number = this.number+1;
return this;
}
}
クエリの例(値を取得する等)
public class QueryExample {
public int getNumber() {
return this.number;
}
}
コマンドとクエリが分離していない場合の例
public class CommandExample {
public static int getNumber(int number) {
//クエリ
this.number = this.number+1;
//コマンド
return this.number;
}
}
コマンドとクエリが分離されている場合の例
public class CommandExample {
//クエリ
public static int increaseNumber(int number) {
this.number = this.number+1;
return this;
}
//コマンド
public int getNumber() {
return this.number;
}
}
コマンドとクエリが分離されていないと?
メソッドの責務が複数になり、理解容易性を下げて意図しない不具合を生み出す可能性があります。
例えば、getIdというメソッド名を見たときにエンジニアの皆さんは
Idを取得するメソッドだと考えると思います。
ただそのgetId()にIdを取得する際にidの値を+1するなどのクエリが入っていたとしたら、、
(コマンドとクエリが混在している状態)
getIdの期待値と異なるものが返ってしまい予期しない不具合が発生します。
そのため、コマンドとクエリは分離して定義してあげる必要があります。
(クエリはvoidかその値ではなくてObjectを渡すのが良さげですね)
まとめ
コマンドクエリ分離の原則とは主作用と副作用を分離して定義する原則です。
分離しないことで、メソッドに複数の責任が定義されてしまい、理解容易性を下げます。
また意図しない不具合を生み出す可能性があります。
そのため以下のアクションが必要になります。
- メソッド名を単一にする
- 主作用と副作用を分ける