命令查询分隔违规

时间:2011-04-14 12:59:39

标签: c# coding-style separation-of-concerns command-query-separation

您如何看待

 if(!DoSomething()) return;

在“清洁代码”中,这被视为违反命令查询分离。 但是,我们怎么能理解命令DoSomething()出错了? 那么sql命令(例如:void Delete(Table))?我们如何知道该表是否存在?

感谢。

4 个答案:

答案 0 :(得分:1)

如果出现问题,DoSomething()可能会抛出异常,如果您打电话者必须处理它。
例如:

try  
{  
  DoSomething();  
  // .. do more after success  
}  
catch(SomeException ex) // maybe focus on a special error
{
  // maybe do something special or just clean up!  
}  

答案 1 :(得分:1)

我同意rObiwahn的意见,即在发出CanDoSomething命令之前,您应该检查DoSomething。在纯CQRS环境中,DoSomething不会返回任何内容,如果有任何事情阻止发生某事(不是由于异常,而是竞争条件或其他在CanDoSomethingDoSomething之间发生变化的情况) ,您的域名会发出DoSomethingWasInvalid事件(或类似内容),这样可以使您的申请最终保持一致。

这可能听起来很复杂,但是一旦你开始将逻辑分解成小块并允许你的应用程序拥抱最终的一致性,它真的变得非常简单。

Google群组中的DDD / CQRS群体有很多优质资源。像“How do you tell the sender that a command failed?”这样的问题与您的问题类似。像Udi Dahan,Greg Young,Rinat Abdullin和其他人一样监视这个群体并提供一些非常好的答案。我建议不时地检查一下。

希望这有帮助!

答案 2 :(得分:1)

我将在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
  1. 功能`do_something'是一个命令,其中数组sql_list将从表“my_table”加载STUFF。
  2. do_something' makes it the responsibility of the client my_code'上的前提条件合同,以提供table_name' before making the call to do_something'。
  3. 作为回报,后置条件确保合同使供应商do_something' fill the array sql_list'负责STUFF实例。
  4. 功能`sql_list'是一个查询,返回一个指向STUFF数组的引用指针。
  5. 同样,功能table_name' is a query returning a reference pointer to a STRING, which is set with a "setter" command called set_table'。
  6. 在这种情况下,“合同设计”的“合同”负责确保关注点的适当分离,以及谁负责上述这些小代码中的内容。请注意代码中缺少TRY-CATCH结构。在这种情况下,数据源应具有“my_table”。合同的存在意味着软件将在合同失败时提出异常。需求失败表示调用者已损坏,而确保后置条件失败则指向供应商功能。

    最后,该代码展示了明确的命令 - 查询 - 分离以及从契约设计中获得的质量保证的应用。因此,原始问题可以回答:

    “但是我们怎么能理解命令DoSomething()出错了?sql命令怎么样(例如:void删除(表))?我们如何知道该表是否存在?”

    虽然对delete_table(“my_table”)的调用可能会被注入某个祖先或者可能发生在另一个线程上,但这是do_something'. As long as those contracts stand guard over calls to do_something'中的契约所针对的过程,妥善处理。注入“delete_table”只会导致合同失败。

    所有这一切都假设“my_table”上的DROP TABLE不合适,并且这样做是偶然的。但是,如果“my_table”上的DROP TABLE变得可以,则需要重试机制或其他“处理程序”来管理此用例,并且上述代码将不起作用。

答案 3 :(得分:0)

我现在真的想到了这件事,[为什么我们不会想到“分离的担忧”而不是“关注点分离”!]我知道它的主题,但是对标准的过分推动会导致没有。从人类历史来看,很容易看出有多少实践/标准被证明是错误的!这完全取决于你对卓越的看法。

所以在这种情况下我总是试着想到相反的东西保持真实。我想说更多但我认为从我的回答角度来看已经足够了;)

祝你好运!