問題空間の簡単な復習から始めましょう。DDDの基本的な原則の1つは、ビジネスルールを適用する必要のある場所にできるだけ近づけることです。これは非常に重要な概念であり、システムをより「まとまり」のあるものにします。ルールを「上向き」に移動することは、一般的に貧血モデルの兆候です。ここで、オブジェクトは単なるデータのバッグであり、ルールには適用されるデータが注入されます。
貧血モデルは、DDDを使い始めたばかりの開発者には非常に理にかなっています。メールを検証するために必要な情報が注入されるUser
モデルとを作成EmailMustBeUnqiueRule
します。シンプル。エレガント。問題は、この「一種の」思考が根本的に手続き型であるということです。DDDではありません。何十ものRules
きちんとラップされてカプセル化されたモジュールが残されてしまいますが、いつどこで適用されるかが明確ではないため、変更できなくなるところまで完全にコンテキストがありません。それは理にかなっていますか?それは可能という自明のこと EmailMustBeUnqiueRule
の作成時に適用されますUser
が、何についてUserIsInGoodStandingRule
?。ゆっくりだが確実に、抽出の粒状化Rules
それらのコンテキストから外れると、理解しにくい(したがって変更できない)システムが残ります。ルールは、実際のクランチ/実行が非常に詳細であり、モデルがフォーカスを失い始めた場合にのみカプセル化する必要があります。
今すぐあなたの特定の質問へ上:持つ問題Service
/ CommandHandler
スローException
ビジネスロジックは、自分のドメインのうち、(「上向き」)リークし始めているということです。なぜ、あなたのんService
/ CommandHandler
電子メールを知る必要は一意である必要がありますか?アプリケーションサービスレイヤーは通常、実装ではなく調整に使用されます。この理由は、ChangeEmail
メソッド/コマンドをシステムに追加した場合に簡単に説明できます。これで、メソッド/コマンドハンドラーの両方に独自のチェックを含める必要があります。これは、開発者がを「抽出」したくなるかもしれない場所EmailMustBeUniqueRule
です。上で説明したように、そのルートには行きたくありません。
追加の知識を駆使すると、より多くのDDD回答が得られます。電子メールの一意性は不変であり、User
オブジェクトのコレクション全体に適用する必要があります。ドメインに「User
オブジェクトのコレクション」を表す概念はありますか?たぶん私がどこに行くのかわかると思います。
この特定のケース(およびコレクション全体で不変条件を適用することを含む多くのケース)では、このロジックを実装するのに最適な場所はRepository
です。これはRepository
、この種の検証を実行するために必要な追加のインフラストラクチャ(データストア)も "知っている" ため、特に便利です。あなたの場合、私はadd
メソッドにこのチェックを入れます。これは理にかなっていますか?概念的にはUser
、システムにを追加するのはこの方法です。データストアは実装の詳細です。