Skip to content

Instantly share code, notes, and snippets.

@rinotc
Last active March 12, 2023 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rinotc/478b57fa8b64b7b01102ec282725d70e to your computer and use it in GitHub Desktop.
Save rinotc/478b57fa8b64b7b01102ec282725d70e to your computer and use it in GitHub Desktop.
よくあるドメインサービスの実装
trait UserEmailUniqueChecker extends DomainService {
/**
* 引数のメールアドレスがユニークであるかどうかを調べる
*/
def check(email: EmailAddress): Boolean
}
final class User private (
val id: UserId,
val name: Option[String],
val email: EmailAddress
) extends Entity[UserId]
with Aggregate {
/**
* メールアドレスを変更する
*/
def changeEmail(email: EmailAddress): User = copy(email = email)
}
/** メールアドレス変更ユースケースの入力 **/
case class ChangeEmailInput(userId: UserId, email: EamilAddress)
/** メールアドレス変更ユースケースの出力 **/
sealed abstract class ChangeEmailOutput
object ChangeEmailOutput {
/** メールアドレスの変更に成功した **/
case class Success(user: User) extends ChangeEmailOutput
/** 入力で渡されたユーザーIDのユーザーが見つからなかった **/
case class NotFoundUser(userId: UserId) extends ChangeEmailOutput
/** メールアドレスがユニークではなかった **/
case class EmailIsNotUnique(email: EmailAddress) extends ChangeEmailOutput
}
class ChangeEmailUseCase @Inject() (
userEmailUniqueChecker: UserEmailUniqueChecker,
userRepository: UserRepository
) {
import ChangeEmailOutput._
def handle(input: ChangeEmailInput): ChangeEmailOutput = {
val result = for {
// 更新対象のユーザーを取得する
user <- userRepository.findById(input.userId).toRight(NotFoundUser(input.userId))
// 引数のメールアドレスがユニークかどうか?
_ <- Either.cond(userEmailUniqueChecker.check(input.email), (), EmailIsNotUnique(input.email))
} yield {
// ドメインモデルの状態を更新する
emailChangedUser = user.changeEmail(input.email)
// 永続化する
userRepository.update(emailChangedUser)
// 成功したと返す
Success(emailChangedUser)
}
// Either[ChangeEmailOutput, ChangeEmailOutput] になってるのでunwrapする
result.merge
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment