7

私は流暢なインターフェースを書き始め、マーティン・ファウラーが流暢なインターフェースについて書いた古い作品を見てみました(彼とエリック・エバンスがこの用語を作り出したことに気づいていませんでした)。作品の中で、マーティンは、セッターは通常、構成または作業中のオブジェクトのインスタンスを返すと述べています。これは、CQSの違反であると彼は言います。

中括弧の世界での一般的な規則は、修飾子メソッドが無効であるということです。これは、CommandQuerySeparationの原則に従っているためです。この規則は流暢なインターフェースの邪魔になるので、この場合は規則を一時停止する傾向があります。

したがって、私の流暢なインターフェースが次のようなことをする場合:

myObject
  .useRepository("Stuff")
  .withTransactionSupport()
    .retries(3)
  .logWarnings()
  .logErrors();

これは本当にCQSの違反ですか?

更新ログの警告とエラーを別々の動作として表示するために、サンプルを分割しました。

4

4 に答える 4

9

はい、そうです。これらのメソッドはすべて明らかに何かを返していますが、同様に明らかに副作用があります (戻り値で何もしないという事実から判断すると、わざわざそれらを呼び出す必要があります)。CQS の定義では、ミューテーターが値を返すべきではないと述べているため、明確な違反が発生します。

しかし、CQS に違反していることはあなたにとって重要ですか? 流暢なインターフェースが考慮すべきすべてのことの生産性を向上させ、それが利点と欠点が同じようによく知られているよく知られたパターンであると考えるなら、それが理論上の原則 X に違反していることがなぜ問題になるのでしょうか?

于 2012-03-16T18:06:56.787 に答える
3

オブジェクトを変更するときはこの原則に違反しますが、新しいオブジェクトを返すだけの場合は違反しません。

var newObject = myObject
    .useRepository("Stuff")
    .withTransactionSupport()
    .retries(3)
    .logWarningsAndErrors(); 

myObjectこのステートメントの後に が変更されていなければ、すべて問題ありません。一般的に言えば、流暢なインターフェースは、副作用がある場合に限り、CQS の原則に違反します。

ただし、問題は、例がクエリをまったく表しているかどうかです。「流暢」は必ずしも「クエリ」を意味しますか? おそらく、同じオブジェクトが 1 つのアクションから次のアクションに渡される、アクションに流暢なインターフェースとして認識される可能性があります。

于 2012-03-16T18:07:27.380 に答える
0

いいえ。ここでのパターンは「構成」です。このような構成コマンドは、コマンドに関係のないものとは対照的に、構成オブジェクト自体を返します。コマンド/クエリ分離の違反は、構成の目的を果たすコマンドが無関係なデータを返した場合に発生します。たとえば、次のようになります。

if (myObject.UseRepository("Stuff") > 1 && myObject.UseRepository("Bla") < 5) {
    // oh, good, some invisible stuff internal to myObject is in right interval...
}
于 2012-03-16T18:08:00.750 に答える
0

それらの方法が何をしているかに依存すると思います。それぞれが独自のコマンドである場合、はい、CQS を壊している可能性があります。

ただし、これは 2 つの異なる方法で簡単に修正できます。

  1. コマンドをチェーンしないでください。myObject.useRepository("..") を実行するだけです。次に、次のものを呼び出します。しかし、チェーン内の次のアイテムが前のものからの情報を必要とする場合、問題が発生します。

  2. これらのそれぞれを独自のコマンドにする代わりに、これらのチェーン化されたものは、DTO のデータを直接更新するだけです。最後に、.Configure() というメソッドを実行します。このメソッドは、この DTO をすべての処理を行う単一のコマンドに送信します。

于 2020-05-18T18:42:08.480 に答える