Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# fluent接口是否违反了命令-查询分离原则?_C#_Fluent Interface_Command Query Separation - Fatal编程技术网

C# fluent接口是否违反了命令-查询分离原则?

C# fluent接口是否违反了命令-查询分离原则?,c#,fluent-interface,command-query-separation,C#,Fluent Interface,Command Query Separation,我开始写一个流畅的界面,看了一看Martin Fowler写的一篇关于流畅界面的老文章(我没有意识到他和Eric Evans创造了这个术语)。在这篇文章中,Martin提到setter通常返回正在配置或处理的对象的实例,他说这违反了CQS 花括号世界中的常见约定是修改器 方法是无效的,我喜欢它,因为它遵循 命令分离。这项公约确实妨碍了一项新的法律 流畅的界面,所以我倾向于为此暂停惯例 案例 因此,如果我的fluent界面执行以下操作: myObject .useRepository("Stu

我开始写一个流畅的界面,看了一看Martin Fowler写的一篇关于流畅界面的老文章(我没有意识到他和Eric Evans创造了这个术语)。在这篇文章中,Martin提到setter通常返回正在配置或处理的对象的实例,他说这违反了CQS

花括号世界中的常见约定是修改器 方法是无效的,我喜欢它,因为它遵循 命令分离。这项公约确实妨碍了一项新的法律 流畅的界面,所以我倾向于为此暂停惯例 案例

因此,如果我的fluent界面执行以下操作:

myObject
  .useRepository("Stuff")
  .withTransactionSupport()
    .retries(3)
  .logWarnings()
  .logErrors();
这真的违反了CQS吗


更新我将我的示例显示为日志警告和错误作为单独的行为。

是的,它是。所有这些方法显然都返回了一些东西,同样明显的是它们都有副作用(从你没有对返回值做任何事情的事实判断,但是你确实费心去调用它们)。由于CQS的定义规定,突变子不应返回值,因此我们手中有一个明确的违规行为


但是违反CQS对你来说重要吗?如果FLUENT接口使你更能考虑所有的事情,如果你认为它是一个众所周知的模式,它同样具有众所周知的优点和缺点,那么它为什么违反了纸上的原理X?

< P>当它改变对象时,它违背了这个原理,而当它只返回一个新对象时,它就违反了这个原则。
var newObject = myObject
    .useRepository("Stuff")
    .withTransactionSupport()
    .retries(3)
    .logWarningsAndErrors(); 
如果在该语句之后,
myObject
保持不变,则一切正常。一般来说,流畅的界面违反了CQS原则,如果且仅当它有副作用时

然而,问题是,如果您的示例确实表示一个查询。“流利”是否一定意味着“查询”?它可能仅仅被视为一个动作流畅的界面,其中相同的对象从一个动作传递到下一个动作。

否。这里的模式是“配置”。此类配置命令返回的配置对象本身与与命令无关的内容相反。如果用于配置目的的命令返回一些不相关的数据,则会违反命令/查询分离,例如:

if (myObject.UseRepository("Stuff") > 1 && myObject.UseRepository("Bla") < 5) {
    // oh, good, some invisible stuff internal to myObject is in right interval...
}
if(myObject.UseRepository(“Stuff”)>1&&myObject.UseRepository(“Bla”)<5){
//哦,很好,myObject内部的一些看不见的东西处于正确的间隔。。。
}

我认为这取决于这些方法在做什么。如果每一个都是它自己的命令,那么是的,它可能会破坏CQS

但是,您可以通过两种不同的方式轻松解决此问题

  • 只是不要把命令串起来。只需执行myObject.useRepository(“…”)。然后打电话给下一个,等等。但是如果链中的下一个项目需要上一个项目的信息,那么您将遇到麻烦

  • 相反,这些链接的东西只是直接更新DTO上的数据,而不是使它们各自成为自己的命令。最后,运行名为.Configure()的方法,然后将此DTO发送到执行所有处理的单个命令


  • 嗯,但是配置的重点是更改对象(根据配置),所以为什么要麻烦呢?如果要修改的对象是新实例还是旧实例,会有什么区别?这4个调用中的任何一个要么修改表达式的返回值(不管是什么),要么什么也不做,因此应该忽略。问题是,如果它确实修改了现有对象并同时返回结果,那么它将同时成为命令和查询。它应该是一个命令或一个查询。
    logWarningsAndErrors
    返回什么东西是多么明显?@M.Babcock:从技术上讲,它不是,只是来自那个片段。你把我带到那里了,我同意。如果它违反了原则X,如果它有助于您使用它,那又有什么关系呢?如果不是,那么它真的是一个流畅的界面吗?@M.Babcock更新了我的示例。当然,
    logWarningsAndErrors
    返回一个我可以添加其他行为的界面。sry,我不明白你的答案,但我想知道。你能把它展开吗?“如果你有……”在哪里?此外,代码段中的内部状态没有改变。我看到违反了“说,不要问”的原则,但仅此而已