1

你有什么想法

 if(!DoSomething()) return;

在 Clean Code 中,这被视为违反命令查询分离。但是我们如何理解命令 DoSomething() 中的某些内容是否出错?sql 命令(例如:void Delete(Table))呢?我们如何知道该表是否存在?

谢谢。

4

4 回答 4

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!  
}  
于 2011-07-14T10:20:17.113 回答
1

我同意 rObiwahn 的评论,您应该CanDoSomething在发出DoSomething. 在纯 CQRS 环境中,DoSomething不会返回任何东西,并且如果有任何东西阻止了某事的发生(不是由于异常,而是由于竞争条件或其他在 and 之间发生变化的东西CanDoSomethingDoSomething,您的域将发出一个DoSomethingWasInvalid事件(或类似的东西),它将让您的应用程序最终变得一致。

这听起来可能很复杂,但是一旦您开始将逻辑分解为小块并允许您的应用程序实现最终一致性,它就会变得非常简单。

google 群里的 DDD/CQRS 群有很多不错的资源。诸如“您如何告诉发送者命令失败?' 有点类似于你的问题。像 Udi Dahan、Greg Young、Rinat Abdullin 和其他人这样的人监控着这个群体并提供了一些非常好的答案。我也建议不时检查一下。

希望这可以帮助!

于 2011-07-24T13:23:06.303 回答
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. my_code'上的前置条件合约do_something' makes it the responsibility of the client提供table_name' before making the call todo_something'。
  3. 作为回报,后置条件确保合同使其成为供应商do_something' fill the arraysql_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 calledset_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 todo_something 中的合同的用途,但该过程将得到适当的处理。对“delete_table”的注入调用只会导致合约失败。

所有这一切都假设在“my_table”上 DROP TABLE 是不可行的,并且这样做是不幸的意外。但是,如果可以在“my_table”上删除 TABLE,则需要重试机制或其他“处理程序”来管理此用例,并且上面的代码将不起作用。

于 2012-02-12T02:01:13.060 回答
0

我现在真的想到了这件事,[为什么我们不考虑“关注点分离”而不是“关注点分离”!]我知道它离题,但过多地推动标准将导致无处可去。从人类历史上很容易看出有多少实践/标准被时间证明是错误的!这完全取决于您对卓越的看法。

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

祝你好运!

于 2011-04-14T13:13:49.847 回答