画像に関連する 2 つの異なる「アクション」があります。「物理的」プロセスと「論理的」プロセスがあります。イメージはドメインの一部であるため、論理プロセスはイメージに関する情報をドメイン リポジトリに永続化します。追加 (および削除) の物理プロセスは、論理プロセスの前提条件です。
一歩後退すると、物理プロセスは論理プロセスから完全に独立していますが、その逆は当てはまりません。画像が保存されていない場合、(ドメイン内の) 画像に関するメタ情報を保持したくないことは明らかです。また、物理ファイルを削除できない場合は、ドメインから情報を削除したくありません。
ドメインには、イメージの論理インスタンスをデータソースから削除するために必要な情報が含まれている必要があります。ドメインは、物理的に独立したアプリケーションと考えてください。この場合、ドメインは、保持しているデータが物理ファイルと関係があることを実際には認識していません。必ずこのようにしてください。
通常、エンティティはアセンブリにあり、リポジトリとドメイン サービスは別のアセンブリにあります。アプリケーション サービスはドメイン モデルの外に存在しますが、ドメイン モデルを活用して作業を行います。そのため、アプリケーション サービスは 1 つまたはドメイン サービスを使用するか、他のアプリケーション サービスを使用し、ドメイン サービスは 1 つまたは複数のリポジトリを使用できます。
これを念頭に置いて、実際の削除ロジックには 2 つの場所があり、それらを調整するための 3 つ目の場所があります。これが私がそれをしていた場合の仕組みです。ドメイン サービスは、基になるデータソースからの論理的な削除 (および必要な検索も) のためにリポジトリを利用します。ドメイン オブジェクト インスタンスの操作以外は認識しません。また、物理インスタンスの削除を具体的に処理するアプリケーション サービス (ドメイン外) も用意します。議論のために、ドメイン リポジトリとドメイン サービスをそれぞれ含む「ImageRepository」クラスと「ImageServices」クラスがあると仮定します。ImageServices には、使用している Find() メソッドだけでなく、Delete() メソッドも必要です。
物理インスタンスを削除できなかった場合は、論理インスタンスを削除したくないため、物理イメージの削除操作の成功を測定する手段があることを確認してください。この場合、おそらくある種のカスタム例外を使用します(ファイルの削除は、一般的に失敗しない標準操作であると考えているためです)。これは通常、「管理」の領域に当てはまります。したがって、通常、「ImageManagementService」のような名前のアプリケーション サービスがあります。簡単にするために、このサービスは (ドメインではなくアプリケーションの一部であるため) 物理的な削除を行うプライベート メソッドを持つことができます。「DeleteImageFile()」としましょう。
3つ目は、この2つの操作を連携させたもので、これもアプリケーションサービスです。これを「ImageManagementService」のパブリック メソッドにするだけです。これを「RemoveImage」と呼ぶことができます。このアプリケーション サービスは、次のことを行います。
- ドメイン サービスからインスタンス情報を取得します (リポジトリへのパススルー コール)。
- インスタンス情報を使用して、物理ファイルを見つけて削除します (最初に言及したアプリケーション サービス)。
- 物理的な削除が成功した場合は、インスタンスを削除します (ドメイン サービスに戻り、リポジトリを再びファサードします)。
したがって、アプリケーション自体が「ImageManagementService」インスタンスから「RemoveImage()」メソッドを呼び出します。内部的には、"RemoveImage()" は最初にドメインの "ImageServices" から "FindBy..()" を呼び出して、ドメインからインスタンスを取得します。そこからファイルパスを使用して、「ImageManagementService」インスタンスのプライベートな「DeleteImageFile()」メソッドを呼び出します。成功すると、ファサードとして機能しているドメインの「ImageService」の「Delete()」メソッドを呼び出します。あなたのリポジトリに。
この場合、懸念の分離に焦点を当てることが非常に重要だと思います。なぜなら、明示的な分離 (さまざまなアセンブリで実行できる) があれば、どの種類のロジックをどの場所に配置できるかを理解できるようになるからです。エヴァンの本を強くお勧めします。また、DDD に関連する SOC の概念を簡単に理解するには、「オニオン アーキテクチャ」に関する Jeffrey Palermo の 3 回シリーズを参照することをお勧めします。
アプリケーション サービスからリポジトリを直接呼び出すのではなく、ドメイン サービスを使用する理由について、いくつかの注意事項があります。主に、リポジトリのインスタンス化はドメイン サービスよりも複雑です。これはほとんどがファサードですが、ドメイン内の他のどこにも収まらない追加のロジックが含まれている可能性があることを覚えておいてください。これの良い例は、一意のファイル名を強制したい場合です。ドメイン オブジェクト自体は、他の集約内の他のドメイン オブジェクトを直接認識していないため、ドメイン サービスは、保存操作の前に同じ名前の既存のインスタンスをチェックする場合があります。とても便利です。また、ドメイン サービスは単一のリポジトリに限定されません。複数のリポジトリ間でドメイン サービスを調整することができます。集計が重複している場合は、関連する 2 つの集約ルートで同時に作業を呼び出す必要がある場合があります。ドメイン サービスでこれを行うことができ、そのようなロジックをドメインに保持し、アプリケーションに影響を与えることはありません。
お役に立てれば。これを行う方法は他にもあると確信していますが、これは、同様のシナリオで自分のアプリケーションで成功を収めた方法です。