私はDDDを学ぼうとしていますが、インフラストラクチャサービスの扱いに問題があります。
実際、私は彼らが何を目指しているのか理解していますが、私のアプリケーション内のどこに収まるのかわかりません。
実際、私は次のものを持っています
質問1使用するドメインサービスの役割(つまり、ドメインサービスに挿入されたインフラストラクチャサービス)か、(非常にシンプルな方法で)のようなものかと思っていました。
class UserDomainService {
constructor (userRepository, emailService) {
this.userRepository = userRepository
this.emailService = emailService
}
saveUser (user) {
/** Apply some business rules here ...*/
const user = this.userRepository.save(user)
this.emailService.send('New user added : ' + user.firstName)
}
}
または、次のように、アプリケーションサービスの役割である必要があります。
class ApplicationService {
constructor (userDomainService, userRepository, emailService) {
this.userDomainService = userDomainService
this.userRepository = userRepository
this.emailService = emailService
}
postUser (user) {
if (this.userDomainService.manageSomeRules(user)) {
this.userRepository.save(user)
this.emailService.send('New user added : ' + user.firstName)
return user
}
return new RuleNotSatisfied()
}
}
質問2
受信したユーザーをPOSTエンドポイント(REST API))から適切なエンティティに変換する責任は誰にありますか?
質問2の編集:エンティティをDTOに、またはその逆に変換できるサービスの種類を教えてください。どこに置けばいいですか?
インフラストラクチャサービスがドメインの概念(エンティティと値オブジェクト)を受け入れて返す場合、ドメインサービスがインフラストラクチャサービスを使用することは問題ありません。
さらに、ドメインサービスは、エンティティに適合できないビジネスロジックの一部をカプセル化する必要があります。したがって、saveUser
はドメインサービスに適した方法ではありません。
尋ねる質問は-メールを送信することは重要なドメイン概念ですか? Email
はドメインのエンティティですか?その場合、ドメインレイヤーで定義された電子メール送信者用のインターフェースがあり、インフラストラクチャレイヤーに分離された実装がある可能性があります。 、そしてドメインサービスで次のことを有意義に行うことができます-:
_sendEmailIfWhiteListed(id) {
Email = this.emailRepository.get(id);
if (email.isWhiteListed) {
this.emailSender.send(email);
}
}
_
ただし、これは、メールがドメイン内のエンティティである場合にのみ有効です。そうでない場合は、考えてみてください-なぜ電子メールの送信をユーザーを保存する責任にするのですか?
あなたの場合、メールはあなたのユビキタス言語のエンティティではないようです。したがって、ここでは ドメインイベントパターン を優先します。新しいユーザーを作成すると、ドメインイベントNewUserCreated
が発生します。また、アプリケーションレイヤーに配置するドメインイベントのハンドラーは、メール送信者に委任してメールを送信します。
投稿データを意味のあるエンティティに変換する責任は誰にありますか?それはあなたが何をしているのかに依存します:
new Entity()
を呼び出し、api data
引数からマップされた意味のあるドメイン引数(値オブジェクト)を渡すことができますthis.entityFactory.Create()
そして、api data
引数からマッピングされた意味のあるドメイン引数(値オブジェクト)を渡しますdata
の構造を認識してはなりません。これはAPIの問題であるためです。user.update
_のようなCRUDスタイルのメソッドは避けたいと思いますについて考えてくださいはユーザーデータが更新しました? DDDは、ビジネスプロセスと目的について考えることを奨励しています。user.UpdateProfile
_のようなエンティティメソッドで操作の目的を明示することをお勧めします。DDDは言語に関するすべてです。ドメインの専門家が使用する言語を聞き、ユビキタス言語に同意し、コードで忠実に使用します。ドメインエキスパートがpersist
またはsave
を言わない場合は、ドメインレイヤーでそれらの単語を使用しないでください。
最初の答えはDDDだと思います。ロジックをドメインオブジェクトに配置します。必要に応じてサービスを注入します。
着信メッセージをドメインオブジェクトに変換するための別の「ホスティングレイヤー」があります。
アプリケーション層は、ドメインオブジェクトを使用して必要な効果を実現します。
しかしながら。 DDDがサービスパターンにあまり適合しないと思います。私の考えでは、ロジックはドメインオブジェクトではなくサービスに属していることがよくあります。
つまりRecordPlayer.PlayRecord(record)
ではなくRecord.Play()
を使用します
さらに、これらのサービスの性質は、それらがステートレスであることです。私はレコードを再生し、結果を返し、すべてを破棄します。
一方、デスクトップアプリではDDDの方が優れています。いくつかのレコードをインスタンス化して、それらに対してさまざまな機能を実行する場合があります。棚から取得、再生、一時停止など。DDDスタイルのコードは、ユーザーのアクションと思考プロセスに一致します。 「このレコードを再生します」-> record.Play()