命令查询分隔冲突

问题描述

| 你有什么想法
 if(!DoSomething()) return;
在“干净代码”中,这被视为违反了命令查询分隔。 但是,我们如何才能理解DoSomething()命令中的某些内容是否出错? sql命令怎么样(例如:void Delete(Table))?我们如何知道该表是否存在? 谢谢。     

解决方法

我同意rObiwahn的评论,在发出
DoSomething
命令之前,应先检查
CanDoSomething
。在纯CQRS环境中,
DoSomething
不会返回任何内容,并且如果有什么阻止某事发生(不是由于异常,而是竞争条件或
CanDoSomething
DoSomething
之间的其他变化),则您的域将发出
DoSomethingWasInvalid
事件(或类似事件)那),这将最终使您的应用程序变得一致。 听起来可能很复杂,但是一旦您开始将逻辑分解成小块并允许您的应用程序包含最终的一致性,它实际上就变得非常简单。 Google网上论坛的DDD / CQRS网上论坛有很多不错的资源。诸如“如何告诉发送方命令失败?”之类的问题与您的问题有点类似。像Udi Dahan,Greg Young,Rinat Abdullin等人监视该小组并提供一些非常好的答案。我也建议您不时检查一下。 希望这可以帮助!     ,如果出了什么问题,
DoSomething()
可能会抛出异常,如果您作为调用者必须处理该异常。 例如。:
try  
{  
  DoSomething();  
  // .. do more after success  
}  
catch(SomeException ex) // maybe focus on a special error
{
  // maybe do something special or just clean up!  
}  
    ,我将在Eiffel中编写此示例,以使其易于理解。
my_code
      -- Calls the `do_something\' routine
   do
      set_table (\"my_table\")
      do_something
   end

do_something
      -- Something to do
   require
      valid_table: is_valid_table (table_name)
   do
      sql_list := execute_sql_on_table (table_name)
   ensure
      has_result: sql_list.count > 0
   end

sql_list: ARRAYED_LIST [STUFF]

table_name: STRING

set_table (a_name: STRING)
       -- Set `table_name\' to `a_name\'
   require
      has_name: not a_name.is_empty
      valid_table: is_valid_table (a_name)
   do
      table_name := a_name
   ensure
      table_name_set: table_name.same_string (a_name)
   end

delete_table (a_name: STRING)
      -- Delete `a_name\' from the database.
   require
       valid_table: is_valid_table (a_name)
   do
      execute_sql (\"DROP TABLE \" + a_name)
   ensure
       table_gone: not is_valid_table (a_name)
   end
功能“ do_something \”是一个命令,其中将从表“ my_table \”中的STUFF加载数组sql_list。 前提条件合同在ѭ10my_code\上提供
table_name\' before making the call to
do_something\。 作为回报,后置条件确保合同使其具有STUFF实例的供应商
do_something\' fill the array
sql_list\的责任。 功能“ sql_list \”是一个查询,返回指向STUFF数组的引用指针。 同样,功能“13ѭset_table\”。 在这种情况下,按合同设计的“合同”负责确保适当分离关注点以及由谁负责上面这小部分代码中的内容。请注意,代码中明显缺少TRY-CATCH构造。在这种情况下,数据源应具有\“ my_table \”。合同的存在意味着合同失败时软件将引发异常。需求失败表示呼叫者已损坏,而确保后置条件的失败则指向供应商功能。 最后,该代码展示了清晰的命令-查询-分隔和从按合同设计获得的质量保证的应用。因此,可以回答原始问题: \“但是,我们如何才能理解DoSomething()命令中的某些内容出了错?关于sql命令(例如:void Delete(Table))呢?我们如何知道该表是否存在?” 虽然确实可以将对delete_table(\“ my_table \”)的调用注入到某个祖先,或者可能在另一个线程上发生,但这是
do_something\'. As long as those contracts stand guard over calls to
do_something\'中合同的含义,但将适当地处理该过程。注入对“ delete_table \”的调用只会导致合同失败。 所有这些都是假定在\“ my_table \”上拖放表是不正确的,并且这样做是不幸的。但是,如果可以在\“ my_table \”上拖放表就可以了,则需要重试机制或其他\“ handler \”来管理此用例,并且上面的代码将不起作用。     ,我现在真的想到了这件事,[为什么我们不考虑“分离的担忧”而不是“关注的分离”!]我知道这是不合主题的,但是对标准的过多推动将导致没有任何地方。从人类历史中可以很容易地看出随着时间的流逝,有多少实践/标准被证明是错误的!这全都是您对卓越的看法。 因此,在这种情况下,我总是想着相反的想法保持真实。我想说更多,但从我的回答角度来看,这已经足够;) 祝好运!