(1) サービス層関数/ジョブ/タスク/作業単位は、ファクトリまたはエンティティ インスタンスまたは DomainService 関数の動作メソッドを呼び出しますか? これらのコンポーネントの責任に基づくコール スタックについてはわかりません。
通常 - トップレベルは必要な集約ルートを取得し、その上で関数を呼び出します。トップ レベルが複数の集約ルートを取得してドメイン サービスに渡すこともありますが、ドメイン サービスは、認識されていない集約ルートがあることを示す非常に強力な兆候であるため、そうではありません。最後に - 最上位レベルにより、集約ルートが永続化されます。
(2) Entity インスタンスには、上記のような「動作メソッド」もありますか? たとえば、Post には p.UpdatePost(string bodyText) がありますか、それともドメイン モデルの問題ではないので、リポジトリでも同じことを達成する必要がありますか? または、サービス層の機能です。この場合、リポジトリを呼び出す必要があり、エンティティ インスタンスには、永続性ではなくドメインに固有の動作メソッドが含まれているだけですか? しかし、それがユーザーの目的であるのに、なぜ「投稿の更新」がドメイン機能のように聞こえるのでしょうか?
はい、彼らがやります。ドメイン モデルは、その状態の変化を認識する必要があります。そして、それは最初に思われるよりもはるかに有益です。これの素晴らしい点は、拡張性ポイントを獲得できることです。クライアントが 1 週間後にあなたのところに来て、ユーザーが投稿を更新するときにシステムに追加の項目をチェックしてほしいと言った場合post.bodyText="new value"
、post.UpdatePost
.
一方、CRUD はドメイン駆動設計と相互に排他的ではありません。たとえば、私のアプリケーションでは、ユーザーとそのロールの管理は面白くないので、詳細にモデル化しようとさえしていません。ビジネスで重要な部分を認識する必要があるのは、アプリケーションが記述し、使用している部分です。
ドメイン駆動設計は、複雑なアプリケーションに対してのみ意味があることに注意してください。単純なブログ アプリケーションでは必要ありません。
(3) サービス層 (ドメイン サービスではない) がインターフェイスがドメイン層と対話する方法をカプセル化する必要があると仮定するのは間違っていますか?
私が見ているように、アプリケーション サービスはインフラストラクチャを調整するためのものです。インフラストラクチャが関与していない場合、アプリケーション サービスは価値を失います。
アプリケーション サービスは、基本的に単なるファサードです。そして、複雑さが追加され、それが解決する問題を過大評価する場合、すべてのファサードは良くありません。
内部ドメイン:
//aggregate root is persistence ignorant.
//it shouldn't reference repository directly
public class Customer{
public string Name {get; private set;}
public static Customer Register(string name){
return new Customer(name);
}
protected Customer(string name){
//here it's aware of state changes.
//aggregate root changes it's own state
//instead of having state changed from outside
//through public properties
this.Name=name;
}
}
//domain model contains abstraction of persistence
public interface ICustomerRepository{
void Save(Customer customer);
}
ドメイン外:
public class CustomerRepository:ICustomerRepository{
//here we actually save state of customer into database/cloud/xml/whatever
public void Save(Customer customer){
//note that we do not change state of customer, we just persist it here
_voodoo.StoreItSomehow(customer);
}
}
//asp.net mvc controller
public class CustomerController{
public CustomerController(ICustomerRepository repository){
if (repository==null)throw new ArgumentNullException();
_repository=repository;
}
public ActionResult Register(string name){
var customer=Customer.Register(name);
_repository.Save(customer);
}
}