-アプリケーションでアプリケーションサービスを識別する方法を理解しようとしています。私は2つのことでドメインサービスを識別できると思います。
それで、私が現在取り組んでいるこの単純なユースケースについて考えました:
管理者は、特定のユーザーを禁止できる必要があります。操作をログに記録し、禁止されたユーザーにメールを送信する必要があります。
関数getUserById()
を持つUserRepository
があります。 ban()
関数を持つUser
エンティティがあります。
次のようにUserService
を作成します:
class UserService{
static void banUser(int userId){
User user= UserRepository.getUserById(userId);
user.ban();
UserRepository.update(user);
}
}
userId
はPOST
変数で、WebフォームからController
で受け取ります。
ここで、ロギングはどこに行きますか?操作exの前後に2回、禁止プロセスをログに記録する必要があります。
Logger.log("Attempting to ban user with id:"+userId);
//user gets banned
Logger.log("user banned successfully.");
次に、ユーザーにメールを送信する必要があります。電話はどこに行けばいいですか?
ロギングと電子メールを配置することはUserService
クラス自体であると考えましたが、もっと良い解決策があると思います。
3番目に、アプリケーションサービスは、これらすべてにどのように適合しますか?
ドメインサービスとアプリケーションサービス
ドメインサービスは、ドメイン内の他のエンティティまたは値オブジェクトに属さない動作を保持するクラスです。リポジトリとは関係ありません。 ユーザーのロールをモデル化する の場合、多くのドメインサービスがロール自体のメソッドになります。
代わりに、アプリケーションサービスは、ドメインを使用するために外部の世界で使用されるインターフェイスです。したがって、UserService
はアプリケーションサービスです。
技術的な副作用の取り扱い
このようなドメインイベントを処理するために 監視可能なエンティティ を使用します。
こちらです:
Banned
イベントを監視し、明示的なsave
呼び出しを必要とせずに永続化状態を更新できますUserService
は、ban()
コマンドが成功した場合にのみ、ログに記録してメールを送信するハンドラーでイベントをサブスクライブできます。class UserService{
public public UserService(IUserRepository repo, INotificationService notification)
{
this.UserRepository = repo;
this.Notification = notification;
}
public void BanUser(int userId){
User user= UserRepository.getUserById(userId);
user.ban();
Notification.NotifyBanned(user);
}
}
public interface IUserAuditTrail
{
void UserBanned(User user)
void AccountCreated(User user)
}
ここで、ロギングはどこに行きますか?
次に、ユーザーにメールを送信する必要があります。電話はどこに行けばいいですか?
ドメインイベントをお勧めします。 UserBanAttemptedEventとUserBannedEventの2つのイベントを作成します(過去の時間に注意してください)。
ロギングおよび電子メール通知のロジックはイベントハンドラーの内部にあります。2つのハンドラーUserBanAttemptedEventHandlerおよびUserBannedEventHandlerを作成します。
* payloadクラスは、UserIdなどの有用な情報を持つ単純なDTOです。このアプローチは、アプリケーションロジックをより適切に分離します。
void banUser(int userId){
DomainEvents.Raise<UserBanAttemptedEvent>(new UserBanAttemptedPayload())
User user= UserRepository.getUserById(userId);
user.ban();
UserRepository.update(user);
DomainEvents.Raise<UserBannedEvent>(new UserBannedPayload())
}
これらのパターンの実装には多くの例があります。
http://lostechies.com/jimmybogard/2014/05/13/a-better-domain-events-pattern/