タグ付けされた質問 「cqrs」

コマンドクエリの責任分担の設計パターン

2
Command自体のメソッドを処理するのではなく、Handle()でクラスCommandHandlerを分離する理由
次のようなS#arpアーキテクチャを使用して実装されたCQRSパターンの一部があります。 public class MyCommand { public CustomerId { get; set; } // some other fields } public class MyCommandHandler<MyCommand> : ICommandHandler<MyCommand, CommandResult> { Handle(MyCommand command) { // some code for saving Customer entity return CommandResult.Success; } } なぜCommandデータと処理メソッドの両方を含むクラスを持たないのでしょうか?コマンド処理ロジックをコマンドプロパティとは別にテストする必要がある場合、一種のテスト容易性の利点ですか?または、さまざまな実装で1つのコマンドを処理する必要がある、頻繁なビジネス要件ICommandHandler<MyCommand, CommandResult>ですか?

3
ドメインドリブンデザインのドメインオブジェクトは書き込み専用である必要がありますか?
私はほぼ2年間ドメインドリブンデザインについて読んでおり、日々の仕事にいくつかの概念を慎重に導入するか、少なくともドメインドリブンデザイン内で定期的に行うことができる方法の計画を立てています。 特に、ドメインオブジェクトは書き込み目的にのみ使用されることを意図しているイベントソーシングとコマンドクエリの責任分離(CQRS)についての詳細を読んで、私が始めた結論の1つです。より明確にするために、私が読んだドキュメントの多くで人々が微妙に示唆していることは、ドメインオブジェクトがドメイン中心の操作/計算、検証を行う責任があること、そして主に永続化への道を提供するためにそこにあることを示唆しているようですリポジトリ実装内で提供されるインフラストラクチャ。状態を公開する責任を排除するため、これによりドメインモデルが大幅に簡素化される可能性があるという事実は気に入っていますが。 ドメインオブジェクトが主に書き込み専用オブジェクトとして使用されることが実際に正しい場合は、誰かに答えられることを望んでいるという疑問が生じます。 セッターを持つオブジェクト、またはオブジェクトの状態を変更するがC#のプロパティゲッターなどから状態を読み取る外部へのパブリックインターフェイスを提供しないメソッドで単体テストを実行するにはどうすればよいですか?そのオブジェクトをテスト可能にするためだけに状態を公開しても大丈夫ですか? ドメイン内で行われた計算または操作の結果を、それらを永続化せずにユーザーに表示し、ドメインのコンテキスト外の永続化ストアから結果をプルするにはどうすればよいですか?結果を表示するためだけに状態を公開しても大丈夫ですか? 唯一のプロパティゲッター(getアクセサー)はドメインでも書き込み可能なものでなければならないという経験則ですか?または、読み取り専用プロパティは読み取り専用であり、実際のドメインモデルで必要な役割を果たさないため、読み取り専用プロパティは避けるべき唯一のものであると言いますか? 関連資料: TDD、DDD、およびカプセル化

2
CQRS +イベントソーシング:(それは正しいですか)コマンドは一般にポイントツーポイントで通信されますが、ドメインイベントはpub / subを介して通信されますか?
私は基本的に、CQRSの概念と関連する概念に頭を包み込もうとしています。 CQRSには必ずしもメッセージングとイベントソーシングが組み込まれているわけではありませんが、適切な組み合わせのようです(これらの概念を組み合わせた多くの例/ブログ投稿でわかるように) 何かの状態変更のユースケース(SOに関する質問を更新するなど)が与えられた場合、次のフローが正しいと考えますか(ベストプラクティスとして)。 システムは、いくつかの小さなコマンドに分割される可能性のある集約UpdateQuestionCommandを発行します。質問集約ルートをターゲットとするUpdateQuestion、およびユーザー集約ルートをターゲットとするUpdateUserAction(ポイントをカウントするなど)。これらは、ポイントツーポイントメッセージングを使用して非同期的に送信されます。 集約ルートはそれぞれの処理を実行し、すべてがうまくいけば、QuestionUpdatedイベントとUserActionUpdatedイベントをそれぞれ起動します。これらのイベントには、イベントストアに外部委託された状態が含まれます。 これらのイベントは、ブロードキャスト用のpub / subキューにも置かれます。サブスクライバー(読み取りビューを作成する1つまたは複数のプロジェクターの可能性が高い)は、これらのイベントを無料でサブスクライブできます。 一般的な質問:コマンドはPoint-to-Pointで通信される(つまり、受信者が既知である)のに対して、イベントはブロードキャストされる(つまり、受信者が不明である)ことは本当にベストプラクティスですか? 上記を仮定すると、ポイントツーポイントではなくpub / subを介してコマンドをブロードキャストすることの利点/欠点は何でしょうか? 例:佐賀はどの集約ルートが最初に参加するのかわからないため、集約ルートの1つに障害が発生した場合に佐賀が果たす必要がある調停の役割が妨げられるため、佐賀の使用中にコマンドをブロードキャストすることが問題になる可能性があります。 一方、コマンドのブロードキャストが許可されると、利点(柔軟性)が得られます。

2
DDDを使用せず、ESを使用しない(または使用する)CQRS-書き込みモデルとは何か、読み取りモデルとは何ですか?
私の知る限り、CQRSの背後にある大きなアイデアは、コマンドとクエリを処理するための2つの異なるデータモデルを持つことです。これらは「書き込みモデル」および「読み取りモデル」と呼ばれます。 Twitterアプリケーションのクローンの例を考えてみましょう。コマンドは次のとおりです。 ユーザーは自分で登録できます。CreateUserCommand(string username)放出するUserCreatedEvent ユーザーは他のユーザーをフォローできます。FollowUserCommand(int userAId, int userBId)放出するUserFollowedEvent ユーザーは投稿を作成できます。CreatePostCommand(int userId, string text)放出するPostCreatedEvent 上記では「イベント」という用語を使用していますが、「イベントソース」イベントを意味するものではありません。読み取りモデルの更新をトリガーする信号を意味します。イベントストアはありませんが、これまではCQRS自体に集中したいと考えています。 クエリは次のとおりです。 ユーザーは投稿のリストを見る必要があります。 GetPostsQuery(int userId) ユーザーは、フォロワーのリストを見る必要があります。 GetFollowersQuery(int userId) ユーザーは、フォローしているユーザーのリストを見る必要があります。 GetFollowedUsersQuery(int userId) ユーザーは、「フレンドフィード」-すべての友達のアクティビティのログ(「友達のジョンが新しい投稿を作成しました」)を表示する必要があります。 GetFriedFeedRecordsQuery(int userId) 処理CreateUserCommandするには、そのようなユーザーが既に存在するかどうかを知る必要があります。したがって、この時点で、自分の書き込みモデルにはすべてのユーザーのリストが必要であることを知っています。 処理FollowUserCommandするには、userAがすでにuserBをフォローしているかどうかを知る必要があります。この時点で、書き込みモデルにすべてのユーザーフォローユーザー接続のリストが必要です。 そして最後に、処理するCreatePostCommandために他に何も必要ないと思います。なぜなら、私にはのようなコマンドがないからUpdatePostCommandです。それらがある場合、投稿が存在することを確認する必要があるため、すべての投稿のリストが必要になります。しかし、この要件がないため、すべての投稿を追跡する必要はありません。 質問#1:実際に使用する「モデルの書き込み」という用語を使用するのは実際に正しいですか?または、ESの場合、「書き込みモデル」は常に「イベントストア」を表しますか?もしそうなら、コマンドを処理する必要があるデータとクエリを処理する必要があるデータの間に何らかの分離がありますか? を処理GetPostsQueryするには、すべての投稿のリストが必要です。つまり、読み取りモデルにはすべての投稿のリストが必要です。私はを聞いてこのモデルを維持しPostCreatedEventます。 GetFollowersQueryとの両方を処理するには、GetFollowedUsersQueryユーザー間のすべての接続のリストが必要です。このモデルを維持するために耳を傾けるつもりですUserFollowedEvent。ここに質問#2があります:書き込みモデルの接続リストをここで使用しても実質上問題ありませんか?または、将来、書き込みモデルよりも詳細な情報が必要になる可能性があるため、個別の読み取りモデルを作成する必要がありますか? 最後に、処理するGetFriendFeedRecordsQueryには次のことが必要です。 聞く UserFollowedEvent 聞く PostCreatedEvent どのユーザーがどの他のユーザーをフォローしているかを知る ユーザーAがユーザーBをフォローし、ユーザーBがユーザーCをフォローし始めると、次のレコードが表示されます。 ユーザーAの場合:「友達ユーザーBはユーザーCのフォローを開始しました」 ユーザーBの場合:「ユーザーCのフォローを開始しました」 ユーザーCの場合:「ユーザーBがあなたをフォローしています」 ここだ質問#3:私は接続のリストを取得するために使用すべきかのモデル?書き込みモデルを使用する必要がありますか?読み取りモデルを使用する必要があります- GetFollowersQuery/ GetFollowedUsersQuery?または、GetFriendFeedRecordsQueryモデル自体UserFollowedEventにすべての接続の独自のリストを処理させ、維持させる必要がありますか?
11 cqrs  read-model 

1
CQRS + Event SourcingアーキテクチャでのAdd / Create *コマンドの処理方法
イベントソーシングと一緒にCQRSパターンを使用して、最初のアプリケーションを実装します。集約ルートの作成を適切に処理する方法について疑問に思っています。誰かがCreateItemコマンドを送信したとしましょう。どのように処理する必要がありますか?イベントItemCreatedを保存​​する場所 新しいアイテムの最初のイベントとして?または、すべてのアイテムを集約し、そのイベントリストがItemCreatedイベントのみで構成される、何らかの種類のItemListエンティティが必要ですか? Udi Dahan は、集約ルートを作成せず、常に何らかのフェッチメソッドを常に使用することを提案しています。しかし、新しいもので、IDが割り当てられていないものを取得する方法。私は背後にある考え方を理解しており、新しいオブジェクトは、それに応答するイベントがゼロで構成される状態を持つオブジェクトであると考えるのはかなり合理的です。しかし、どのように使用すればよいですか?私のような私のリポジトリに明確な方法を持っていなければならないgetNewItem()か、私の作るget(id)方法を受け入れてOptional<ItemId>代わりに? 編集:しばらく掘り下げた後、アクターを使用した前述のパターンの非常に興味深い実装を見つけました。作成者は、集計を作成する代わりに、新しく作成されたUUIDを使用して、何らかの種類のリポジトリからそれを取得します。このアプローチの欠点は、一時的な不整合状態を許容することです。またdelete、このようなアプローチでメソッドを実装する方法を疑問に思っています。削除済みイベントを集約のイベントリストに追加するだけですか?

3
イベントを再生するときにCRQSの副作用を処理するにはどうすればよいですか?
CQRSではバグを修正するのは簡単で、イベントを再デプロイして再生するだけだと言われています。 ただし、イベントを再生するだけでアイテムが2回出荷される場合、イベントの1つが原因で、制御できない外部システムが顧客に「アイテムを出荷する」原因となる場合はどうでしょうか。 それをどのように解決しますか?

2
CQRSで新しい集約ルートを作成するにはどうすればよいですか?
cqrsアーキテクチャで新しい集約ルートを作成するにはどうすればよいですか?この例では、最初の1つのAR1への参照を保持する新しい集約ルートAR2を作成します。 開始点としてAR1メソッドを使用してAR2を作成しています。これまでのところ、いくつかのオプションが表示されます。 AR1の内部メソッドでは、リポジトリにアクセスできるドメインサービスを使用して、このオブジェクトをcreateAr2RootOpt1呼び出しnew AR2()てdb imediatellyに保存できます。 最初の集約ルートなどでイベントを発行できます。SholdCreateAR2Eventこれに反応してコマンドCreateAR2Commandを発行するステートレスサガがあり、それが処理されて実際にAR2が作成されて放出されAR2CreatedEventます。イベントソースを使用する場合、SholdCreateAR2Event最初の集約ルートの状態には影響しないため、イベントストアに保持されません。(または、これをイベントストアに保存する必要がありますか?) class AR1{ Integer id; DomainService ds; //OPTION 1 void createAr2RootOpt1(){ AR2 ar2 = new AR2(); ds.saveToRepo(ar2); } //OPTION 2 void createAr2RootOpt2(){ publishEvent(new SholdCreateAR2Event()); //we don't need this event. Shoud it still be preserved in event store? } } class AR2{ Integer id; Integer ar1Id; …

3
妥協する必要があります:DRY、またはCommand-Query-Separation?
私は最近、コマンドとクエリメソッドの両方であるメソッドをリファクタリングしていました。 それを1つのコマンドメソッドと1つのクエリメソッドに分離した後、コマンドを呼び出してクエリから値を取得するコード内の複数の場所があり、これはDRYの原則に違反しているようです。 しかし、その一般的なコードをメソッドにラップすると、そのメソッドはコマンドとクエリの両方になります。これは受け入れられますか?

2
コマンドハンドラーとDDD
クエリサービスを使用してデータを取得し、コマンドサービスを使用してコマンドを送信するASP.NET MVCアプリケーションがあります。私の質問は、コマンド部分についてです。 リクエストが届くと、コマンドサービスはコマンドディスパッチャーを使用して、指定されたコマンドハンドラーにコマンドをルーティングします。このコマンドハンドラーは最初にコマンドを検証し、すべてが許容できる場合はコマンドを実行します。 具体例:AddCommentToArticleCommandHandlerは、ArticleId、CommentText、EmailAddressを持つAddCommentToArticleCommandを受け取ります。 最初; -記事が存在するかどうかを確認します-記事が閉じていないかどうかを確認します-コメントテキストが20〜500文字で入力されているかどうかを確認します-電子メールアドレスが入力されており、有効な形式であるかどうかを確認します この検証をどこに置くか疑問に思っていますか? 1 /コマンドハンドラ自体。ただし、他のコマンドハンドラで再利用することはできません。 2 /ドメインエンティティ内。しかし、ドメインエンティティはリポジトリやサービスを認識していないため、必要な検証を実行できません(記事が存在するかどうかを確認できません)。ただし、一方で、エンティティにロジックが含まれていない場合は、DDDの原則に従っていない単純なデータコンテナーになります。 3 /コマンドハンドラーはバリデーターを使用するため、検証を他のコマンドハンドラーで再利用できます。 4 /その他のメカニズム? この特定の例の一連の責任と、その中で役割を果たすオブジェクト(エンティティ、リポジトリなど)を探しています。 コマンドハンドラーからリポジトリまで、これをどのように実装するかについてのアイデアはありますか?

3
CQRS / ESでは、コマンドは別のコマンドを作成できますか?
CQRS / ESでは、コマンドはクライアントからサーバーに送信され、適切なコマンドハンドラーにルーティングされます。そのコマンドハンドラーは、リポジトリーからアグリゲートをロードし、その上のいくつかのメソッドを呼び出して、それをリポジトリーに保存します。イベントが生成されます。イベントハンドラー/佐賀/プロセスマネージャーは、コマンドを発行するためにこれらのイベントをリッスンできます。 そのため、コマンド(入力)はイベント(出力)を生成し、それがシステムにさらにコマンド(入力)をフィードバックできます。さて、コマンドがイベントを発行せず、別のコマンドをエンキューするのが一般的な方法でしょうか?このようなアプローチは、外部プロセスでの実行を強制するために使用できます。 編集: 私が考えている特定のユースケースは、支払いの詳細の処理です。クライアントはPayInvoiceコマンドを送信します。そのペイロードにはユーザーのクレジットカードの詳細が含まれます。PayInvoiceHandler通過MakeInvoicePayment支払いゲートウェイとの相互作用の原因である別のプロセスにコマンドを。支払いが成功すると、InvoicePaidイベントが生成されます。PayInvoiceコマンドが保持された後、コマンドが保持される前に何らかの理由でシステムがクラッシュした場合MakeInvoicePaymentは、これを手動で追跡できます(支払いは行われません)。MakeInvoicePaymentコマンドが持続した後、システムがクラッシュする前にInvoicePaidイベントが持続する場合、ユーザーのクレジットカードに請求が行われているのに、請求書に支払い済みのフラグが付けられていない可能性があります。その場合、状況を手動で調査し、請求書に手動で支払い済みのマークを付ける必要があります。

4
CQRS + ESのオブジェクトはどこで完全に初期化する必要がありますか:コンストラクター内、または最初のイベントを適用するとき?
OOPコミュニティでは、クラスコンストラクターがオブジェクトを部分的または完全に未初期化のままにしてはならないという合意が広まっているようです。 「初期化」とはどういう意味ですか?大まかに言えば、新しく作成されたオブジェクトを、そのクラスのすべての不変条件が保持される状態にするアトミックプロセス。これはオブジェクトに最初に発生するものであり(オブジェクトごとに1回だけ実行する必要があります)、初期化されていないオブジェクトを取得することは許可されません。(したがって、クラスコンストラクターでオブジェクトの初期化を正しく実行するための頻繁なアドバイスです。同じ理由で、Initializeメソッドはしばしばアトミック性を分解し、まだ使用されていないオブジェクトを取得して使用することを可能にするため、眉をひそめられます明確な状態にあります。) 問題: CQRSとイベントソーシング(CQRS + ES)を組み合わせると、オブジェクトのすべての状態変化が順序付けられた一連のイベント(イベントストリーム)でキャッチされ、オブジェクトが実際に完全に初期化された状態にいつ到達するのか疑問に思います。クラスコンストラクターの最後、または最初のイベントがオブジェクトに適用された後? 注:「集約ルート」という用語の使用は控えています。必要に応じて、「オブジェクト」を読むたびに置き換えてください。 議論の例:各オブジェクトが何らかの不透明なId値(GUIDと考える)によって一意に識別されると仮定します。そのオブジェクトの状態変化を表すイベントストリームは、同じId値によってイベントストアで識別できます(正しいイベントの順序については心配しないでください)。 interface IEventStore { IEnumerable<IEvent> GetEventsOfObject(Id objectId); } さらに、2つのオブジェクトタイプCustomerとがあると仮定しますShoppingCart。焦点を当てましょうShoppingCart:作成されたとき、ショッピングカートは空であり、正確に1人の顧客に関連付けられている必要があります。最後のビットはクラス不変です:にShoppingCart関連付けられていないオブジェクトはCustomer無効な状態です。 従来のOOPでは、コンストラクターでこれをモデル化できます。 partial class ShoppingCart { public Id Id { get; private set; } public Customer Customer { get; private set; } public ShoppingCart(Id id, Customer customer) { this.Id = id; this.Customer = customer; } …

2
ゼロ引数コンストラクターと常に有効なエンティティ
私は最近、Always Validドメインエンティティについて多くの読書をしました。エンティティが常に有効であることを保証するために、私は次のことを行う必要があると信じるようになりました。 1)ここで説明されているように、プリミティブな強迫観念を取り除き、値オブジェクトコンストラクターに検証/ドメインルールを配置します:https : //enterprisecraftsmanship.com/2016/09/13/validation-and-ddd/。2)ここで説明されているように、検証またはドメインルールをエンティティまたはプロパティセッターのコンストラクタに配置します:http ://gorodinski.com/blog/2012/05/19/validation-in-domain-driven-design-ddd/ 。 ただし、次に、https://github.com/gregoryyoung/mrなどのいくつかのオープンソースプロジェクトを調べます。私が理解していることから、このプロジェクトの作成者は常に有効なドメインモデルの擁護者ですが、それでもInventoryItemクラス(https://github.com/gregoryyoung/mr/blob/master/SimpleCQRS/Domain.cs)を調べます。私はこれを行うことができることに気づきました: InventoryItem inventoryItem = new InventoryItem(); またはこれ: InventoryItem inventoryItem2 = new InventoryItem(Guid.Empty,null); 私の考えでは、これはエンティティが無効な状態で初期化されることを意味します。これは、私が最近見た他のすべてのオープンソースプロジェクトにも当てはまるようです。たとえば、次のプロジェクトです。https://github.com/dcomartin/DDD-CQRS-ES-Example/blob/master/src/Domain /Customer.cs。 これらのオープンソースプロジェクト(https://martinfowler.com/bliki/ContextualValidation.html)にコンテキスト検証があることに気づきました。また、ドメインモデルにマップする場合、ORMにはデフォルトの空のコンストラクターが必要であることも理解しています。 ドメインオブジェクトは、引数なしのコンストラクタを使用してデフォルト値で初期化されている/空/ null値で初期化されている場合、有効な状態ですか?

2
「その他」の集合体の状態をどこで検証する必要がありますか?
シナリオ: 顧客が注文し、製品を受け取った後、注文プロセスに関するフィードバックを提供します。 次の集計ルートを想定します。 お客様 注文 フィードバック ビジネスルールは次のとおりです。 顧客は自分の注文についてのみフィードバックを提供でき、他の人のフィードバックは提供できません。 顧客は、注文に対する支払いが済んでいる場合にのみフィードバックを提供できます。 class Feedback { public function __construct($feedbackId, Customer $customer, Order $order, $content) { if ($customer->customerId() != $order->customerId()) { // Error } if (!$order->isPaid()) { // Error } $this->feedbackId = $feedbackId; $this->customerId = $customerId; $this->orderId = $orderId; $this->content = $content; } } ここで、企業が新しいルールを望んでいると想定します。 …

2
イベントの調達、再生、バージョン管理
イベントソーシング、CQRS、マイクロサービスを使用するシステムを設計しています。これは珍しいパターンではないことを理解しました。このサービスの重要な機能は、記録システムから再水和/復元する機能である必要があります。マイクロサービスは、MQ(Kafka)でコマンドとクエリを生成します。他のマイクロサービスが応答します(イベント)。コマンドとクエリは、監査と復元の目的でS3に保持されます。 現在の思考プロセスは、システムを復元するために、S3からイベントログを抽出し、単純にKafkaにフィードバックできるというものでした。 しかし、これは時間の経過に伴う生産者と消費者の両方の変化を認めることができません。コマンド/クエリレベルでのバージョン管理は、問題の解決にある程度役立つようですが、復元中のコマンドが受信および処理されたときに、まったく同じになるようにコンシューマーのバージョン管理を行うことはできません。 [のバージョン]コマンドを最初に受信したときに処理を実行しているコード。 これを解決するために使用できるパターンはありますか?この機能を宣伝する他のシステムを知っている人はいますか? 編集:例を追加します。 「バイヤー」が私のオークションサイトの「セラー」に「質問」を送信します。フローは次のようになります。 UI -> Web App: POST /question {:text text :to seller-id :from user-id} Web App -> MQ: SEND {:command send-question :args [text seller-id user-id]} MQ -< Audit: <command + args appended to log in S3> MQ -< Questions service: - Record question in DB …
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.