ドメインドリブンデザインのドメインオブジェクトは書き込み専用である必要がありますか?


13

私はほぼ2年間ドメインドリブンデザインについて読んでおり、日々の仕事にいくつかの概念を慎重に導入するか、少なくともドメインドリブンデザイン内で定期的に行うことができる方法の計画を立てています。

特に、ドメインオブジェクトは書き込み目的にのみ使用されることを意図しているイベントソーシングとコマンドクエリの責任分離(CQRS)についての詳細を読んで、私が始めた結論の1つです。より明確にするために、私が読んだドキュメントの多くで人々が微妙に示唆していることは、ドメインオブジェクトがドメイン中心の操作/計算、検証を行う責任があること、そして主に永続化への道を提供するためにそこにあることを示唆しているようですリポジトリ実装内で提供されるインフラストラクチャ。状態を公開する責任を排除するため、これによりドメインモデルが大幅に簡素化される可能性があるという事実は気に入っていますが。

ドメインオブジェクトが主に書き込み専用オブジェクトとして使用されることが実際に正しい場合は、誰かに答えられることを望んでいるという疑問が生じます。

  1. セッターを持つオブジェクト、またはオブジェクトの状態を変更するがC#のプロパティゲッターなどから状態を読み取る外部へのパブリックインターフェイスを提供しないメソッドで単体テストを実行するにはどうすればよいですか?そのオブジェクトをテスト可能にするためだけに状態を公開しても大丈夫ですか?
  2. ドメイン内で行われた計算または操作の結果を、それらを永続化せずにユーザーに表示し、ドメインのコンテキスト外の永続化ストアから結果をプルするにはどうすればよいですか?結果を表示するためだけに状態を公開しても大丈夫ですか?

唯一のプロパティゲッター(getアクセサー)はドメインでも書き込み可能なものでなければならないという経験則ですか?または、読み取り専用プロパティは読み取り専用であり、実際のドメインモデルで必要な役割を果たさないため、読み取り専用プロパティは避けるべき唯一のものであると言いますか?

関連資料:

  1. TDD、DDD、およびカプセル化

回答:


9

公平を期すために、まだ進化している設計アプローチに対して「真の方法」の答えがあるかどうかはわかりません。まず、DQとCQRSは同じものではありませんが、CQRSの人々はDDDの影響を受けた出発点から派生したようです。

DDDの考え方には多くのことが行われていますが、その多くは、適切に定義された問題の境界、利害関係者間のコミュニケーション、システム間の相互作用に関係しています。コアは美徳です。

ドメインオブジェクトを変更可能にする必要があるかどうか、どのように変更するか、およびドメインオブジェクトがシステム全体でどの機能を果たすかについての議論が見られるかもしれません。CQRSはシステムを読み取りと書き込みの経路に分割するため、書き込み経路にいるときに実際に読み取りアクセスを必要としないと結論付けるのが賢明です。読み取りは、一部のドメインオブジェクトによって発生し、他のドメインオブジェクトによって消費(処理)されるイベントに対して行うこととなります。CQRSの履歴を少し遡ると、ドメインオブジェクトにはセッターがなく、ゲッターと1つの「ハンドラー」メソッドだけが必要であるという引数が見つかります。ここでのロジックは、イベントを消費するだけで状態が変化し、その変化はドメインオブジェクトによって内部的に完全に処理されるということです。

変更の結果を表示するには、それらを個別の変更のアーティファクトとして扱い、個別のフラットな永続構造(テーブルなど)に入れ、システムの現在および過去の状態に関するレポートを読んでいるかのように読み取ります。 。たとえば、読み取りに必要なデータを抽出し、システムの単一のビュー(画面など)に密接に対応するデータベーステーブルに保存することで、イベントを消費できます。

このスタイルを試してみる場合、他のプログラマーはこのアプローチに慣れていない可能性が高く、設計アプローチとして正当化できるシナリオは比較的少ない(しかし興味深い)ことを認識してください。

単体テストには、いくつかのアプローチがあります。最初の最も自然な方法は、ドメインオブジェクトによって発生することが予想されるイベントが正しいことを確認することです。ドメインオブジェクトは、変更に関する情報を保持する一般的な変更イベントを発生させる場合があります。それを確認できます。イベントがまったく発生したことと、他のイベントが発生していないことを確認できます。

別の方法は、ドメインオブジェクトの読み取り可能な属性を公開するテストスパイを使用して、状態の変更を確認できるようにすることです。たとえば、ドメインオブジェクトを継承し、アクセサを追加して、カプセル化された状態を読み取り、それが正しいことを確認できます。

繰り返しますが、これらのアプローチは混乱を招くため、混乱しています。プログラミングに良いアイデアを取り入れたい場合は、まずジューシーなビットを使用してください。DDDの境界と役割を明示的にすることは、コードとの通信に関する考え方の変更です。CQRSは少なくとも、データの読み取りとデータの書き込みは分離可能な操作であることを示唆しています。その洞察は、あなたが提示する必要があるデータの役割が何であるか、あなたが本当に必要とする量、それを消費している人、それがどれくらい新鮮である必要があるかなどについて非常に明確に考えるように導きます...本格的なEvent Sourcing実装により、コーディングのカプセル化を改善します。まず、オブジェクト内のアトミックな操作に焦点を当てることから始めます。オブジェクトインターフェイスデザインへの「伝える、聞かない」アプローチ


1
ジューシービットで始まる場合は+1。さらに、CQSだけを噛む(今のところ「イベント」の部分をスキップする)ことから始めるのが良いかもしれません。
cottsak

1

ドメインドリブンデザインのドメインオブジェクトは書き込み専用である必要がありますか?

いいえ。CQRSはDDDと一緒に使用できます。


しかし、CQRSのクエリ部分は、モデルに変更を書き込むためにドメインモデルで使用されるデータのクエリに関するものですか、それとも、ユーザーに値を示すアプリケーション層のデータのクエリに使用できますか?私は、DDDは変更の調整に関するものであり、ドメインモデル内の別のオブジェクトへの変更を調整する以外の目的で読み取るために使用すべきではないと一部の人から聞いています。何らかの方法で決定するということは、ドメインオブジェクトで公開されたデータがドメイン内でのみ消費される場合、そのデータが制限されて変化するという根本的に異なるモデル設計を意味します。
jpierson

0

ドメインモデルの単体テストでは、実行されるコマンドごとに正しいドメインイベントが発生することを確認する必要があります。ドメインコマンドとキャプチャされたイベントは、状態を調べることができます。

ToString()ドメインのコマンドとイベントをオーバーライドして、人間が読める状態の自動レポートを提供することもできます。

2番目の質問に答えるには、コマンドの結果を表示するために、ドメインイベントが読み取りモデルに「公開」されるように調整する必要があります。


イベントソーシングを使用していないときに、これがまだ適用されるかどうかについて少し詳しく説明していただけますか?
jpierson

1
イベントソースがないと、おそらく私の提案は機能しません。あなたのコードのやり方がわかりません。理想的にはプロパティを公開しないドメインオブジェクトの場合、おそらく、テストするプロパティを公開するテストインターフェイスを明示的に実装できます。テストコードのみが、そのようなドメインオブジェクトをテストインターフェイスにキャストすることを「認識」します。
エドジェームズ

その提案をありがとう。特にテスト容易性のためにドメインクラスを変更するというアイデアについては少し不安に感じますが、これをテスト可能にしたい場合、これはまだドメインドリブンデザインの灰色の領域の1つであると思われます。別の考えは、同じインターフェイスを介して安定性とテスト容易性を公開する場合、少なくとも2つのインフラストラクチャ依存関係を導入するのは1つのインフラストラクチャ依存関係だけであるということです。他の人はそれについてどう思いますか?
jpierson
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.