ドメインで「何か」が変更された場合は、ローカルドライブにフォルダを作成する必要があります。したがって、DDD方式では、イベントを発生させ、ドメインにフォルダーを作成させないようにする必要があります。
私の質問は、イベントが失敗した場合(つまり、フォルダーの作成が失敗した場合)はどうなりますか?
補正コマンドと呼ばれる最初の変更を元に戻すには、別のコマンドを再起動する必要がありますか?
また、補正コマンドが失敗した場合はどうなりますか?ドメインを変更しましたが、フォルダが存在しません。
ドメインで「何か」が変更された場合は、ローカルドライブにフォルダを作成する必要があります。したがって、DDD方式では、イベントを発生させ、ドメインにフォルダーを作成させないようにする必要があります。
私の質問は、イベントが失敗した場合(つまり、フォルダーの作成が失敗した場合)はどうなりますか?
補正コマンドと呼ばれる最初の変更を元に戻すには、別のコマンドを再起動する必要がありますか?
また、補正コマンドが失敗した場合はどうなりますか?ドメインを変更しましたが、フォルダが存在しません。
提案されたソリューションを説明する方法は、実際にはDDDではありません。状況を複雑にしすぎている可能性があるのは、より多くのCQRS(つまり、イベントと補正コマンド)です。
非同期操作を対象としたこのシナリオでは、本当にCQRSアプローチを採用する必要がありますか?のように、呼び出されて永続化されるビジネスロジックとは別のトランザクションで作成されるフォルダには、どのような利点がありますか?クエリサービスは別の物理マシン上にある可能性が高く、RPCが必要になるため、クエリサービスが処理するイベントを発生させる場合は、このアプローチに十分な理由があります。また、イベントでは、多くの非正規化テーブルを更新する必要がある場合があります。したがって、パフォーマンスのために、このプロセスで非同期イベントモデルを使用することは理にかなっています。しかし、ローカルフォルダを作成するために、それが行われるかどうかはわかりませんか?
可能なアプローチ
public class ApplicationService : IApplicationService
{
private readonly IMyAggregateRepository _myAggregateRepository;
private readonly IFolderCreationService _folderCreationService;
public ApplicationService(IMyAggregateRepository myAggregateRepository, IFolderCreationService folderCreationService)
{
_myAggregateRepository = myAggregateRepository;
_folderCreationService = folderCreationService;
}
public void SomeApplicationServiceMethod(Guid id)
{
using (IUnitOfWork unitOfWork = UnitOfWorkFactory.Create())
{
MyAggregate aggregate = _myAggregateRepository.GetById(id);
aggregate.SomeMethod();
_myAggregateRepository.Save(aggregate);
_folderCreationService.CreateFolder();
}
}
}
ここで、変更は、作業単位のusingステートメント内のすべてのコードがエラーなしで完了した場合にのみデータベースにコミットされます。
フォルダサービスを呼び出すのはドメインサービスまたはドメインエンティティではないことに注意してください...それはアプリケーションサービスです。私は、ドメインサービスを純粋なドメインロジックに集中させ続けることを好みます。ドメイン、データベース、およびこのフォルダサービスなどの他のインフラストラクチャサービスへのクライアント呼び出しを調整するのは、アプリケーションサービスの仕事です。
これがイベントモデルを使用する正当な理由があると判断した場合、あなたが言ったことは正しいです。イベントハンドラーでフォルダーの作成に失敗した場合は、補正コマンドを発行する必要があります。このハンドラーが設計上失敗しないようにする必要があります(つまり、問題のエンティティは常にこの補正コマンドを実行できる状態にあり、状態は元に戻ります)。すべてのシナリオをカバーする優れた単体テストがあると役立ちます。この補正コマンドを失敗させる設計上の欠陥がある場合は、失敗時に電子メール/通知を送信して手動で介入する必要があると思います。
PS質問のポイントではありませんが、本当に正当な理由がない限り、物理フォルダーを作成しないことを強くお勧めします。私の経験では、それは展開/マシンのアップグレードなどに頭痛の種を引き起こすだけです。明らかに、そうする理由はわかりませんが、代わりに保存する必要があるものには、ドキュメントストア/データベースを使用することをお勧めします。
ファイルシステムフォルダがドメインに不可欠である場合、ドメインサービスとしてフォルダの作成を実装します。そうすれば、エンティティにすべてのビジネスルールとロジックを処理させ、フォルダの作成に失敗しても、ドメインが無効な状態のままになることはありません。
ロジックを処理するメソッドにパラメーターとしてサービスを渡します(ダブルディスパッチパターン)。
フォルダサービスの例。
IFolderService
{
CreateFolder(string path);
}
エンティティの例。
class MyEntity
{
public void DoWork(IFolderService folderService, ...)
{
folderService.CreateFolder(...);
// do work.
}
}
作業が完了したら、ドメインイベントを発生させてサブシステムに通知できます。