在维基百科的命令查询分离定义中,有人说
更正式地说,方法只有在它们是引用透明的情况下才能返回值,因此没有副作用.
如果我发出命令,我该如何确定或报告该命令是否成功,因为通过此定义,该函数无法返回数据?
例如:
string result = _storeService.PurchaseItem(buyer, item);
Run Code Online (Sandbox Code Playgroud)
此调用中包含命令和查询,但查询部分是命令的结果.我想我可以使用命令模式重构这个,如下所示:
PurchaseOrder order = CreateNewOrder(buyer, item);
_storeService.PerformPurchase(order);
string result = order.Result;
Run Code Online (Sandbox Code Playgroud)
但这似乎增加了代码的大小和复杂性,这对于重构来说并不是一个非常积极的方向.
当您需要操作结果时,有人能给我一个更好的方法来实现命令查询分离吗?
我在这里错过了什么吗?
谢谢!
注意:Martin Fowler对此有关cqs CommandQuerySeparation的限制:
Meyer绝对喜欢使用命令查询分离,但也有例外.弹出堆栈是修改状态的修饰符的一个很好的例子.梅耶正确地说你可以避免使用这种方法,但这是一个有用的习惯用法.所以我喜欢在我可以的时候遵循这个原则,但我准备打破它以获得我的流行音乐.
从他的观点来看,重构命令/查询分离几乎总是值得的,除了一些小的简单例外.
我正在学习什么是CQRS模式,并且开始知道还有CQS模式
当我试图搜索时,我发现了很多图表,关于CQRS的信息但是没有发现很多关于CQS的信息
CQRS模式的关键点
在cqrs中,有一个要编写的模型(命令模型)和一个要读取的模型(查询模型),它们是完全独立的.
CQS如何与CQRS区分开来..?
两者都有区别的关键点是什么..?
任何援助将不胜感激 :)
编辑:修复了几个语法和一致性问题,使代码更加明显,接近我实际做的事情.
我有一些看起来像这样的代码:
SomeClass someClass;
var finalResult =
DoSomething(() =>
{
var result = SomeThingHappensHere();
someClass = result.Data;
return result;
})
.DoSomething(() => return SomeOtherThingHappensHere(someClass))
.DoSomething(() => return AndYetAnotherThing())
.DoSomething(() => return AndOneMoreThing(someClass))
.Result;
HandleTheFinalResultHere(finalResult);
Run Code Online (Sandbox Code Playgroud)
其中DoSomething方法是扩展方法,并且它期望传递给它的Func.因此,每个DoSomething => lambda中的每个方法调用都返回一个Result类型.
这类似于一个可能的monad.除了检查空值,我检查Result类的状态,并调用传递给DoSomething的Func或返回前一个Result而不调用Func
我面临的问题是希望在我的代码中使用这种组合,但我还需要能够将一个组合调用结果中的数据传递给另一个调用结果,正如您可以看到的那样someClass.
我的问题不是这在技术上是否正确......我知道这是有效的,因为我现在正在这样做.我的问题是这是否是滥用闭包,命令查询分离或任何其他原则......然后询问有什么更好的模式来处理这种情况,因为我很确定我是现在,这种类型的代码陷入了"闪亮的新锤子"模式.
c# closures anti-patterns principles command-query-separation
如果CQS阻止命令返回状态变量,那么命令的一个代码怎么可能不成功?假设你不能依赖例外.
似乎任何请求/响应都违反了CQS.
所以看起来你会有一套"母亲可能我"的方法给出了命令返回的状态.多线程/多计算机应用程序中会发生什么?
如果我有三个客户端要求服务器的对象增加一个(并且对象的限制为0-100).所有人都检查它们是否可以但是一个人得到它 - 而另外两个不能,因为它只是达到了极限.这似乎是返回状态可以解决这里的问题.
如果您的问题作为此问题的重复项而被关闭,那是因为您有一些通用形式的代码
x = X()
# later...
x = x.y()
# or:
x.y().z()
Run Code Online (Sandbox Code Playgroud)
其中X是某种类型,它提供了y旨在z变异(修改)对象(X类型的实例)的方法。这可以适用于:
list、dict和setbytearray这种形式的代码很常见,但并不总是错误的。问题的明显迹象是:
与x.y().z()一样,会引发异常AttributeError: 'NoneType' object has no attribute 'z'。
有了x = x.y(),x就变成None, 而不是被修改的对象。这可能会被后来的错误结果发现,或者被像上面这样的异常(x.z()稍后尝试时)发现。
Stack Overflow 上有大量关于这个问题的现有问题,所有这些问题实际上都是同一个问题。之前甚至有多次尝试在特定上下文中涵盖同一问题的规范。然而,理解问题并不需要上下文,因此这里尝试一般性地回答:
代码有什么问题吗?为什么这些方法会这样,我们如何解决这个问题?
另请注意,当尝试使用 alambda(或列表理解)来产生副作用时,会出现类似的问题。
同样明显的问题可能是由因其他原因返回的方法引起的None …
对于可以返回修改对象或仅修改实例的函数,Python中的命名约定是什么.
我们假设您要实现两者,如何命名函数?
示例:假设您需要crop()Image对象的函数.我Ruby很简单,因为你应该使用crop()如果你返回一个副本并crop!()修改原始实例.
我开始编写一个流畅的界面,看看Martin Fowler在流畅的界面上写的一篇较旧的文章(我没有意识到他和Eric Evans创造了这个术语).在这篇文章中,Martin提到setter通常会返回正在配置或处理的对象的实例,他说这违反了CQS.
大括号世界中的常见惯例是修饰符方法是void,我喜欢它,因为它遵循CommandQuerySeparation的原则.这个约定确实妨碍了一个流畅的接口,所以我倾向于暂停这个案例的约定.
所以,如果我的流畅界面做了类似的事情:
myObject
.useRepository("Stuff")
.withTransactionSupport()
.retries(3)
.logWarnings()
.logErrors();
Run Code Online (Sandbox Code Playgroud)
这真的违反了CQS吗?
更新我打破了我的示例,将日志警告和错误显示为单独的行为.
我喜欢Command Query Separation的想法,但是无法看到如何在添加实体的MVC Controller操作中使用它,并且在添加实体后需要新实体的ID.
例如,在下面的简化示例中,服务用于创建新项目:
public ActionResult Assign(AssignViewModel viewModel)
{
var newItem = _AssignItemService.AssignItem(viewModel.ItemName, viewModel.ItemValue);
return RedirectToAction("ListItem", new {id = newItem.Id);
}
Run Code Online (Sandbox Code Playgroud)
但是当我重定向到要显示新项目的操作时,我需要知道新创建的项目的ID,以便可以从数据库中检索它.所以我必须要求服务返回新创建的项目(或至少,它的ID).
在纯CQS中,命令没有返回值,因此上面的模式将是无效的.
任何建议都感激不尽.
那么,如果我写一个异步命令,那是否会不可避免地违反CQS原则?
给定一个真实的匿名购物车,"AddToCart"工作流程必须执行以下步骤:
因此,虽然"AddToCart"听起来应该是一个命令(因为它更新了系统状态),但实际上它依赖于许多查询.
处理这样的工作流程的普遍接受的方法是什么?
AddToCartCommandHandler取决于可能运行查询的其他服务.CartService,用于协调运行查询的工作流,然后是命令.我之所以无法找到答案,是因为它"取决于设计",这是不适用的例外情况之一吗?
如果命令和查询是分开的,我是否会将我的真实实体框架实体类传递给添加/更新购物车的命令(因此EF可以确定它是否附加)?在这种情况下,似乎DTO不会这样做.
注意:我隐含地假设实现的系统这样
CQS做的目的是最终它们可以成为一个完整的CQRS系统.如果是这样,这个工作流程显然无法进行转换 - 因此我的问题.
我正在第一次尝试CQS.
从我阅读的有关此模式的文档中可以清楚地看出,查询不得更改系统状态.
但是,目前还不清楚是否可以从命令中运行查询(我似乎无法在任何地方找到任何信息).
我可以想到几个真实案例需要发生的事情.但是,鉴于在线缺乏这种模式的现实例子,我不确定如何继续.在线有很多理论,但我能找到的唯一代码就是这里和这里.
asp.net-mvc design-patterns entity-framework command-query-separation
c# ×5
asp.net-mvc ×2
python ×2
async-await ×1
closures ×1
cqrs ×1
ncqrs ×1
nonetype ×1
principles ×1