Version 1. Dependency Injection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class User(id: Int) | |
trait NotificationService { | |
def notifyUserAboutSth(user: User): Unit | |
} | |
trait UserRepository { | |
def find(id: Int): Option[User] | |
} | |
class UserService( | |
repository: UserRepository, | |
notificationService: NotificationService) { | |
def notifyUser(userId: Int): Unit = repository.find(userId) match { | |
case Some(foundUser) ⇒ notificationService.notifyUserAboutSth(foundUser) | |
case None ⇒ println("No user found!") | |
} | |
} |
Version 2. Higher order function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class Context(userRepository: UserRepository, notificationService: NotificationService) | |
object UserService { | |
def notifyUser(userId: Int): Context ⇒ Unit = context ⇒ | |
context.userRepository.find(userId) match { | |
case Some(foundUser) ⇒ context.notificationService.notifyUserAboutSth(foundUser) | |
case None ⇒ println("No user found!") | |
} | |
} | |
//build up the computation | |
val notify: Context => Unit = UserService.notifyUser(joe) | |
//fire the side-effects | |
notify(context) |
Version 3. Reader Monad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class Reader[R, A](run: R ⇒ A) { | |
def map[B](f: A ⇒ B): Reader[R, B] = Reader(r ⇒ f(run(r))) | |
def flatMap[B](f: A ⇒ Reader[R, B]): Reader[R, B] = Reader(r ⇒ f(run(r)).run(r)) | |
} | |
object UserService { | |
def notifyUser(user: User): Reader[Context, Unit] = Reader { context ⇒ | |
context.userRepository.find(user.id) match { | |
case Some(foundUser) ⇒ context.notificationService.notifyUserAboutSth(foundUser) | |
case None ⇒ println("No user found!") | |
} | |
} | |
} | |
//build up the computation | |
val notify: Reader[Context, Unit] = UserService.notifyUser(joe) | |
//fire the side-effects | |
notify.run(context) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait AccountService { | |
def credit(userId: Int, amount: Int): Reader[Context, Unit] | |
def debit(userId: Int, amount: Int): Reader[Context, Unit] | |
} | |
val service: AccountService = ??? | |
val transfer: Reader[Context, Unit] = for { | |
_ ← service.credit(1, 10) | |
_ ← service.debit(2, 10) | |
} yield () | |
//fire the side-effects | |
transfer.run(context) |
Note that inside the for comprehension the context doesn't even appear.
No comments :
Post a Comment