私は現在、.net と nhibernate を使用して、旅行業界のクライアント向けにかなり大規模なアプリケーションをいくつか開発しており、DDD の実装に関するいくつかの問題と、進行する最善の方法についてチーム内での意見の相違に直面しています。誰かが何らかのガイダンスを提供できることを願っています。
現時点では、集約ルート ([EntityName]Service) ごとにサービスを使用して、ドメインの外部にサービス レイヤーを実装しています。他のすべてのレイヤーは、これらのサービスを使用して、GetByThis() や GetByTheOther() などのメソッドを介して集約ルートへの参照を取得します。他のレイヤーからドメインへのすべての呼び出しは、これらのサービスを介して行われます。
サービスは、リポジトリへの挿入された参照 (他の場所では参照されない) を保持し、すべての保存/更新動作とトランザクションの管理も担当します。サービスメソッドは複雑さを増しており、条件付き作成ロジックのように、ドメインに属しているように見える動作をすることがあります (プロパティ = this の場合は子オブジェクトを何かに設定し、そうでない場合は別のものに設定します)。私たちのドメイン エンティティには、ほとんどが GetByThis() や HasAThing() などの単純なメソッドがあります。ドメインの表現力が失われているように感じます。
私の主な問題は次のとおりです。
- サービス層にそれほど多くのロジックを含める必要がありますか? そうでない場合、どこに行くべきですか?ドメインの場合、集約ルートはリポジトリへの参照を保持する必要がありますか? はいの場合、これらはどのように注入されますか (集約ルートを作成するファクトリに?)
- トランザクション性をどのように処理する必要がありますか?
- エンティティ (または集約ルート) はドメイン サービスへの参照を保持する必要がありますか? もしそうなら、彼らはどのように参照を取得する必要がありますか?
- エンティティの新しい ID を取得するには、リポジトリにラップしたストアド プロシージャを呼び出す必要があります。これをどこで参照しますか?多くの子エンティティを作成する必要があるエンティティのいくつかの複雑なメソッドは、これを参照する必要がありますか?
編集
@david-masters と @guillaume31 のよく考えられた回答に感謝します。
あなたは、私が感じていた「臭いコード」の感覚を解決するのを助けてくれました。
まず、対処すべき (非常に) レガシーな Oracle DB があると言うべきだったので、(他の問題の中でも) ID 生成の要件があります。
これを見た他の人にとっては、どちらの回答も優れたアドバイスを与えてくれましたが、私にとっては、これが最良のアドバイスでした。
「実用的な観点から、私が自問することは次のとおりです。ドメイン層の一部を取得して別のアプリケーションで再利用したい場合、その新しいアプリケーションでドメインを活用するために必要なすべてのビジネス ルールと動作が含まれているでしょうか。 ? そうでない場合は、現在アプリケーション側にある一部の部分をドメイン層に移動する必要があることを意味している可能性があります。」</p>
これを念頭に置いてドメインとサービス層を再評価し、設計上の問題を解決したと確信しています。