2016-03-22 1 views
2

古典的な顧客限定コンテキストとMakeCustomerPreferredコマンドがあり、ロギングや認可などのクロスカッティングの問題があるとします。このようなクロスカッティングの問題を扱う方法は広範囲に議論されてきましたが、ドメインイベント自体でコマンドを発行する責任を負うユーザーまたはサービスに関する情報を記録したい場合があります。CQRS/ESシステムでイベントを発行しているサービスとユーザの録音

例イベント:

interface CustomerMadePreferred { 
    customerId: string, 
    issuingService: string, 
    issuingUser: string, 
} 

コマンド例:私たちの上のコマンドを使用して

interface MakeCustomerPreferred { 
    customerId: string 
} 

は、発行ユーザとサービスの詳細をコンテキストに欠けるでしょう。コマンドの一部としてクライアントにissuingServiceissuingUserの値を指定する必要があるかもしれませんが、問題は一般にクライアントから送信されたコマンドであり、クライアントがアプリケーションの制御外のWebブラウザであると想定できますユーザーがコマンド内で送信できる値を制御することはできません。さらに、OASuthトークンなどを使用してReSTfulまたはJSON Web APIの背後にサービスがある場合、これらの値を一般的に判断できます。これは私にいくつかの明白な戦略を残す。

可能な戦略:

  1. 認証コンテキストから決定された値と照合して検証し、その後のコマンドでissuingServiceissuingUserを含めると。これにより、クライアントから発行されたコマンドは、ハンドラによって処理されたものと同一になり、コマンドパラメータのみが必要であり、認証コンテキストが渡されないという点で、ハンドラ実装が単純になります。
  2. issuingServiceおよびissuingUser auth contextそれらの詳細をコマンドハンドラに渡されたコマンドに追加/注入する。これにより、元のコマンドを発行しているクライアントが簡単になりますが、コマンドハンドラとクライアントの間でコマンドのコントラクトが少し異なります。例:Object.assign({}, makeCustomerPreferredCommand, authContext);
  3. authコンテキストをコマンドハンドラとは別の引数として渡すか、コマンドハンドラから呼び出せるサービスからauthコンテキストを渡すことができます。これにより、コマンドの契約は保持されますが、コマンドハンドラの実装は複雑になります。

私はコマンドハンドラの実装に機能的なアプローチを可能にすると思われる主な理由のオプションとに傾いています。多分、私はいくつかのオプションを除外しているか、またはイベントに不要なものとしてissuingServiceissuingUserを含むいくつかの詳細を見落としています。

UPDATE:代替、オプションそれを呼び出す生成イベントをCustomerMadePreferred、代わりに処理し、そのいくつかの並べ替えのキーが含まれている可能性があり、別CommandIssuedイベントを発行してこれらの詳細を含まないようにすることができます発行者情報を、コマンドハンドラによって発行されたイベントと関連付けるために使用することができる。

+0

テクニカル実装では、同じ問題について考えているときに、予定にメタデータを追加することを計画しています。したがって、イベントはドメインオブジェクトのままですが、コンテキストを特定するために技術的なメタデータを添付することができます。 –

+0

@jpierson 2と3の間に違いはありません。*コマンドハンドラとクライアント*の間でコマンドが若干異なりますか? – guillaume31

+0

@ guillaume31では、2と3の違いはおそらく微妙ですが、これらのコマンド・タイプを取り巻くユニット・テストやコマンド・タイプを取り巻く他の反射型ツールをどのように書くかについては、大きな影響を受けます。コマンドハンドラのクラス/関数の契約もまた影響を受ける。 – jpierson

答えて

1

私はほとんどオプション4が好きです。私の気持ちは、相関IDが間違った仕組みであるということです。代わりに、私は因果関係IDを使用します。相関IDは若干異なることを意味します。 command.id:Nによって生成されたすべてのイベントは、イベントを持ちます。causationId:N、コマンド履歴(ドメイン外)に戻ってドメイン外の問題をチェックすることができます。

つまり、おそらくを見ている必要があります。はこの情報を取得したいと考えています。 devOpsチームの場合は、おそらくドメインのイベントをきれいに保つことが重要です。前述のコマンド履歴にリンクするだけです。

しかし、ここに隠れているドメインの概念があり、ユビキタス言語から抜け出してモデルに組み込む必要があることを示唆しているため、ドメインエキスパートがこれを望むのであれば、それは眉を浮かべるはずです。

Don't Create Aggregate Rootsと比較し;。?。顧客口座への変更は何から来ていない、彼らは本当にドメイン内から来てもしそうなら、おそらく追跡することを希望していること)

+0

大きなポイント!私は、causationIdという用語が好きです。私はまた、_originating command_というフレーズも、特定のコマンドにイベントを関連付けるという概念を記述するのに使われていると聞いてきました。私のケースでは、このような情報をイベントに含めるかどうかの問題は、ドメイン・エキスパートによる直接の懸念よりも、開発者または運用上の懸念のほうが多いと考えています。 – jpierson

1

私は普通に終わります最も複雑ではない解決策としてコマンドハンドラで直接認証コンテキストに到達します(これは、あなたのケースでは2.または3.と一致するかどうかわかりません)。私の場合、クライアントはコマンド自体を送信せず、(HTTPリソース、動詞、コンテンツタイプ)を通してコマンドを送信するので、クライアントとサーバーの間で異なるコマンド構造は問題ではありません。

+0

私もこれについて考えていました。私は、コマンド契約がクライアントにどれだけ公開されているか、GET/POSTに限定されたRPCスタイルを追っているのか、言及しているようにHTTP機能を利用しているのかによって異なります。 – jpierson

関連する問題