唯一无法回退的是时间

当前请求到底是Command还是Query由当前请求的响应者决定。前端控制器收到一条消息比如记为message1,这个请求内容为message1的请求可能经过一个相当复杂的处理管道,管道还会分叉,每个分叉中的消息可能和原始的message1有所不同,新的分叉中的消息比如记为message1.1吧,message1.1是由message和一些系统状态组合出的新的message对象,这个message1.1继续往下走,有可能还有message1.1.1, message1.1.2,message1.1.3……,message被这么有组织有偏移的分类后就尽是些非常具体的message了,这些具体的message就可以用具体的逻辑处理了。问题的关键是在这个“message+系统”的联合运动过程中每一次对message的分类都不能损失信息(最初的那个message包含了所有信息,这个大message进入我们的系统,配合上我们的系统的状态来分解message,这个分解是按照我们事先书写好的程序逻辑进行的,我们这些程序员天天写程序的本质就是对事物按照人类使用了几万年的古老分类法进行分类,反正这个问题我表述不清,反正就是事物的运动不会损失信息,反正就是message如果要持久化的话这个持久化不应损失任何信息,持久化模型可能跟message dto模型是不同结构的,但配合上我们的系统状态后每一条message的持久化一定不会损失信息)。还有一个问题是在这个“message在系统中的运动”这个过程中我们还会对message从另一个角度进行分类,这另一个角度是当前的message是否已经被“handled”,message1被MessageHandler1 handled后记为message1',message1'的结构跟message1有可能是不同的,message1'称作MessageHandler1输出的event,而这条MessageHandler1输出的message1'可能又会被送入MessageHandler2处理,message1'对于MessageHandler1来说是输出是event,但对于MessageHandler2来说却是Command。至此我们将所有的message按照输入输出的角度可以分作两类:输入的是Command,输出的是Event。虽然这条message可能在我们的服务端经过一条极其复杂的带有分叉的处理管道,但若是这条message的处理被要求是事务性的就难办了,如果失败了我们如何把这条message从那套极其复杂的管道中退回来?退回来是很难的,但是一定是能够办到的,因为我们的message在任何一个处理环节都没有损失信息(唯一损失的是时间)既然没有损失任何信息当然是可以原路返回的,原路返回的时候别忘了把系统状态返回过来,系统要回到收到包含这条message的请求之前的状态。我们的系统绝不可能回到收到这条message之前的状态!因为时间是无法后退的,所以这是为什么我们经常听到“最终一致性”这个词。

可以导致系统的状态变更的就是Command,是Command就要有办法控制(head、get、read、query等操作是否是有副作用的,是否会导致你的系统状态的变更在于你的业务边界是什么。资源每被get一次访问计数加了1,如果在你的业务边界下访问次数加1有意义的话状态就变更了,没意义就不用变更不用加1)。

所有的运动都应该是可以控制的。比如var age = 30;这么一条赋值语句,这个语句中有个动词“=”,它的意思是赋值,赋值是动词。赋值导致了系统状态的变更,所有的命令都应该是可控的,怎么控制?只需要用个using语句一包裹就可以控制了: using(var acCotnext = new ACContext(subject, resource,action)){ var age = 30; }
摘自:http://git.oschina.net/anycmd/anycmd