17

私はDDDの原則を使用してアプリケーションを作成しています。できる限りすべてを考えた後、私はバウンドコンテキストの作成を開始します。最終的な構造はまだ設定していませんが、現時点では、アプリケーションは次の制限されたコンテキストで構成されています。

  1. 従業員の管理
  2. 購入
  3. 記録
  4. 報告

これをできるだけプラグインできるようにしたいので、たとえば、別々に開発して保守することができます。おそらく、それらはWCFまたはWebAPIのいずれかを公開してそれらと対話します。

単純なCQRSパターンのUdiDahans実装を使用します。これは高度なコラボレーションアプリではないため(ユーザー数が1000人未満で、同じ小さなデータセットを編集する可能性が低いため)、イベントソーシングやメッセージバスなどを使いたくありません。不必要な複雑さをたくさん追加します。

だから質問に:

従業員と部門のエンティティはすべてのBCに共通ですが、それをどのようにモデル化するのですか?

部門は組織構造の一部であるため、従業員管理BCでは、従業員は部門で作業し、部門を管理でき、これまでに取り組んだ部門の履歴があります。

購買では、BC商品は部門から購入され、部門に配送されます。サプライヤーは、部門ごとに異なる契約を結んでいます。

アーカイブでは、一部の情報がアーカイブされ、部門に関連付けられます。

同じことが従業員にも当てはまります。

制限されたコンテキストからデータを永続化する方法は?

それらは同じデータベースにマップすることも、それぞれに独自のデータベースを持たせることもできます。

私がこれまでにしたいくつかの考え

モデル化の方法
「会社」または「組織」と呼ばれるもう1つのBCを作成し、そこで部門を管理する必要がありますか?

上記のUdiDahansの記事に従って、各BCの部門エンティティと従業員エンティティを、そのBCに必要なフィールドと動作だけで作成する必要があります。これは理にかなっているように聞こえますが、実際にこれをどのように使用するかを考えているので、理解できません。他の場所で管理されている部門にアクセスする必要がありますが、BCを混在させずに、これをどのように正確に行うのですか?

使い方?
クエリを実行して、どこかから部門のリストを取得したとします。UIには、購入したい部門のリストも表示されます。これはこの部門の最初の購入であるため、購買BCはこの部門についてまだ知りません...したがって、購買BCの部門オブジェクトは、他のBCから維持されたデータで満たされます-では、これをどのように保持しますか?配送先住所や請求書住所などの情報が存在しない場合は、追加する必要がありますか?

次に、「部門UIの登録」で、すべてのBCで「RegisterDepartment」サービスを呼び出し、UI(MVCコントローラー)を介して行われたすべての変更と同期していることを確認する必要がありますか?

従業員も同じです。どの従業員が購入したか、アーカイブに何かを入れたか知りたいです。したがって、どういうわけか、これらのBCにも従業員オブジェクトが必要ですが、別のBCからそれらを管理します。

永続
化上記の課題のいくつかは、データベース内の同じテーブルにさまざまな従業員オブジェクトをマッピングすることで解決できます。PurchasingBCとArchiveBCは新しい従業員を登録できませんが、そこにいる従業員に情報を追加し、同じデータベース内の他のオブジェクトに結び付けます。そうすれば、データベースは、すべてのBCがまだ同じ世界に住んでいることを確認します...

アドバイスが必要なので、後で維持するのが非常に難しいものを作ってしまうことはありません。

4

2 に答える 2

13

あなたの疑問のほとんどは、「単一の現実のオブジェクトは、異なる境界のコンテキストによってどのように共有されているのか」ということを巡っているようです。

重要なのは、エンティティは同じですが、BCごとに異なる方法で処理されるということです。従業員管理BCでは、全体の重みは従業員と部門のエンティティに集中しています。これらを追加、変更、相互に割り当て、履歴を保持し、管理に関するすべてのビジネスロジックを処理できる必要があります。従業員の個人データを保持する、適切な公式構造を維持する、または特定の責任を維持するといういくつかのポリシーを実装できます。

一方、購入コンテキストの部門エンティティは、たとえば、請求書の住所と、おそらく責任のある部門の担当者のみを意味し、関心の中心が注文を作成します。購入の手順に直接関係しないすべてのデータは、別のコンテキストに提供する必要があります。たとえば、ドメインですべての注文を部門に接続する必要があり、請求書の詳細が欠落している場合、購入コンテキストはそれ自体でそれらを埋めようとしないでください。代わりに、不足している部分を埋めるために従業員管理者に通知することができます。

同じアプリケーションまたは同じウィンドウで発生する可能性が非常に高いことに注意してください。ただし、それが従業員管理コンテキストを介して、つまりコンテキストパブリックAPIを呼び出すことによって確実に行われるようにする必要があります。

ちなみに、私はあなたのドメインを知りませんが、例えば配達と購入を分離することによって、あなたはあなたの文脈の境界を再考したいかもしれません。

使用法に移り、あなたの例に従って、購入したい場合は、次のパスを検討します。

  • 必要な部門データを読みます(後で「方法」で待ちましょう)。この時点ですべてのデータが存在するかどうかを確認することをお勧めします。
  • ドメインによっては、サプライヤーなどの別のBCを紹介する価値があるかもしれないので、購入できる商品を読んでください。上記のすべては、CQRSの「クエリ」部分です。
  • 注文またはその他の必要な購入コンテキストエンティティを構築し、検証またはその他のロジックを実行します
  • 変更をコミットし、購入コンテキストエンティティを永続化します(「コマンド」部分)
  • いくつかのドメインイベントを作成して公開します(たとえば、アーカイブまたはレポートに通知するため)

最後になりましたが、ドメインレイヤーでのグローバルな永続性について心配する必要はありません。すべてのBCは、必要なオブジェクトを提供し、それらをどこから取得するかなどの詳細を処理するデータアクセスまたはインフラストラクチャレイヤーに接続する必要があります。

特に、エンティティは必ずしもデータベースレイアウトをミラーリングする必要はなく、1つまたは複数のデータベースに格納するかどうかの問題は、パフォーマンスの問題にすぎないはずです。たとえば、一部のエンティティは同じオブジェクト(たとえば、従業員名)を参照しますが、まったく異なるテーブルまたはデータベース(つまり、購入履歴またはアーカイブに送信された要素)から他の詳細を取得できます。NHibernateのようなものを使用して、これを簡単に管理できるようにすることができます。

于 2012-11-23T18:18:19.337 に答える
5

ここでは古い質問に答えていますが、OPの質問で直面した問題の別の例があります。

製造会社で使用しているアプリケーションに取り組んでいる状況があります。この会社には、営業、運用、生産、アカウント、技術サポートの部門があります。これらすべての部門には、顧客の概念があります。そのため、これらの部門に顧客エンティティがどのように存在するかを理解するのに苦労しました(これをバインドされたコンテキストとしてマップしました)。

これについて何度も考えたとき、何かがクリックされたのですが、ジミー・ボガードのブログ投稿で読んだコメントを思い出しました。彼は、自分が取り組んだドメインモデルについて話しましたが、問題に取り組むほど、ドメインを理解し、エレガントなデザインにたどり着くことができました。

私が明確にした瞬間は、永続性について考えるのをやめ、これらのBCの顧客について考えるのをやめたときでした。

私が気付いたのは、セールスBCは顧客について知る必要があるということでしたが、MDが誰であるか、連絡先のリスト、オフィスのリスト、意思決定者が誰であるか、財務担当者が誰であるかなど、非常に具体的な情報が必要です。

現在、Ops BCはシステムで注文を出す責任があり、顧客の概念が必要です。ただし、MDが誰であるか、または連絡先のリストを知る必要はなく、その顧客がどのオフィスを持っているかを誰が気にするのでしょうか。Opsは顧客名、この場合は4文字の顧客コードを知っている必要があります。私が考えるとき、私はこの情報をエンティティとして永続化する必要さえありません。それは私のOpsBCの値オブジェクトである可能性があります。しかし、どうすればこの情報をOps BCに取り込むことができますか?まあ、それは本当に簡単です。BCは、アプリケーションがOpsBCと対話できるインターフェイスを定義します。私のアプリケーションは、そのOps BC内で何が起こっているのかわかりませんが、Order Aggregatrルートがあり、CustomerValueObject型の引数を受け取るRaiseNewOrderへのメソッドがあることは知っています。CustomerValueObjectは、4文字のコードと顧客名で構成されています。したがって、私のアプリUIでは、Sales(Customer Managementと呼びます)BCを使用して、顧客のリストを取得し、ドロップダウンリストを表示できます。次に、操作のトランザクション部分、つまりユーザーが新しい注文情報を投稿するときに、Ops BCを使用し、customerVOを引数として渡します。

したがって、OpsBCとSalesBCは分離されており、自己完結型であり、ドメインの整合性を確保するために必要な概念が内部にあり、オペレーターが選択できるようにUIで必要なデータにアクセスできます。次に、OpsBCでアクションを実行する顧客。

私が気付いたのは、営業チームの顧客は、運用チームの顧客と同じではないということでした。Opsの人にとって、顧客は注文にタグを付けるものにすぎません。彼らはその会社の内部の仕組みやそれに関する情報には何の興味も持っていません。BC全体で顧客に共通のIDを持っている限り、プレゼンテーションに必要なデータIDをプルバックする方法があります。たとえば、Ops BCを使用して、顧客XXXXの注文リストをプルバックできます。そのためにCustomerAggregateを経由する必要はありません。

今、このしわを投げます。営業担当者は、ある時点で顧客の注文について知る必要があります。そのため、営業BCで情報の複製を開始する必要がありますか?ここで行き詰まりましたが、営業担当者について話していることに気付きました。彼らはUIのユーザーであり、UIでは特定の顧客の注文のリストを取得できます。

私はまだDDDにかなり慣れていませんが、DDDはすべてドメインの専門家との会話に関するものであり、それらの会話を適切に行うと、BC全体に存在すると思われるエンティティは存在しないことに気付きます。

私たち開発者は、経験を通じてデータを非正規化し、データベース構造と、これらのCustomerオブジェクトをテーブルに永続化する方法について考えるように設定されていると思います...したがって、エンティティは1つのグロブと見なされますが、ドメイン専門家はこれらのエンティティをこのように見ていません。

私にとって取引を封印したコメントは、「この注文から会計部門は何を見る必要があるのか​​」などの質問をしたときのかなり意地悪なOps Directorからのコメントであり、彼の回答から、「私は何を気にしない」という宣誓を差し引いたものでした。彼らが欲しい、私はただ私が欲しいものが欲しい」。そして、私はあなたがBCを見る必要がある方法だと思います。

このワッフルがとにかく誰かを助けることを願っています。

于 2016-02-02T11:58:28.333 に答える