Skip to content

Instantly share code, notes, and snippets.

@seanparsons
Created March 19, 2012 22:27
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 seanparsons/2127688 to your computer and use it in GitHub Desktop.
Save seanparsons/2127688 to your computer and use it in GitHub Desktop.
How I see the difference between functional and object oriented decomposition.
import scalaz._
import Scalaz._
import scalaz.effects._
// Given this chunk of code that represents a primitive database storing a user.
case class User(id: Int, name: String)
object Database {
var user: User = null
}
// OO Decomposition.
case class UserRepository() {
def loadUser(id: Int): User = Database.user
def saveUser(user: User): Unit = {
Database.user = user
}
}
case class UserManager(userRepository: UserRepository) {
def updateName(id: Int, newName: String) {
val user = userRepository.loadUser(id)
val updatedUser = user.copy(name = newName)
userRepository.saveUser(updatedUser)
}
}
Database.user = new User(1, "Sen") // Setup code only.
// Updating the user and then re-loading their details:
val userRepository = new UserRepository()
val userManager = new UserManager(userRepository)
userManager.updateName(1, "Sean")
println(userRepository.loadUser(1))
// Functional decomposition with added use of the IO monad.
def loadUser(id: Int): IO[User] = io(Database.user)
def saveUser(user: User): IO[Unit] = io(Database.user = user)
def updateName(id: Int, newName: String): IO[Unit] = {
for {
user <- loadUser(id)
updatedUser <- io(user.copy(name = newName))
saved <- saveUser(updatedUser)
} yield saved
}
Database.user = new User(1, "Sen") // Setup code only.
// Updating the user and then re-loading their details:
val userIO = for {
_ <- updateName(1, "Sean")
loadedUser <- loadUser(1)
} yield loadedUser
println(userIO.unsafePerformIO)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment