web-dev-qa-db-ja.com

DDDを行う際のドメインサービスとアプリケーションサービスの識別

-アプリケーションでアプリケーションサービスを識別する方法を理解しようとしています。私は2つのことでドメインサービスを識別できると思います。

  1. リポジトリのファサードとして機能します。
  2. 単一のエンティティにカプセル化できないビジネスロジックを保持します。

それで、私が現在取り組んでいるこの単純なユースケースについて考えました:

管理者は、特定のユーザーを禁止できる必要があります。操作をログに記録し、禁止されたユーザーにメールを送信する必要があります。

関数getUserById()を持つUserRepositoryがあります。 ban()関数を持つUserエンティティがあります。
次のようにUserServiceを作成します:

class UserService{
    static void banUser(int userId){
          User user= UserRepository.getUserById(userId);
          user.ban();
          UserRepository.update(user);
    }
}

userIdPOST変数で、WebフォームからControllerで受け取ります。

ここで、ロギングはどこに行きますか?操作exの前後に2回、禁止プロセスをログに記録する必要があります。

Logger.log("Attempting to ban user with id:"+userId);
//user gets banned 
Logger.log("user banned successfully.");

次に、ユーザーにメールを送信する必要があります。電話はどこに行けばいいですか?

ロギングと電子メールを配置することはUserServiceクラス自体であると考えましたが、もっと良い解決策があると思います。

3番目に、アプリケーションサービスは、これらすべてにどのように適合しますか?

3
Songo

ドメインサービスとアプリケーションサービス
ドメインサービスは、ドメイン内の他のエンティティまたは値オブジェクトに属さない動作を保持するクラスです。リポジトリとは関係ありません。 ユーザーのロールをモデル化する の場合、多くのドメインサービスがロール自体のメソッドになります。

代わりに、アプリケーションサービスは、ドメインを使用するために外部の世界で使用されるインターフェイスです。したがって、UserServiceはアプリケーションサービスです。

技術的な副作用の取り扱い
このようなドメインイベントを処理するために 監視可能なエンティティ を使用します。

こちらです:

  • リポジトリはBannedイベントを監視し、明示的なsave呼び出しを必要とせずに永続化状態を更新できます
  • UserServiceは、ban()コマンドが成功した場合にのみ、ログに記録してメールを送信するハンドラーでイベントをサブスクライブできます。
3
Giacomo Tesio
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)
}
3
Piotr Perak

ここで、ロギングはどこに行きますか?

次に、ユーザーにメールを送信する必要があります。電話はどこに行けばいいですか?

ドメインイベントをお勧めします。 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/

DDDSample.Net

0
Eldar