1

についてどう思いますか

 if(!DoSomething()) return;

クリーンコードでは、これはコマンドクエリ分離の違反と見なされます。しかし、コマンドDoSomething()の何かがうまくいかなかったかどうかをどうやって理解できますか?SQLコマンド(例:void Delete(Table))はどうですか?そのテーブルが存在したかどうかをどうやって知ることができますか?

ありがとう。

4

4 に答える 4

1

CanDoSomethingのコマンドを発行する前に確認する必要があるというrObiwahnからのコメントに同意しますDoSomething。純粋なCQRS環境でDoSomethingは、何も返さず、何かが発生するのを妨げた場合(例外ではなく、競合状態またはとの間CanDoSomethingで変化する何かDoSomething)、ドメインはDoSomethingWasInvalidイベント(またはそのようなもの)を発行します。アプリケーションが最終的に一貫性を持つようにします。

複雑に聞こえるかもしれませんが、ロジックを小さなチャンクに分割し始め、アプリケーションが結果整合性を受け入れることができるようになると、非常に単純になります。

グーグルグループの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. do_something' makes it the responsibility of the clientdo_something'を提供するための my_code'の前提条件コントラクトtable_name' before making the call to
  3. その見返りに、事後条件保証契約はdo_something' fill the array、STUFF のインスタンスを持つサプライヤー sql_list' の責任になります。
  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'.

この場合、Design-by-Contract の「コントラクト」は、懸念事項の適切な分離と、上記の小さなコードで誰が何を担当するかを保証します。コードに 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」で DROP TABLE がOKになった場合は、この使用例を管理するために再試行メカニズムまたはその他の「ハンドラー」が必要となり、上記のコードは機能しません。

于 2012-02-12T02:01:13.060 に答える
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 に答える
0

私は今、本当にこのことが頭に浮かびました.[なぜ私たちは「懸念の分離」ではなく「分離の懸念」を考えないのですか!] 私はそれが話題から外れていることを知っていますが、基準を押しすぎるとどこにも行きません. 人類の歴史から、どれだけの慣行/基準が間違っていることが証明されたかを簡単に確認できます! それはすべて、卓越性のあなたの視点に関するものです。

そのような場合、私は常に真であり続けるために反対のことを考えようとします. もっと言いたいのですが、私の回答の観点からはそれで十分だと思います;)

幸運を!

于 2011-04-14T13:13:49.847 に答える